From b6416b15dac3a638d803681fbad8746b1808b6aa Mon Sep 17 00:00:00 2001 From: Adam Dobrowolski Date: Tue, 30 Mar 2021 15:46:52 +0200 Subject: [PATCH] [EGD-6019] Minimum settings ownership lifetime fixups added weakptr link to settings and checks it wont crash on deinitialized setings now Pseuto UT are passing Added: - deregistration on Settings destrution - weak referencing of Service to not crash Settings on missuse - Proxy as initialization parameter to Settings Unused code removed Enabled tests to be written for Settings --- enabled_unittests | 10 + module-apps/Application.cpp | 5 +- .../ApplicationDesktop.cpp | 2 - .../ApplicationSettings.cpp | 2 +- .../models/FactoryData.cpp | 14 +- .../models/FactoryData.hpp | 4 +- .../model/ApplicationManager.cpp | 5 +- .../service-audio/ServiceAudio.cpp | 4 +- .../service-bluetooth/ServiceBluetooth.cpp | 9 +- .../service-bluetooth/SettingsHolder.cpp | 5 + .../service-bluetooth/SettingsHolder.hpp | 1 + .../service-cellular/ServiceCellular.cpp | 28 +- module-services/service-db/CMakeLists.txt | 1 + module-services/service-db/EntryPath.cpp | 20 +- .../service-db/agents/settings/Settings.cpp | 261 ++++-------------- .../agents/settings/SettingsAgent.cpp | 255 ----------------- .../agents/settings/SettingsAgent.hpp | 30 -- .../agents/settings/SettingsCache.cpp | 54 +++- .../agents/settings/SettingsProxy.cpp | 81 ++++++ .../service-db/service-db/EntryPath.hpp | 30 ++ .../service-db/service-db/Settings.hpp | 57 +--- .../service-db/service-db/SettingsCache.hpp | 8 +- .../service-db/SettingsMessages.hpp | 232 +--------------- .../service-db/service-db/SettingsProxy.hpp | 30 ++ .../service-db/test/CMakeLists.txt | 1 + .../test-service-db-settings-messages.cpp | 48 +--- .../test-settings-Settings/CMakeLists.txt | 17 ++ .../test/test-settings-Settings/main.cpp | 5 + .../test-settings-Interface.cpp | 72 +++++ .../test-settings-Settings.cpp | 91 ++++++ .../test/test-settings/CMakeLists.txt | 2 - .../test-service-db-settings-api.cpp | 149 ++++------ .../test-service-db-settings-testapps.hpp | 89 +++--- .../test-service-db-settings-testservices.hpp | 119 +------- .../service-desktop/ServiceDesktop.cpp | 7 +- .../developerMode/DeveloperModeHelper.cpp | 1 + .../service-evtmgr/EventManager.cpp | 16 +- .../service-evtmgr/EventManager.hpp | 2 +- module-sys/Service/Common.hpp | 1 - module-sys/Service/Service.hpp | 14 +- module-sys/Service/ServiceForward.hpp | 20 ++ module-sys/Service/ServiceProxy.hpp | 46 +++ module-utils/Split.hpp | 51 ++++ module-utils/Utils.hpp | 43 +-- 44 files changed, 772 insertions(+), 1170 deletions(-) create mode 100644 module-services/service-db/agents/settings/SettingsProxy.cpp create mode 100644 module-services/service-db/service-db/EntryPath.hpp create mode 100644 module-services/service-db/service-db/SettingsProxy.hpp create mode 100644 module-services/service-db/test/test-settings-Settings/CMakeLists.txt create mode 100644 module-services/service-db/test/test-settings-Settings/main.cpp create mode 100644 module-services/service-db/test/test-settings-Settings/test-settings-Interface.cpp create mode 100644 module-services/service-db/test/test-settings-Settings/test-settings-Settings.cpp create mode 100644 module-sys/Service/ServiceForward.hpp create mode 100644 module-sys/Service/ServiceProxy.hpp create mode 100644 module-utils/Split.hpp diff --git a/enabled_unittests b/enabled_unittests index b04e527a1bbadb44aaac2ce9f59bca7aacfd7690..ffd8eb7e81d9e52728dca134de6833cf4b883020 100644 --- a/enabled_unittests +++ b/enabled_unittests @@ -479,5 +479,15 @@ TESTS_LIST["catch2-unittest_CellularResult"]=" CellularResult; " #--------- +TESTS_LIST["catch2-settings-Settings"]=" + Settings - not initialized; + Settings - initialized; + Interface - not initialized; + Interface - initialized; + Interface - expired; + Interface - copied; +" +#--------- + diff --git a/module-apps/Application.cpp b/module-apps/Application.cpp index 2bbb77a23662b27e2730b2315a0931ac03bdde47..cd8f526d1f80028c7e0a796cb43ba2445d2d49d7 100644 --- a/module-apps/Application.cpp +++ b/module-apps/Application.cpp @@ -102,7 +102,7 @@ namespace app default_window(gui::name::window::main_window), windowsStack(this), keyTranslator{std::make_unique()}, startInBackground{startInBackground}, callbackStorage{std::make_unique()}, topBarManager{std::make_unique()}, - settings(std::make_unique(this)), phoneMode{mode}, phoneLockSubject(this) + settings(std::make_unique()), phoneMode{mode}, phoneLockSubject(this) { topBarManager->enableIndicators({gui::top_bar::Indicator::Time}); using TimeMode = gui::top_bar::TimeConfiguration::TimeMode; @@ -154,7 +154,6 @@ namespace app Application::~Application() noexcept { windowsStack.windows.clear(); - settings->unregisterValueChange(); } Application::State Application::getState() @@ -621,6 +620,7 @@ namespace app { setState(State::INITIALIZING); + settings->init(service::ServiceProxy(shared_from_this())); app::manager::Controller::applicationInitialised(this, StartupStatus::Success, startInBackground); if (startInBackground) { @@ -638,6 +638,7 @@ namespace app sys::ReturnCodes Application::DeinitHandler() { + settings->deinit(); LOG_INFO("Closing an application: %s", GetName().c_str()); for (const auto &[windowName, window] : windowsStack) { diff --git a/module-apps/application-desktop/ApplicationDesktop.cpp b/module-apps/application-desktop/ApplicationDesktop.cpp index bd24b1b355c9bb606080cd158caacea508b1ef5f..44ceae00f8055fc0849bb2f7a9436c2a80658d81 100644 --- a/module-apps/application-desktop/ApplicationDesktop.cpp +++ b/module-apps/application-desktop/ApplicationDesktop.cpp @@ -383,8 +383,6 @@ namespace app sys::ReturnCodes ApplicationDesktop::DeinitHandler() { - LOG_INFO("DeinitHandler"); - settings->unregisterValueChange(); return sys::ReturnCodes::Success; } diff --git a/module-apps/application-settings-new/ApplicationSettings.cpp b/module-apps/application-settings-new/ApplicationSettings.cpp index 8300e1c0c924c07e8895cd4eec53d690ad94117b..5aa82d09e22312e7784c58ff0e74841283da3159 100644 --- a/module-apps/application-settings-new/ApplicationSettings.cpp +++ b/module-apps/application-settings-new/ApplicationSettings.cpp @@ -460,7 +460,7 @@ namespace app return std::make_unique(app); }); windowsFactory.attach(gui::window::name::technical_information, [&](Application *app, const std::string &name) { - auto factoryData = std::make_unique(std::make_unique<::settings::Settings>(this)); + auto factoryData = std::make_unique(*settings); auto presenter = std::make_unique(std::move(factoryData)); return std::make_unique(app, std::move(presenter)); }); diff --git a/module-apps/application-settings-new/models/FactoryData.cpp b/module-apps/application-settings-new/models/FactoryData.cpp index 105b6efd4f10495f4cdd0b37d6f0ff38a7797c35..628e80b888bbcb0cb5ed3e1ffc42eb3b2613827d 100644 --- a/module-apps/application-settings-new/models/FactoryData.cpp +++ b/module-apps/application-settings-new/models/FactoryData.cpp @@ -5,28 +5,28 @@ #include #include -FactoryData::FactoryData(std::unique_ptr settingsProvider) : settings(std::move(settingsProvider)) +FactoryData::FactoryData(settings::Settings &settings) : settings(settings) {} auto FactoryData::getModel() -> std::string { - return settings->getValue(settings::factory::entry_key + std::string("/model"), settings::SettingsScope::Global); + return settings.getValue(settings::factory::entry_key + std::string("/model"), settings::SettingsScope::Global); } auto FactoryData::getCase() -> std::string { - return settings->getValue(settings::factory::entry_key + std::string("/case"), ::settings::SettingsScope::Global); + return settings.getValue(settings::factory::entry_key + std::string("/case"), ::settings::SettingsScope::Global); } auto FactoryData::getSerial() -> std::string { - return settings->getValue(settings::factory::entry_key + std::string("/serial"), settings::SettingsScope::Global); + return settings.getValue(settings::factory::entry_key + std::string("/serial"), settings::SettingsScope::Global); } auto FactoryData::getBatteryRev() -> std::string { - return settings->getValue(settings::factory::entry_key + std::string("/battery_revision"), - settings::SettingsScope::Global); + return settings.getValue(settings::factory::entry_key + std::string("/battery_revision"), + settings::SettingsScope::Global); } auto FactoryData::getPcb(std::string type) -> std::string { std::string full_pcb = "/pcb_" + type + "_version"; - return settings->getValue(settings::factory::entry_key + full_pcb, settings::SettingsScope::Global); + return settings.getValue(settings::factory::entry_key + full_pcb, settings::SettingsScope::Global); } diff --git a/module-apps/application-settings-new/models/FactoryData.hpp b/module-apps/application-settings-new/models/FactoryData.hpp index f21f0393a514c20b38d98fe7abf345701e0a4276..87b6a4140b685be98184044857ca0d621a3b24a4 100644 --- a/module-apps/application-settings-new/models/FactoryData.hpp +++ b/module-apps/application-settings-new/models/FactoryData.hpp @@ -20,7 +20,7 @@ class AbstractFactoryData class FactoryData : public AbstractFactoryData { public: - explicit FactoryData(std::unique_ptr settings); + explicit FactoryData(settings::Settings &settings); auto getModel() -> std::string override; auto getCase() -> std::string override; @@ -29,5 +29,5 @@ class FactoryData : public AbstractFactoryData auto getPcb(std::string type) -> std::string override; private: - std::unique_ptr settings; + settings::Settings &settings; }; diff --git a/module-services/service-appmgr/model/ApplicationManager.cpp b/module-services/service-appmgr/model/ApplicationManager.cpp index 6499ec60cd0ab699b60fdd340290117a9112d18e..7650955374b2fe3233ba5b3eec4924c2b03e14a9 100644 --- a/module-services/service-appmgr/model/ApplicationManager.cpp +++ b/module-services/service-appmgr/model/ApplicationManager.cpp @@ -134,7 +134,7 @@ namespace app::manager : Service{serviceName, {}, ApplicationManagerStackDepth}, ApplicationManagerBase(std::move(launchers)), rootApplicationName{_rootApplicationName}, actionsRegistry{[this](ActionEntry &action) { return handleAction(action); }}, notificationProvider(this), - autoLockEnabled(false), settings(std::make_unique(this)), + autoLockEnabled(false), settings(std::make_unique()), phoneModeObserver(std::make_unique()), phoneLockHandler(locks::PhoneLockHandler(this)) { @@ -148,6 +148,7 @@ namespace app::manager sys::ReturnCodes ApplicationManager::InitHandler() { + settings->init(service::ServiceProxy(shared_from_this())); utils::setDisplayLanguage( settings->getValue(settings::SystemProperties::displayLanguage, settings::SettingsScope::Global)); @@ -259,7 +260,7 @@ namespace app::manager sys::ReturnCodes ApplicationManager::DeinitHandler() { - settings->unregisterValueChange(); + settings->deinit(); closeApplications(); return sys::ReturnCodes::Success; } diff --git a/module-services/service-audio/ServiceAudio.cpp b/module-services/service-audio/ServiceAudio.cpp index 27c9f02268edfa6e89aec6d32d86601a91d3b747..b496a1144fd0b2c9a80a6c3ec61d64fb687b9fcb 100644 --- a/module-services/service-audio/ServiceAudio.cpp +++ b/module-services/service-audio/ServiceAudio.cpp @@ -94,7 +94,7 @@ static constexpr std::initializer_listAudioServicesCallback(params...); }), - settingsProvider(std::make_unique(this)) + settingsProvider(std::make_unique()) { LOG_INFO("[ServiceAudio] Initializing"); bus.channels.push_back(sys::BusChannel::ServiceAudioNotifications); @@ -110,6 +110,7 @@ ServiceAudio::~ServiceAudio() sys::ReturnCodes ServiceAudio::InitHandler() { + settingsProvider->init(service::ServiceProxy(shared_from_this())); std::transform(std::begin(cacheInitializer), std::end(cacheInitializer), std::inserter(settingsCache, std::end(settingsCache)), @@ -125,6 +126,7 @@ sys::ReturnCodes ServiceAudio::InitHandler() sys::ReturnCodes ServiceAudio::DeinitHandler() { + settingsProvider->deinit(); return sys::ReturnCodes::Success; } diff --git a/module-services/service-bluetooth/ServiceBluetooth.cpp b/module-services/service-bluetooth/ServiceBluetooth.cpp index 840974861cb5e09ee343c453c133d2c4de2d8cda..03b20c7180fc3a06d2f5fd76c8a873e781cbe0de 100644 --- a/module-services/service-bluetooth/ServiceBluetooth.cpp +++ b/module-services/service-bluetooth/ServiceBluetooth.cpp @@ -45,9 +45,6 @@ namespace ServiceBluetooth::ServiceBluetooth() : sys::Service(service::name::bluetooth, "", BluetoothServiceStackDepth) { - auto settings = std::make_unique(this); - settingsHolder = std::make_shared(std::move(settings)); - bluetooth::KeyStorage::settings = settingsHolder; LOG_INFO("[ServiceBluetooth] Initializing"); } @@ -60,6 +57,11 @@ ServiceBluetooth::~ServiceBluetooth() // this means it is an init point of bluetooth feature handling sys::ReturnCodes ServiceBluetooth::InitHandler() { + auto settings = std::make_unique(); + settings->init(service::ServiceProxy(shared_from_this())); + settingsHolder = std::make_shared(std::move(settings)); + bluetooth::KeyStorage::settings = settingsHolder; + worker = std::make_unique(this); worker->run(); @@ -105,6 +107,7 @@ sys::ReturnCodes ServiceBluetooth::InitHandler() sys::ReturnCodes ServiceBluetooth::DeinitHandler() { + settingsHolder->deinit(); worker->deinit(); return sys::ReturnCodes::Success; } diff --git a/module-services/service-bluetooth/service-bluetooth/SettingsHolder.cpp b/module-services/service-bluetooth/service-bluetooth/SettingsHolder.cpp index 61b2b77e6884a32b2de2323e0778e86cc212751a..5b446d7768ca81010c72d3164599e1c2ac3ef1af 100644 --- a/module-services/service-bluetooth/service-bluetooth/SettingsHolder.cpp +++ b/module-services/service-bluetooth/service-bluetooth/SettingsHolder.cpp @@ -53,4 +53,9 @@ namespace bluetooth } }); } + + void SettingsHolder::deinit() + { + settingsProvider->deinit(); + } } // namespace Bluetooth diff --git a/module-services/service-bluetooth/service-bluetooth/SettingsHolder.hpp b/module-services/service-bluetooth/service-bluetooth/SettingsHolder.hpp index f0c9836e1f3b78dd6808ab3fdd256e11ffa59d91..7e16382728de169db4e3eda47d09554a6fbbee8c 100644 --- a/module-services/service-bluetooth/service-bluetooth/SettingsHolder.hpp +++ b/module-services/service-bluetooth/service-bluetooth/SettingsHolder.hpp @@ -84,6 +84,7 @@ namespace bluetooth void setValue(const Settings &newSetting, const SettingEntry &value); std::function onStateChange; std::function onLinkKeyAdded; + void deinit(); private: static std::map settingString; diff --git a/module-services/service-cellular/ServiceCellular.cpp b/module-services/service-cellular/ServiceCellular.cpp index 96456e5137d937ec39e9110ba979ad1e937ba4aa..4a1bc705ab97e8a3590a669acb87a7311223434e 100644 --- a/module-services/service-cellular/ServiceCellular.cpp +++ b/module-services/service-cellular/ServiceCellular.cpp @@ -180,15 +180,6 @@ ServiceCellular::ServiceCellular() bus.channels.push_back(sys::BusChannel::ServiceEvtmgrNotifications); bus.channels.push_back(sys::BusChannel::PhoneModeChanges); - settings = std::make_unique(this); - - connectionManager = std::make_unique( - utils::getNumericValue( - settings->getValue(settings::Cellular::offlineMode, settings::SettingsScope::Global)), - static_cast(utils::getNumericValue(settings->getValue( - settings->getValue(settings::Offline::connectionFrequency, settings::SettingsScope::Global)))), - std::make_shared(*this)); - callStateTimer = sys::TimerFactory::createPeriodicTimer( this, "call_state", std::chrono::milliseconds{1000}, [this](sys::Timer &) { CallStateTimerHandler(); }); stateTimer = sys::TimerFactory::createPeriodicTimer( @@ -201,7 +192,10 @@ ServiceCellular::ServiceCellular() sys::TimerFactory::createPeriodicTimer(this, "connection", std::chrono::seconds{60}, [this](sys::Timer &) { utility::conditionally_invoke( [this]() { return phoneModeObserver->isInMode(sys::phone_modes::PhoneMode::Offline); }, - [this]() { connectionManager->onTimerTick(); }); + [this]() { + if (connectionManager != nullptr) + connectionManager->onTimerTick(); + }); }); ongoingCall.setStartCallAction([=](const CalllogRecord &rec) { @@ -248,8 +242,6 @@ ServiceCellular::ServiceCellular() ServiceCellular::~ServiceCellular() { LOG_INFO("[ServiceCellular] Cleaning resources"); - settings->unregisterValueChange(settings::Cellular::volte_on, ::settings::SettingsScope::Global); - settings->unregisterValueChange(settings::Cellular::apn_list, ::settings::SettingsScope::Global); } // this static function will be replaced by Settings API @@ -284,6 +276,16 @@ sys::ReturnCodes ServiceCellular::InitHandler() { board = EventManagerServiceAPI::GetBoard(this); + settings = std::make_unique(); + settings->init(service::ServiceProxy(shared_from_this())); + + connectionManager = std::make_unique( + utils::getNumericValue( + settings->getValue(settings::Cellular::offlineMode, settings::SettingsScope::Global)), + static_cast(utils::getNumericValue(settings->getValue( + settings->getValue(settings::Offline::connectionFrequency, settings::SettingsScope::Global)))), + std::make_shared(*this)); + state.set(this, State::ST::WaitForStartPermission); settings->registerValueChange( settings::Cellular::volte_on, @@ -307,7 +309,7 @@ sys::ReturnCodes ServiceCellular::InitHandler() sys::ReturnCodes ServiceCellular::DeinitHandler() { - + settings->deinit(); return sys::ReturnCodes::Success; } diff --git a/module-services/service-db/CMakeLists.txt b/module-services/service-db/CMakeLists.txt index 2b7f1e0599629a0729a066f0bfc10387c8e38c3f..b908c1ddc99b5fe3583f74de3d78b7aac5dfcc71 100644 --- a/module-services/service-db/CMakeLists.txt +++ b/module-services/service-db/CMakeLists.txt @@ -15,6 +15,7 @@ set(SOURCES messages/QueryMessage.cpp agents/settings/SettingsAgent.cpp agents/settings/Settings.cpp + agents/settings/SettingsProxy.cpp agents/settings/SettingsCache.cpp agents/settings/FactorySettings.cpp agents/file_indexer/FileIndexerAgent.cpp diff --git a/module-services/service-db/EntryPath.cpp b/module-services/service-db/EntryPath.cpp index c475b9b87661dff14b4bdf46012e834ca828b5d6..3694a9b4894186a5b10ef568f4c485e390b59074 100644 --- a/module-services/service-db/EntryPath.cpp +++ b/module-services/service-db/EntryPath.cpp @@ -1,10 +1,28 @@ // Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -#include "service-db/SettingsMessages.hpp" +#include "service-db/EntryPath.hpp" +#include namespace settings { + + void EntryPath::parse(const std::string &dbPath) + { + auto parts = utils::split(dbPath, "\\", false); + if (1 == parts.size()) { + variable = dbPath; + scope = SettingsScope::Global; + } + else { + mode = parts[0]; + service = parts[1]; + profile = parts[2]; + variable = parts[3]; + scope = SettingsScope::AppLocal; + } + } + namespace { bool isLessAppLocal(const EntryPath &lhs, const EntryPath &rhs) noexcept diff --git a/module-services/service-db/agents/settings/Settings.cpp b/module-services/service-db/agents/settings/Settings.cpp index 8cfbac52fb81826559fa3779cc4e9329f253a2b4..21a3310c5e16001bbbc9f91d0cea4e8070c4ccb9 100644 --- a/module-services/service-db/agents/settings/Settings.cpp +++ b/module-services/service-db/agents/settings/Settings.cpp @@ -2,18 +2,15 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include -#include #include -#include -#include -#include -#include - +#include +#include #include #include #if defined(DEBUG_SETTINGS_DB) and DEBUG_SETTINGS_DB == 1 +#include #define log_debug(...) LOG_DEBUG(__VA_ARGS__); #else #define log_debug(...) @@ -21,259 +18,101 @@ namespace settings { - Settings::Settings(sys::Service *app, const std::string &dbAgentName, SettingsCache *cache) - : dbAgentName(dbAgentName), cache(cache) + Settings::~Settings() { - this->app = - std::shared_ptr(app, [](sys::Service *service) {}); /// with deleter that doesn't delete. - this->app->bus.channels.push_back(sys::BusChannel::ServiceDBNotifications); - if (nullptr == cache) { - this->cache = SettingsCache::getInstance(); - } - registerHandlers(); + deinit(); } - void Settings::sendMsg(std::shared_ptr &&msg) + void Settings::init(const service::ServiceProxy &interface) { - app->bus.sendUnicast(std::move(msg), dbAgentName); + this->interface = SettingsProxy(interface); + this->interface.init([&](const EntryPath &p, const std::string &v) { this->handleVariableChanged(p, v); }); + if (not interface.isValid()) { + throw std::invalid_argument("need the interface!"); + } } - void Settings::registerHandlers() - { - using std::placeholders::_1; - using std::placeholders::_2; - log_debug("Settings::registerHandlers for %s", app->GetName().c_str()); - app->connect(settings::Messages::VariableChanged(), std::bind(&Settings::handleVariableChanged, this, _1)); - app->connect(settings::Messages::CurrentProfileChanged(), - std::bind(&Settings::handleCurrentProfileChanged, this, _1)); - app->connect(settings::Messages::CurrentModeChanged(), - std::bind(&Settings::handleCurrentModeChanged, this, _1)); - app->connect(settings::Messages::ProfileListResponse(), - std::bind(&Settings::handleProfileListResponse, this, _1)); - app->connect(settings::Messages::ModeListResponse(), std::bind(&Settings::handleModeListResponse, this, _1)); - } - auto Settings::handleVariableChanged(sys::Message *req) -> sys::MessagePointer + void Settings::deinit() { - log_debug("handleVariableChanged"); - if (auto msg = dynamic_cast(req)) { - auto key = msg->getPath(); - auto val = msg->getValue(); - log_debug("handleVariableChanged: (k=v): (%s=%s)", key.to_string().c_str(), val.value_or("").c_str()); - ValueCb::iterator it_cb = cbValues.find(key); - if (cbValues.end() != it_cb) { - auto [cb, cbWithName] = it_cb->second; - if (nullptr != cb && nullptr != cbWithName) { - // in case of two callbacks there is a need to duplicate the value - auto value = val.value_or(""); - cb(std::string{value}); - cbWithName(key.variable, value); - } - else if (nullptr != cb) { - cb(val.value_or("")); - } - else { - cbWithName(key.variable, val.value_or("")); - } + if (interface.isValid()) { + interface.deinit(); + for (const auto &callbacks : cbValues) { + log_debug("[Settings::unregisterValueChange] %s", callbacks.first.to_string().c_str()); + interface.unregisterValueChange(callbacks.first); } } - return std::make_shared(); - } - auto Settings::handleCurrentProfileChanged(sys::Message *req) -> sys::MessagePointer - { - log_debug("handleCurrentProfileChanged"); - if (auto msg = dynamic_cast(req)) { - auto profile = msg->getProfileName(); - log_debug("handleCurrentProfileChanged: %s", profile.c_str()); - cbProfile(profile); - } - return std::make_shared(); - } - auto Settings::handleCurrentModeChanged(sys::Message *req) -> sys::MessagePointer - { - log_debug("handleCurrentModeChanged"); - if (auto msg = dynamic_cast(req)) { - auto mode = msg->getProfileName(); - log_debug("handleCurrentModeChanged: %s", mode.c_str()); - cbMode(mode); - } - return std::make_shared(); - } - auto Settings::handleProfileListResponse(sys::Message *req) -> sys::MessagePointer - { - log_debug("handleProfileListResponse"); - if (auto msg = dynamic_cast(req)) { - auto profiles = msg->getValue(); - log_debug("handleProfileListResponse: %zu elements", profiles.size()); - cbAllProfiles(profiles); - } - return std::make_shared(); + cbValues.clear(); } - auto Settings::handleModeListResponse(sys::Message *req) -> sys::MessagePointer + + void Settings::handleVariableChanged(const EntryPath &path, const std::string &value) { - log_debug("handleModeListResponse"); - if (auto msg = dynamic_cast(req)) { - auto modes = msg->getValue(); - log_debug("handleModeListResponse: %zu elements", modes.size()); - cbAllModes(modes); + log_debug("handleVariableChanged: (k=v): (%s=%s)", path.to_string().c_str(), value.c_str()); + if (auto callbacks = cbValues.find(path); std::end(cbValues) != callbacks) { + auto &[cb, cbWithName] = callbacks->second; + if (nullptr != cb) { + cb(value); + } + if (nullptr != cbWithName) { + cbWithName(path.variable, value); + } } - return std::make_shared(); } void Settings::registerValueChange(const std::string &variableName, ValueChangedCallback cb, SettingsScope scope) { - EntryPath path; - path.variable = variableName; - path.service = app->GetName(); - path.scope = scope; + auto path = EntryPath{.service = interface.ownerName(), .variable = variableName, .scope = scope}; - auto it_cb = cbValues.find(path); - if (cbValues.end() != it_cb && nullptr != it_cb->second.first) { - LOG_INFO("Callback function on value change (%s) already exists, rewriting", path.to_string().c_str()); + if (auto callbacks = cbValues.find(path); + std::end(cbValues) != callbacks && nullptr != callbacks->second.first) { + log_debug("Callback function on value change (%s) already exists, rewriting", path.to_string().c_str()); } cbValues[path].first = std::move(cb); - - auto msg = std::make_shared(path); - sendMsg(std::move(msg)); + interface.registerValueChange(std::move(path)); } void Settings::registerValueChange(const std::string &variableName, ValueChangedCallbackWithName cb, SettingsScope scope) { - EntryPath path; - path.variable = variableName; - path.service = app->GetName(); - path.scope = scope; + auto path = EntryPath{.service = interface.ownerName(), .variable = variableName, .scope = scope}; - auto it_cb = cbValues.find(path); - if (cbValues.end() != it_cb && nullptr != it_cb->second.second) { - LOG_INFO("Callback function on value change (%s) already exists, rewriting", path.to_string().c_str()); + if (auto callbacks = cbValues.find(path); cbValues.end() != callbacks && nullptr != callbacks->second.second) { + log_debug("Callback function on value change (%s) already exists, rewriting", path.to_string().c_str()); } cbValues[path].second = std::move(cb); - - auto msg = std::make_shared(path); - sendMsg(std::move(msg)); + interface.registerValueChange(std::move(path)); } void Settings::unregisterValueChange(const std::string &variableName, SettingsScope scope) { - EntryPath path; - path.variable = variableName; - path.service = app->GetName(); - path.scope = scope; + auto path = EntryPath{.service = interface.ownerName(), .variable = variableName, .scope = scope}; - auto it_cb = cbValues.find(path); - if (cbValues.end() == it_cb) { - LOG_INFO("Callback function on value change (%s) does not exist", path.to_string().c_str()); + auto callbacks = cbValues.find(path); + if (cbValues.end() == callbacks) { + log_debug("Callback function on value change (%s) does not exist", path.to_string().c_str()); } else { log_debug("[Settings::unregisterValueChange] %s", path.to_string().c_str()); - cbValues.erase(it_cb); - } - - auto msg = std::make_shared(path); - sendMsg(std::move(msg)); - } - - void Settings::unregisterValueChange() - { - for (const auto &it_cb : cbValues) { - log_debug("[Settings::unregisterValueChange] %s", it_cb.first.to_string().c_str()); - auto msg = std::make_shared(it_cb.first); - sendMsg(std::move(msg)); + cbValues.erase(callbacks); } - cbValues.clear(); - LOG_INFO("Unregistered all settings variable change on application (%s)", app->GetName().c_str()); + interface.unregisterValueChange(std::move(path)); } void Settings::setValue(const std::string &variableName, const std::string &variableValue, SettingsScope scope) { - EntryPath path; - path.variable = variableName; - path.service = app->GetName(); - path.scope = scope; - auto msg = std::make_shared(path, variableValue); - sendMsg(std::move(msg)); - cache->setValue(path, variableValue); + auto path = EntryPath{.service = interface.ownerName(), .variable = variableName, .scope = scope}; + interface.setValue(path, variableValue); + getCache()->setValue(path, variableValue); } std::string Settings::getValue(const std::string &variableName, SettingsScope scope) { - EntryPath path; - path.variable = variableName; - path.service = app->GetName(); - path.scope = scope; - return cache->getValue(path); - } - - void Settings::getAllProfiles(OnAllProfilesRetrievedCallback cb) - { - if (nullptr == cbAllProfiles) { - sendMsg(std::make_shared()); - } - cbAllProfiles = std::move(cb); + return getCache()->getValue({.service = interface.ownerName(), .variable = variableName, .scope = scope}); } - void Settings::setCurrentProfile(const std::string &profile) + SettingsCache *Settings::getCache() { - sendMsg(std::make_shared(profile)); + return SettingsCache::getInstance(); } - void Settings::addProfile(const std::string &profile) - { - sendMsg(std::make_shared(profile)); - } - - void Settings::registerProfileChange(ProfileChangedCallback cb) - { - if (nullptr != cbProfile) { - log_debug("Profile change callback already exists, overwritting"); - } - else { - sendMsg(std::make_shared()); - } - - cbProfile = std::move(cb); - } - - void Settings::unregisterProfileChange() - { - cbProfile = nullptr; - sendMsg(std::make_shared()); - } - - void Settings::getAllModes(OnAllModesRetrievedCallback cb) - { - if (nullptr == cbAllModes) { - sendMsg(std::make_shared()); - } - cbAllModes = std::move(cb); - } - - void Settings::setCurrentMode(const std::string &mode) - { - sendMsg(std::make_shared(mode)); - } - - void Settings::addMode(const std::string &mode) - { - sendMsg(std::make_shared(mode)); - } - - void Settings::registerModeChange(ModeChangedCallback cb) - { - if (nullptr != cbMode) { - log_debug("ModeChange callback allready set overwriting"); - } - else { - sendMsg(std::make_shared()); - } - cbMode = std::move(cb); - } - - void Settings::unregisterModeChange() - { - cbMode = nullptr; - sendMsg(std::make_shared()); - } } // namespace settings diff --git a/module-services/service-db/agents/settings/SettingsAgent.cpp b/module-services/service-db/agents/settings/SettingsAgent.cpp index 83d9bd68ef87e7d31b573be343f074a89086b316..eb7d2561f0e3cb7f8d5b1de1b2f46d93059e00d2 100644 --- a/module-services/service-db/agents/settings/SettingsAgent.cpp +++ b/module-services/service-db/agents/settings/SettingsAgent.cpp @@ -11,12 +11,6 @@ namespace settings { - namespace DbPaths - { - constexpr auto phone_mode = "system/phone_mode"; - constexpr auto phone_profile = "system/phone_profile"; - } // namespace DbPaths - namespace factory { constexpr auto data_file = "personalization.json"; @@ -71,29 +65,6 @@ void SettingsAgent::registerMessages() std::bind(&SettingsAgent::handleRegisterOnVariableChange, this, _1)); parentService->connect(settings::Messages::UnregisterOnVariableChange(), std::bind(&SettingsAgent::handleUnregisterOnVariableChange, this, _1)); - // profile - parentService->connect(settings::Messages::RegisterOnProfileChange(), - std::bind(&SettingsAgent::handleRegisterProfileChange, this, _1)); - parentService->connect(settings::Messages::UnregisterOnProfileChange(), - std::bind(&SettingsAgent::handleUnregisterProfileChange, this, _1)); - parentService->connect(settings::Messages::SetCurrentProfile(), - std::bind(&SettingsAgent::handleSetCurrentProfile, this, _1)); - parentService->connect(settings::Messages::GetCurrentProfile(), - std::bind(&SettingsAgent::handleGetCurrentProfile, this, _1)); - parentService->connect(settings::Messages::AddProfile(), std::bind(&SettingsAgent::handleAddProfile, this, _1)); - parentService->connect(settings::Messages::ListProfiles(), std::bind(&SettingsAgent::handleListProfiles, this, _1)); - - // mode - parentService->connect(settings::Messages::RegisterOnModeChange(), - std::bind(&SettingsAgent::handleRegisterOnModeChange, this, _1)); - parentService->connect(settings::Messages::UnregisterOnModeChange(), - std::bind(&SettingsAgent::handleUnregisterOnModeChange, this, _1)); - parentService->connect(settings::Messages::SetCurrentMode(), - std::bind(&SettingsAgent::handleSetCurrentMode, this, _1)); - parentService->connect(settings::Messages::GetCurrentMode(), - std::bind(&SettingsAgent::handleGetCurrentMode, this, _1)); - parentService->connect(settings::Messages::AddMode(), std::bind(&SettingsAgent::handleAddMode, this, _1)); - parentService->connect(settings::Messages::ListModes(), std::bind(&SettingsAgent::handleListModes, this, _1)); } auto SettingsAgent::getDbInitString() -> const std::string @@ -137,89 +108,6 @@ auto SettingsAgent::dbUnregisterValueChange(const settings::EntryPath &path) -> settings::Statements::clearNotificationdRow, path.to_string().c_str(), path.service.c_str()); } -// db Profile -auto SettingsAgent::dbRegisterOnProfileChange(const std::string &service) -> bool -{ - return database->execute(settings::Statements::setNotification, settings::DbPaths::phone_profile, service.c_str()); -} -auto SettingsAgent::dbUnregisterOnProfileChange(const std::string &service) -> bool -{ - return database->execute( - settings::Statements::clearNotificationdRow, settings::DbPaths::phone_profile, service.c_str()); -} -auto SettingsAgent::dbSetCurrentProfile(const std::string &profile) -> bool -{ - return database->execute(settings::Statements::updateValue, profile.c_str(), settings::DbPaths::phone_profile); -} -auto SettingsAgent::dbGetCurrentProfile() -> std::string -{ - auto qProfile = database->query(settings::Statements::getValue, settings::DbPaths::phone_profile); - if (nullptr == qProfile || 1 != qProfile->getRowCount()) { - return std::string{}; - } - return (*qProfile)[0].getString(); -} -auto SettingsAgent::dbGetAllProfiles() -> std::list -{ - auto qProfiles = database->query(settings::Statements::getDictValue, settings::DbPaths::phone_profile); - if (nullptr == qProfiles || 0 == qProfiles->getRowCount()) { - return std::list{}; - } - std::list profiles; - do { - profiles.push_back((*qProfiles)[0].getString()); - } while (qProfiles->nextRow()); - return profiles; -} -auto SettingsAgent::dbAddProfile(const std::string &profile) -> bool -{ - return database->execute(settings::Statements::addDictValue, settings::DbPaths::phone_profile, profile.c_str()); -} - -// dbMode -auto SettingsAgent::dbRegisterOnModeChange(const std::string &service) -> bool -{ - return database->execute(settings::Statements::setNotification, settings::DbPaths::phone_mode, service.c_str()); -} - -auto SettingsAgent::dbUnregisterOnModeChange(const std::string &service) -> bool -{ - return database->execute( - settings::Statements::clearNotificationdRow, settings::DbPaths::phone_mode, service.c_str()); -} - -auto SettingsAgent::dbSetCurrentMode(const std::string &mode) -> bool -{ - return database->execute(settings::Statements::updateValue, mode.c_str(), settings::DbPaths::phone_mode); -} - -auto SettingsAgent::dbGetCurrentMode() -> std::string -{ - auto qMode = database->query(settings::Statements::getValue, settings::DbPaths::phone_mode); - if (nullptr == qMode || 1 != qMode->getRowCount()) { - return std::string{}; - } - return (*qMode)[0].getString(); -} - -auto SettingsAgent::dbGetAllModes() -> std::list -{ - auto qModes = database->query(settings::Statements::getDictValue, settings::DbPaths::phone_mode); - if (nullptr == qModes || 0 == qModes->getRowCount()) { - return std::list{}; - } - std::list modes; - do { - modes.push_back((*qModes)[0].getString()); - } while (qModes->nextRow()); - return modes; -} - -auto SettingsAgent::dbAddMode(const std::string &mode) -> bool -{ - return database->execute(settings::Statements::addDictValue, settings::DbPaths::phone_mode, mode.c_str()); -} - auto SettingsAgent::handleGetVariable(sys::Message *req) -> sys::MessagePointer { if (auto msg = dynamic_cast(req)) { @@ -292,146 +180,3 @@ auto SettingsAgent::handleUnregisterOnVariableChange(sys::Message *req) -> sys:: } return std::make_shared(); } - -// profile -auto SettingsAgent::handleRegisterProfileChange(sys::Message *req) -> sys::MessagePointer -{ - if (auto msg = dynamic_cast(req)) { - if (dbRegisterOnProfileChange(msg->sender)) { - profileChangedRecipients.insert(msg->sender); - auto msgCurrentProfile = std::make_shared(dbGetCurrentProfile()); - parentService->bus.sendUnicast(std::move(msgCurrentProfile), msg->sender); - } - } - return std::make_shared(); -} -auto SettingsAgent::handleUnregisterProfileChange(sys::Message *req) -> sys::MessagePointer -{ - if (auto msg = dynamic_cast(req)) { - if (dbUnregisterOnProfileChange(msg->sender)) { - profileChangedRecipients.erase(msg->sender); - } - } - return std::make_shared(); -} -auto SettingsAgent::handleSetCurrentProfile(sys::Message *req) -> sys::MessagePointer -{ - if (auto msg = dynamic_cast(req)) { - auto profile = msg->getProfileName(); - if (dbSetCurrentProfile(profile)) { - for (const auto &service : profileChangedRecipients) { - if (service != msg->sender) { - auto msgProfileChanged = std::make_shared(profile); - parentService->bus.sendUnicast(std::move(msgProfileChanged), service); - } - } - } - } - return std::make_shared(); -} -auto SettingsAgent::handleGetCurrentProfile(sys::Message *req) -> sys::MessagePointer -{ - if (nullptr != dynamic_cast(req)) { - auto service = profileChangedRecipients.find(req->sender); - if (profileChangedRecipients.end() != service) { - auto msgCurrentProfile = std::make_shared(dbGetCurrentProfile()); - parentService->bus.sendUnicast(std::move(msgCurrentProfile), *service); - } - } - return std::make_shared(); -} -auto SettingsAgent::handleAddProfile(sys::Message *req) -> sys::MessagePointer -{ - if (auto msg = dynamic_cast(req)) { - if (dbAddProfile(msg->getProfileName())) { - auto allProfiles = dbGetAllProfiles(); - for (const auto &service : profileChangedRecipients) { - if (service != req->sender) { - auto msgAllProfiles = std::make_shared(allProfiles); - parentService->bus.sendUnicast(std::move(msgAllProfiles), service); - } - } - } - } - return std::make_shared(); -} -auto SettingsAgent::handleListProfiles(sys::Message *req) -> sys::MessagePointer -{ - if (nullptr != dynamic_cast(req)) { - profileChangedRecipients.insert(req->sender); - auto msgAllProfiles = std::make_shared(dbGetAllProfiles()); - parentService->bus.sendUnicast(std::move(msgAllProfiles), req->sender); - } - return std::make_shared(); -} - -// mode -auto SettingsAgent::handleRegisterOnModeChange(sys::Message *req) -> sys::MessagePointer -{ - if (auto msg = dynamic_cast(req)) { - if (dbRegisterOnModeChange(msg->sender)) { - modeChangeRecipients.insert(msg->sender); - auto msgMode = std::make_shared(dbGetCurrentMode()); - parentService->bus.sendUnicast(std::move(msgMode), msg->sender); - } - } - return std::make_shared(); -} -auto SettingsAgent::handleUnregisterOnModeChange(sys::Message *req) -> sys::MessagePointer -{ - if (nullptr != dynamic_cast(req)) { - dbUnregisterOnModeChange(req->sender); - modeChangeRecipients.erase(req->sender); - } - return std::make_shared(); -} -auto SettingsAgent::handleSetCurrentMode(sys::Message *req) -> sys::MessagePointer -{ - if (auto msg = dynamic_cast(req)) { - if (auto newMode = msg->getProfileName(); dbGetCurrentMode() != newMode) { - if (dbSetCurrentMode(newMode)) { - for (const auto &service : modeChangeRecipients) { - if (service != msg->sender) { - auto msgModeChanged = std::make_shared(newMode); - parentService->bus.sendUnicast(std::move(msgModeChanged), service); - } - } - } - } - } - return std::make_shared(); -} -auto SettingsAgent::handleGetCurrentMode(sys::Message *req) -> sys::MessagePointer -{ - if (nullptr != dynamic_cast(req)) { - if (modeChangeRecipients.end() != modeChangeRecipients.find(req->sender)) { - auto msgMode = std::make_shared(dbGetCurrentMode()); - parentService->bus.sendUnicast(std::move(msgMode), req->sender); - } - } - return std::make_shared(); -} -auto SettingsAgent::handleAddMode(sys::Message *req) -> sys::MessagePointer -{ - if (auto msg = dynamic_cast(req)) { - if (dbAddMode(msg->getProfileName())) { - auto allModes = dbGetAllModes(); - for (const auto &service : modeChangeRecipients) { - if (service != msg->sender) { - auto msgAllModes = std::make_shared(allModes); - parentService->bus.sendUnicast(std::move(msgAllModes), service); - } - } - } - } - return std::make_shared(); -} -auto SettingsAgent::handleListModes(sys::Message *req) -> sys::MessagePointer -{ - if (nullptr != dynamic_cast(req)) { - modeChangeRecipients.insert(req->sender); - auto msgAllModes = std::make_shared(dbGetAllModes()); - parentService->bus.sendUnicast(std::move(msgAllModes), req->sender); - } - return std::make_shared(); -} diff --git a/module-services/service-db/agents/settings/SettingsAgent.hpp b/module-services/service-db/agents/settings/SettingsAgent.hpp index 8878c3aaf5161ddabcc73a02288f40fe0040934a..b00e86697d6bb5d2b9a257cbb495f5938cd1b5c3 100644 --- a/module-services/service-db/agents/settings/SettingsAgent.hpp +++ b/module-services/service-db/agents/settings/SettingsAgent.hpp @@ -51,20 +51,6 @@ class SettingsAgent : public DatabaseAgent auto dbRegisterValueChange(const settings::EntryPath &path) -> bool; auto dbUnregisterValueChange(const settings::EntryPath &path) -> bool; - auto dbRegisterOnProfileChange(const std::string &service) -> bool; - auto dbUnregisterOnProfileChange(const std::string &service) -> bool; - auto dbSetCurrentProfile(const std::string &profile) -> bool; - auto dbGetCurrentProfile() -> std::string; - auto dbGetAllProfiles() -> std::list; - auto dbAddProfile(const std::string &profile) -> bool; - - auto dbRegisterOnModeChange(const std::string &service) -> bool; - auto dbUnregisterOnModeChange(const std::string &service) -> bool; - auto dbSetCurrentMode(const std::string &mode) -> bool; - auto dbGetCurrentMode() -> std::string; - auto dbGetAllModes() -> std::list; - auto dbAddMode(const std::string &mode) -> bool; - auto getDbInitString() -> const std::string override; // msg handlers @@ -73,20 +59,4 @@ class SettingsAgent : public DatabaseAgent auto handleSetVariable(sys::Message *req) -> sys::MessagePointer; auto handleRegisterOnVariableChange(sys::Message *req) -> sys::MessagePointer; auto handleUnregisterOnVariableChange(sys::Message *req) -> sys::MessagePointer; - - // profile - auto handleRegisterProfileChange(sys::Message *req) -> sys::MessagePointer; - auto handleUnregisterProfileChange(sys::Message *req) -> sys::MessagePointer; - auto handleSetCurrentProfile(sys::Message *req) -> sys::MessagePointer; - auto handleGetCurrentProfile(sys::Message *req) -> sys::MessagePointer; - auto handleAddProfile(sys::Message *req) -> sys::MessagePointer; - auto handleListProfiles(sys::Message *req) -> sys::MessagePointer; - - // mode - auto handleRegisterOnModeChange(sys::Message *req) -> sys::MessagePointer; - auto handleUnregisterOnModeChange(sys::Message *req) -> sys::MessagePointer; - auto handleSetCurrentMode(sys::Message *req) -> sys::MessagePointer; - auto handleGetCurrentMode(sys::Message *req) -> sys::MessagePointer; - auto handleAddMode(sys::Message *req) -> sys::MessagePointer; - auto handleListModes(sys::Message *req) -> sys::MessagePointer; }; diff --git a/module-services/service-db/agents/settings/SettingsCache.cpp b/module-services/service-db/agents/settings/SettingsCache.cpp index b74cd76124711ac55c588137fd8d62a00b72f530..59ac2f6fae8f97a98ade1608331d47a4c7e5869b 100644 --- a/module-services/service-db/agents/settings/SettingsCache.cpp +++ b/module-services/service-db/agents/settings/SettingsCache.cpp @@ -1,29 +1,61 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + #include #include namespace settings { + namespace + { + class SettingsCacheImpl : public SettingsCache + { + public: + static SettingsCacheImpl &get() + { + static SettingsCacheImpl instance; + return instance; + } + + const std::string &getValue(const EntryPath &path) const; + void setValue(const EntryPath &path, const std::string &value); + + private: + std::map settingsMap; + mutable cpp_freertos::MutexStandard settingsMutex; + }; + + const std::string &SettingsCacheImpl::getValue(const EntryPath &path) const + { + static const std::string empty; + cpp_freertos::LockGuard lock(settingsMutex); + auto pathIt = settingsMap.find(path); + if (settingsMap.end() != pathIt) { + return pathIt->second; + } + return empty; + } + + void SettingsCacheImpl::setValue(const EntryPath &path, const std::string &value) + { + cpp_freertos::LockGuard lock(settingsMutex); + settingsMap[path] = value; + } + } // namespace + SettingsCache *SettingsCache::getInstance() { - static SettingsCache instance; - return &instance; + return &SettingsCacheImpl::get(); } const std::string &SettingsCache::getValue(const EntryPath &path) const { - static const std::string empty = ""; - cpp_freertos::LockGuard lock(settingsMutex); - auto pathIt = settingsMap.find(path); - if (settingsMap.end() != pathIt) { - return pathIt->second; - } - return empty; + return SettingsCacheImpl::get().getValue(path); } void SettingsCache::setValue(const EntryPath &path, const std::string &value) { - cpp_freertos::LockGuard lock(settingsMutex); - settingsMap[path] = value; + return SettingsCacheImpl::get().setValue(path, value); } } // namespace settings diff --git a/module-services/service-db/agents/settings/SettingsProxy.cpp b/module-services/service-db/agents/settings/SettingsProxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..207fc749f36181f1c387c5fac4348aa7e0912afa --- /dev/null +++ b/module-services/service-db/agents/settings/SettingsProxy.cpp @@ -0,0 +1,81 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace settings +{ + + SettingsProxy::SettingsProxy(const service::ServiceProxy &interface) : service::ServiceProxy(interface) + {} + + SettingsProxy::~SettingsProxy() + { + deinit(); + } + + std::string SettingsProxy::ownerName() noexcept + { + return getService()->GetName(); + } + + void SettingsProxy::init(std::function onChangeHandler) + { + this->onChangeHandler = std::move(onChangeHandler); + + getService()->bus.channels.push_back(sys::BusChannel::ServiceDBNotifications); + getService()->connect(typeid(settings::Messages::VariableChanged), [this](sys::Message *req) { + if (auto msg = dynamic_cast(req)) { + onChange(msg->getPath(), msg->getValue().value_or("")); + } + return std::make_shared(); + }); + } + + void SettingsProxy::deinit() + { + if (isValid()) { + getService()->disconnect(typeid(settings::Messages::VariableChanged)); + } + } + + [[nodiscard]] bool SettingsProxy::isValid() const noexcept + { + return service::ServiceProxy::isValid(); + } + + void SettingsProxy::onChange(EntryPath path, std::string value) + { + if (onChangeHandler) { + onChangeHandler(std::move(path), std::move(value)); + } + } + + template auto message(sys::BusProxy &bus, Args... args) + { + bus.sendUnicast(std::make_shared(args...), service::name::db); + } + + void SettingsProxy::registerValueChange(EntryPath path) + { + message(getService()->bus, std::move(path)); + } + + void SettingsProxy::unregisterValueChange(EntryPath path) + { + message(getService()->bus, std::move(path)); + } + + void SettingsProxy::setValue(const EntryPath &path, const std::string &value) + { + message(getService()->bus, path, value); + } + +} // namespace settings diff --git a/module-services/service-db/service-db/EntryPath.hpp b/module-services/service-db/service-db/EntryPath.hpp new file mode 100644 index 0000000000000000000000000000000000000000..64f5b50fd97c35d5fadf7ad9af901ffb5308af3d --- /dev/null +++ b/module-services/service-db/service-db/EntryPath.hpp @@ -0,0 +1,30 @@ +// 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 +#include +#include + +namespace settings +{ + struct EntryPath + { + std::string mode = ""; + std::string service; + std::string profile = ""; + std::string variable; + SettingsScope scope; + + [[nodiscard]] auto to_string(std::string sep = "\\") const -> std::string + { + if (SettingsScope::Global == scope) { + return variable; + } + return mode + sep + service + sep + profile + sep + variable; + } + + void parse(const std::string &dbPath); + }; +} // namespace settings diff --git a/module-services/service-db/service-db/Settings.hpp b/module-services/service-db/service-db/Settings.hpp index 70d406d9217ab9cdb95b6ab39a915770fb4e30e5..5bb26366e0dce97011417871aa476be3e7100e91 100644 --- a/module-services/service-db/service-db/Settings.hpp +++ b/module-services/service-db/service-db/Settings.hpp @@ -1,12 +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 -#include +#include "EntryPath.hpp" #include "SettingsScope.hpp" -#include "SettingsMessages.hpp" +#include "SettingsProxy.hpp" #include #include @@ -15,23 +14,23 @@ #include #include #include +#include namespace settings { class SettingsCache; + class Settings { public: using ValueChangedCallback = std::function; using ValueChangedCallbackWithName = std::function; - using ProfileChangedCallback = std::function; - using ModeChangedCallback = ProfileChangedCallback; - using ListOfProfiles = std::list; - using ListOfModes = ListOfProfiles; - using OnAllProfilesRetrievedCallback = std::function; - using OnAllModesRetrievedCallback = std::function; - Settings(sys::Service *app, const std::string &dbAgentName = service::name::db, SettingsCache *cache = nullptr); + Settings() = default; + virtual ~Settings(); + + void init(const service::ServiceProxy &interface); + void deinit(); void setValue(const std::string &variableName, const std::string &variableValue, @@ -44,43 +43,17 @@ namespace settings SettingsScope scope = SettingsScope::AppLocal); void unregisterValueChange(const std::string &variableName, SettingsScope scope = SettingsScope::AppLocal); /// unregisters all registered variables (both global and local) - void unregisterValueChange(); std::string getValue(const std::string &variableName, SettingsScope scope = SettingsScope::AppLocal); - void getAllProfiles(OnAllProfilesRetrievedCallback cb); - void setCurrentProfile(const std::string &profile); - void addProfile(const std::string &profile); - void registerProfileChange(ProfileChangedCallback); - void unregisterProfileChange(); - - void getAllModes(OnAllModesRetrievedCallback cb); - void setCurrentMode(const std::string &mode); - void addMode(const std::string &mode); - void registerModeChange(ModeChangedCallback); - void unregisterModeChange(); + SettingsCache *getCache(); private: - std::string dbAgentName; - - std::shared_ptr app; - std::string serviceName; - std::string phoneMode; - std::string profile; - - SettingsCache *cache; + SettingsProxy interface; using ValueCb = std::map>; + ValueCb cbValues; - ModeChangedCallback cbMode; - OnAllModesRetrievedCallback cbAllModes; - ProfileChangedCallback cbProfile; - OnAllProfilesRetrievedCallback cbAllProfiles; - void sendMsg(std::shared_ptr &&msg); - void registerHandlers(); - auto handleVariableChanged(sys::Message *req) -> sys::MessagePointer; - auto handleCurrentProfileChanged(sys::Message *req) -> sys::MessagePointer; - auto handleCurrentModeChanged(sys::Message *req) -> sys::MessagePointer; - auto handleProfileListResponse(sys::Message *req) -> sys::MessagePointer; - auto handleModeListResponse(sys::Message *req) -> sys::MessagePointer; + + void handleVariableChanged(const EntryPath &path, const std::string &value); }; } // namespace settings diff --git a/module-services/service-db/service-db/SettingsCache.hpp b/module-services/service-db/service-db/SettingsCache.hpp index c93e6123d2dbcb685a34ebc3fbdef872278f2e67..b81cdcad7b24b454e1efb019ce9a2930b61b020c 100644 --- a/module-services/service-db/service-db/SettingsCache.hpp +++ b/module-services/service-db/service-db/SettingsCache.hpp @@ -1,7 +1,8 @@ // Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -#include +#pragma once + #include "SettingsMessages.hpp" #include @@ -13,9 +14,6 @@ namespace settings const std::string &getValue(const EntryPath &path) const; void setValue(const EntryPath &path, const std::string &value); static SettingsCache *getInstance(); - - private: - std::map settingsMap; - mutable cpp_freertos::MutexStandard settingsMutex; + virtual ~SettingsCache() = default; }; } // namespace settings diff --git a/module-services/service-db/service-db/SettingsMessages.hpp b/module-services/service-db/service-db/SettingsMessages.hpp index 6d542972cd6f6502a18d231a9bfd1b6076c2aab6..83e13820d334050122ac5330dce804e1b6cceb21 100644 --- a/module-services/service-db/service-db/SettingsMessages.hpp +++ b/module-services/service-db/service-db/SettingsMessages.hpp @@ -5,49 +5,16 @@ #include #include -#include +#include "EntryPath.hpp" #include #include #include #include #include -#include namespace settings { - struct EntryPath - { - std::string mode; - std::string service; - std::string profile; - std::string variable; - SettingsScope scope; - - [[nodiscard]] auto to_string(std::string sep = "\\") const -> std::string - { - if (SettingsScope::Global == scope) { - return variable; - } - return mode + sep + service + sep + profile + sep + variable; - } - - void parse(const std::string &dbPath) - { - auto parts = utils::split(dbPath, "\\", false); - if (1 == parts.size()) { - variable = dbPath; - scope = SettingsScope::Global; - } - else { - mode = parts[0]; - service = parts[1]; - profile = parts[2]; - variable = parts[3]; - scope = SettingsScope::AppLocal; - } - } - }; bool operator<(const EntryPath &lhs, const EntryPath &rhs) noexcept; @@ -66,7 +33,7 @@ namespace settings public: Variable() = default; explicit Variable(EntryPath path, std::optional value = {}) - : SettingsMessage(), path(std::move(path)), value(std::move(value)) + : path(std::move(path)), value(std::move(value)) {} [[nodiscard]] auto getValue() const -> std::optional @@ -88,7 +55,7 @@ namespace settings { public: GetVariable() = default; - explicit GetVariable(EntryPath path) : Variable(path) + explicit GetVariable(EntryPath path) : Variable(std::move(path)) {} }; @@ -96,7 +63,7 @@ namespace settings { public: SetVariable() = default; - SetVariable(EntryPath path, std::string value) : Variable(path, value) + SetVariable(EntryPath path, std::string value) : Variable(std::move(path), value) {} }; @@ -104,7 +71,7 @@ namespace settings { public: RegisterOnVariableChange() = default; - explicit RegisterOnVariableChange(EntryPath path) : Variable(path) + explicit RegisterOnVariableChange(EntryPath path) : Variable(std::move(path)) {} }; @@ -112,7 +79,7 @@ namespace settings { public: UnregisterOnVariableChange() = default; - explicit UnregisterOnVariableChange(EntryPath path) : Variable(path) + explicit UnregisterOnVariableChange(EntryPath path) : Variable(std::move(path)) {} }; @@ -121,7 +88,7 @@ namespace settings public: VariableChanged() = default; explicit VariableChanged(EntryPath path, std::string value, std::string old_value) - : Variable(path, value), old_value(std::move(old_value)) + : Variable(std::move(path), value), old_value(std::move(old_value)) {} [[nodiscard]] auto getOldValue() const -> std::string @@ -133,142 +100,6 @@ namespace settings std::string old_value; }; - /// Profiles manipulation - class ListProfiles : public SettingsMessage - { - public: - [[nodiscard]] auto getProfiles() const -> std::set - { - return profiles; - } - - private: - std::set profiles; - }; - - class ProfileSettingsMessage : public SettingsMessage - { - public: - [[nodiscard]] auto getProfileName() const -> std::string - { - return profile; - } - - protected: - ProfileSettingsMessage() = default; - explicit ProfileSettingsMessage(std::string name) : SettingsMessage(), profile(std::move(name)) - {} - - protected: - std::string profile; - }; - - class SetCurrentProfile : public ProfileSettingsMessage - { - public: - SetCurrentProfile() = default; - explicit SetCurrentProfile(std::string profile) : ProfileSettingsMessage(profile) - {} - }; - - class AddProfile : public ProfileSettingsMessage - { - public: - AddProfile() = default; - explicit AddProfile(std::string profile) : ProfileSettingsMessage(profile) - {} - }; - - class GetCurrentProfile : public ProfileSettingsMessage - { - public: - GetCurrentProfile() = default; - explicit GetCurrentProfile(std::string profile) : ProfileSettingsMessage(profile) - {} - }; - - class RegisterOnProfileChange : public SettingsMessage - {}; - - class UnregisterOnProfileChange : public SettingsMessage - {}; - - class CurrentProfileChanged : public ProfileSettingsMessage - { - public: - CurrentProfileChanged() = default; - explicit CurrentProfileChanged(std::string profile) : ProfileSettingsMessage(profile) - {} - }; - - /// Modes manipulation - class ListModes : public SettingsMessage - { - public: - [[nodiscard]] auto getModes() const -> std::set - { - return modes; - } - - private: - std::set modes; - }; - - class Mode : public SettingsMessage - { - public: - [[nodiscard]] auto getModeName() const -> std::string - { - return mode; - } - - protected: - Mode() = default; - explicit Mode(std::string mode) : SettingsMessage(), mode(std::move(mode)) - {} - - protected: - std::string mode; - }; - - class SetCurrentMode : public ProfileSettingsMessage - { - public: - SetCurrentMode() = default; - explicit SetCurrentMode(std::string mode) : ProfileSettingsMessage(mode) - {} - }; - - class AddMode : public ProfileSettingsMessage - { - public: - AddMode() = default; - explicit AddMode(std::string mode) : ProfileSettingsMessage(mode) - {} - }; - - class GetCurrentMode : public ProfileSettingsMessage - { - public: - GetCurrentMode() = default; - explicit GetCurrentMode(std::string profile) : ProfileSettingsMessage(profile) - {} - }; - - class RegisterOnModeChange : public SettingsMessage - {}; - - class UnregisterOnModeChange : public SettingsMessage - {}; - - class CurrentModeChanged : public ProfileSettingsMessage - { - public: - CurrentModeChanged() = default; - explicit CurrentModeChanged(std::string profile) : ProfileSettingsMessage(profile) - {} - }; - class ValueResponse : sys::ResponseMessage { public: @@ -308,54 +139,5 @@ namespace settings EntryPath path; std::optional value; }; - - class ProfileResponse : public ValueResponse - { - public: - ProfileResponse() = default; - explicit ProfileResponse(std::string profile) : ValueResponse(profile) - {} - }; - - class ModeResponse : public ValueResponse - { - public: - ModeResponse() = default; - explicit ModeResponse(std::string mode) : ValueResponse(mode) - {} - }; - - class ListResponse : public SettingsMessage - { - public: - ListResponse() = default; - explicit ListResponse(std::list value) : SettingsMessage(), value(std::move(value)) - {} - - [[nodiscard]] auto getValue() const -> std::list - { - return value; - } - - protected: - std::list value; - }; - - class ProfileListResponse : public ListResponse - { - public: - ProfileListResponse() = default; - explicit ProfileListResponse(std::list profiles) : ListResponse(profiles) - {} - }; - - class ModeListResponse : public ListResponse - { - public: - ModeListResponse() = default; - explicit ModeListResponse(std::list modes) : ListResponse(modes) - {} - }; - } // namespace Messages } // namespace settings diff --git a/module-services/service-db/service-db/SettingsProxy.hpp b/module-services/service-db/service-db/SettingsProxy.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3867c2727242fd6ff20258da439bda3de8e6652c --- /dev/null +++ b/module-services/service-db/service-db/SettingsProxy.hpp @@ -0,0 +1,30 @@ +// 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 "EntryPath.hpp" +#include "Service/ServiceProxy.hpp" +#include + +namespace settings +{ + class SettingsProxy : private service::ServiceProxy + { + public: + SettingsProxy() = default; + ~SettingsProxy(); + explicit SettingsProxy(const service::ServiceProxy &interface); + void init(std::function onChangeHandler); + void deinit(); + [[nodiscard]] bool isValid() const noexcept; + + void onChange(EntryPath path, std::string value); + void registerValueChange(EntryPath path); + void unregisterValueChange(EntryPath path); + void setValue(const EntryPath &path, const std::string &value); + [[nodiscard]] std::string ownerName() noexcept; + + private: + std::function onChangeHandler; + }; +} // namespace settings diff --git a/module-services/service-db/test/CMakeLists.txt b/module-services/service-db/test/CMakeLists.txt index 761a30dc5d1a4ac9fc5f20427fa98d31e2bd49ce..3e04e4d1035bf09163df6a83cdbb5b28a95536cc 100644 --- a/module-services/service-db/test/CMakeLists.txt +++ b/module-services/service-db/test/CMakeLists.txt @@ -32,3 +32,4 @@ add_catch2_executable( ) add_subdirectory(test-settings) +add_subdirectory(test-settings-Settings) diff --git a/module-services/service-db/test/test-service-db-settings-messages.cpp b/module-services/service-db/test/test-service-db-settings-messages.cpp index 582ea00a68956195438f0a1cd79a3aa49c321b66..bfa151fce1f10824bad9a7dcd09a7abb14ebba56 100644 --- a/module-services/service-db/test/test-service-db-settings-messages.cpp +++ b/module-services/service-db/test/test-service-db-settings-messages.cpp @@ -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 // for Section, SourceLineInfo, SECTION, SectionInfo, StringRef, TEST_CASE @@ -83,24 +83,6 @@ namespace settings } return std::make_shared(); }; - - sys::MessagePointer handleListProfiles(sys::Message *req) - { - if (dynamic_cast(req) != nullptr) { - std::list profiles = {"silent", "loud"}; - return std::make_shared(profiles); - } - return std::make_shared(); - }; - - sys::MessagePointer handleListModes(sys::Message *req) - { - if (dynamic_cast(req) != nullptr) { - std::list modes = {"mode1", "mode2"}; - return std::make_shared(modes); - } - return std::make_shared(); - }; }; } // namespace settings @@ -125,32 +107,4 @@ TEST_CASE("Settings Messages") {"mode", "service", "profile", "variable", settings::SettingsScope::AppLocal})), "db-worker"); } - - SECTION("Send profile messages") - { - settings::Service settings("settings"); - settings.InitHandler(); - - settings.bus.sendUnicast(std::make_shared(), "settings"); - - settings.bus.sendUnicast(std::make_shared("new-profile"), "settings"); - - settings.bus.sendUnicast(std::make_shared(), "settings"); - - settings.bus.sendUnicast(std::make_shared("profile"), "settings"); - } - - SECTION("Send mode messages") - { - settings::Service settings("settings"); - settings.InitHandler(); - - settings.bus.sendUnicast(std::make_shared(), "settings"); - - settings.bus.sendUnicast(std::make_shared(), "settings"); - - settings.bus.sendUnicast(std::make_shared("new-mode"), "settings"); - - settings.bus.sendUnicast(std::make_shared("mode"), "settings"); - } } diff --git a/module-services/service-db/test/test-settings-Settings/CMakeLists.txt b/module-services/service-db/test/test-settings-Settings/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3a403f2ee5a9984be1c2349fef290ca0fee38418 --- /dev/null +++ b/module-services/service-db/test/test-settings-Settings/CMakeLists.txt @@ -0,0 +1,17 @@ +# service-db tests +add_catch2_executable( + NAME + settings-Settings + SRCS + main.cpp + test-settings-Interface.cpp + test-settings-Settings.cpp + ../../agents/settings/Settings.cpp + ../../EntryPath.cpp + INCLUDE + ${CMAKE_SOURCE_DIR}/module-sys + ${CMAKE_SOURCE_DIR}/source + ${CMAKE_SOURCE_DIR}/module-services/service-db + ${CMAKE_SOURCE_DIR}/module-utils/ + DEPS +) diff --git a/module-services/service-db/test/test-settings-Settings/main.cpp b/module-services/service-db/test/test-settings-Settings/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..24584da01024d97094a93e237d62848f0ea3a0c4 --- /dev/null +++ b/module-services/service-db/test/test-settings-Settings/main.cpp @@ -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 +#include diff --git a/module-services/service-db/test/test-settings-Settings/test-settings-Interface.cpp b/module-services/service-db/test/test-settings-Settings/test-settings-Interface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b20dd2a6805429a8d052f49d620b08df0c583002 --- /dev/null +++ b/module-services/service-db/test/test-settings-Settings/test-settings-Interface.cpp @@ -0,0 +1,72 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include +#include +#include + +namespace sys +{ + // mockup + class Service + {}; + +} // namespace sys + +class Interface_imp : public service::ServiceProxy +{ + public: + using ServiceProxy::getService; + Interface_imp() = default; + explicit Interface_imp(std::weak_ptr s) : service::ServiceProxy(std::move(s)) + {} +}; + +TEST_CASE("Interface - not initialized") +{ + SECTION("base api") + { + auto interface = service::ServiceProxy(); + REQUIRE(!interface.isValid()); + } + + SECTION("inherited api") + { + auto interface = Interface_imp(); + REQUIRE_THROWS_AS(interface.getService(), std::runtime_error); + } +} + +TEST_CASE("Interface - initialized") +{ + auto service = std::make_shared(); + auto interface = Interface_imp(service); + REQUIRE(interface.isValid()); + REQUIRE_NOTHROW(interface.getService()); +} + +TEST_CASE("Interface - expired") +{ + Interface_imp *interface; + std::shared_ptr expired; + { + auto service = std::make_shared(); + interface = new Interface_imp(service); + } + REQUIRE(!interface->isValid()); + REQUIRE_THROWS_AS(interface->getService(), std::runtime_error); + delete interface; +} + +TEST_CASE("Interface - copied") +{ + auto service = std::make_shared(); + auto interface = Interface_imp(service); + auto interface2 = interface; + + REQUIRE(interface.isValid()); + REQUIRE_NOTHROW(interface.getService()); + REQUIRE(interface2.isValid()); + REQUIRE_NOTHROW(interface2.getService()); + REQUIRE(interface2.getService() == interface.getService()); +} diff --git a/module-services/service-db/test/test-settings-Settings/test-settings-Settings.cpp b/module-services/service-db/test/test-settings-Settings/test-settings-Settings.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0806423d1c9a00ca450bec122ff15ce126e8824 --- /dev/null +++ b/module-services/service-db/test/test-settings-Settings/test-settings-Settings.cpp @@ -0,0 +1,91 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include +#include +#include "module-services/service-db/service-db/SettingsCache.hpp" +#include + +/// stub +namespace settings +{ + SettingsProxy::~SettingsProxy() + {} + SettingsProxy::SettingsProxy(const service::ServiceProxy &interface) : service::ServiceProxy(interface) + {} + void SettingsProxy::init(std::function onChangeHandler) + { + this->onChangeHandler = std::move(onChangeHandler); + } + void SettingsProxy::deinit() + {} + + void SettingsProxy::onChange(EntryPath path, std::string value) + { + if (onChangeHandler) { + onChangeHandler(std::move(path), std::move(value)); + } + }; + bool SettingsProxy::isValid() const noexcept + { + return true; + } + void SettingsProxy::registerValueChange(EntryPath){}; + void SettingsProxy::unregisterValueChange(EntryPath){}; + void SettingsProxy::setValue(const EntryPath &path, const std::string &value){}; + std::string SettingsProxy::ownerName() noexcept + { + return ""; + } + + const std::string &SettingsCache::getValue(const EntryPath &path) const + { + static const std::string val; + return val; + } + void SettingsCache::setValue(const EntryPath &path, const std::string &value) + {} + + SettingsCache *SettingsCache::getInstance() + { + static SettingsCache s; + return &s; + } + +} // namespace settings + +/// TODO shall we warn here... on uninitialized settings? +TEST_CASE("Settings - not initialized") +{ + settings::Settings setting; + SECTION("Not initialized settings") + { + auto val = setting.getValue("lol"); + REQUIRE(val.empty()); + } + + SECTION("dead initialized settings") + { + auto val = setting.getValue("lol"); + REQUIRE(val.empty()); + } +} + +TEST_CASE("Settings - initialized") +{ + /// this will require stubbing + SECTION("get Value - not exists") + {} + + SECTION("get Value - exists") + {} + + SECTION("get Value - different type that expected") + {} + + SECTION("set value - no value") + {} + + SECTION("set value - override") + {} +} diff --git a/module-services/service-db/test/test-settings/CMakeLists.txt b/module-services/service-db/test/test-settings/CMakeLists.txt index 1130bdf23bb1083d582ba5f2c62e2bf24ffecd54..8cd272c0e8ef03afd490698e00cf3d5adfe89311 100644 --- a/module-services/service-db/test/test-settings/CMakeLists.txt +++ b/module-services/service-db/test/test-settings/CMakeLists.txt @@ -11,7 +11,5 @@ add_catch2_executable( module-audio service-cellular module-cellular - iosyscalls DEPS - disk_image ) diff --git a/module-services/service-db/test/test-settings/test-service-db-settings-api.cpp b/module-services/service-db/test/test-settings/test-service-db-settings-api.cpp index f2c4d20ae450f85561942bc15a5e751d7ba731c8..763d6b76467dc3e567399658fc6ee79d0b7d0e27 100644 --- a/module-services/service-db/test/test-settings/test-service-db-settings-api.cpp +++ b/module-services/service-db/test/test-settings/test-service-db-settings-api.cpp @@ -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 @@ -27,105 +27,60 @@ TEST_CASE("SettingsApi") std::shared_ptr varWritter; std::shared_ptr varReader; std::shared_ptr testVar; - std::shared_ptr profWritter; - std::shared_ptr profReader; - std::shared_ptr testProf; - std::shared_ptr modeWritter; - std::shared_ptr modeReader; - std::shared_ptr testMode; std::shared_ptr testStart; - manager->StartSystem( - nullptr, - [manager, - &varWritter, - &varReader, - &testVar, - &profWritter, - &profReader, - &testProf, - &modeWritter, - &modeReader, - &testMode, - &testStart]() { - // preliminary - testStart = std::make_shared(); - testStart->lock(); - std::cout << "start thr_id: " << std::this_thread::get_id() << std::endl << std::flush; - auto ret = sys::SystemManager::RunSystemService( - std::make_shared(service::name::evt_manager), manager.get()); - ret &= sys::SystemManager::RunSystemService(std::make_shared(), manager.get()); - - varWritter = std::make_shared("writterVar"); - varReader = std::make_shared("readerVar"); - - ret &= sys::SystemManager::RunSystemService(varWritter, manager.get()); - ret &= sys::SystemManager::RunSystemService(varReader, manager.get()); - - testVar = std::make_shared("appTest", varWritter, varReader, testStart); - ret &= sys::SystemManager::RunSystemService(testVar, manager.get()); - - profWritter = std::make_shared("writterProf"); - profReader = std::make_shared("readerProf"); - - ret &= sys::SystemManager::RunSystemService(profWritter, manager.get()); - ret &= sys::SystemManager::RunSystemService(profReader, manager.get()); - - testProf = std::make_shared( - "appTestProfile", profWritter, profReader, testStart); - ret &= sys::SystemManager::RunSystemService(testProf, manager.get()); - - modeWritter = std::make_shared("writterMode"); - modeReader = std::make_shared("readerMode"); - - ret &= sys::SystemManager::RunSystemService(modeWritter, manager.get()); - ret &= sys::SystemManager::RunSystemService(modeReader, manager.get()); - - testMode = - std::make_shared("appTestMode", modeWritter, modeReader, testStart); - ret &= sys::SystemManager::RunSystemService(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(); - manager->bus.sendUnicast(std::move(msgStart), "appTest"); - - msgStart = std::make_shared(); - manager->bus.sendUnicast(std::move(msgStart), "appTestProfile"); - - msgStart = std::make_shared(); - manager->bus.sendUnicast(std::move(msgStart), "appTestMode"); - - return ret; - }); - - // start application - cpp_freertos::Thread::StartScheduler(); - - // check the results - std::cout << "testVar values:" << std::endl << std::flush; - for (auto s : testVar->v) { - std::cout << s << std::endl << std::flush; - } - REQUIRE(testVar->v.size() == 3); - REQUIRE(testVar->v[1] == testVar->v[0] + "1"); - REQUIRE(testVar->v[2] == testVar->v[1] + "2"); - - // check the result - std::cout << "testProf values:" << std::endl << std::flush; - for (auto s : testProf->v) { - std::cout << s << std::endl << std::flush; - } - REQUIRE(testProf->v[1] == testProf->v[0] + "1"); - REQUIRE(testProf->v[2] == testProf->v[0] + "12"); - REQUIRE(testProf->v[3] == "other"); + std::shared_ptr postMortemSetting; + + manager->StartSystem(nullptr, [manager, &varWritter, &varReader, &testVar, &testStart, &postMortemSetting]() { + // preliminary + testStart = std::make_shared(); + testStart->lock(); + std::cout << "start thr_id: " << std::this_thread::get_id() << std::endl << std::flush; + auto ret = sys::SystemManager::RunSystemService(std::make_shared(service::name::evt_manager), + manager.get()); + ret &= sys::SystemManager::RunSystemService(std::make_shared(), manager.get()); + + varWritter = std::make_shared("writterVar"); + varReader = std::make_shared("readerVar"); + + postMortemSetting = varWritter->getSettings(); + + ret &= sys::SystemManager::RunSystemService(varWritter, manager.get()); + ret &= sys::SystemManager::RunSystemService(varReader, manager.get()); + + testVar = std::make_shared("appTest", varWritter, varReader, testStart); + ret &= sys::SystemManager::RunSystemService(testVar, manager.get()); - std::cout << "testMode values:" << std::endl << std::flush; - for (auto s : testMode->v) { - std::cout << s << std::endl << std::flush; + std::cout << "koniec start thr_id: " << std::this_thread::get_id() << std::endl << std::flush; + testStart->unlock(); + auto msgStart = std::make_shared(); + manager->bus.sendUnicast(std::move(msgStart), "appTest"); + + msgStart = std::make_shared(); + manager->bus.sendUnicast(std::move(msgStart), "appTestProfile"); + + msgStart = std::make_shared(); + manager->bus.sendUnicast(std::move(msgStart), "appTestMode"); + + return ret; + }); + + try { + // start application + cpp_freertos::Thread::StartScheduler(); + + // check the results + std::cout << "testVar values:" << std::endl << std::flush; + for (const auto &s : testVar->v) { + std::cout << s << std::endl << std::flush; + } + REQUIRE(testVar->v.size() == 3); + REQUIRE(testVar->v[1] == testVar->v[0] + "1"); + REQUIRE(testVar->v[2] == testVar->v[1] + "2"); + } + catch (std::exception &error) { + std::cout << error.what() << std::endl; + exit(1); } - REQUIRE(testMode->v[1] == testMode->v[0] + "1"); - REQUIRE(testMode->v[2] == testMode->v[0] + "12"); - REQUIRE(testMode->v[3] == "other"); } } diff --git a/module-services/service-db/test/test-settings/test-service-db-settings-testapps.hpp b/module-services/service-db/test/test-settings/test-service-db-settings-testapps.hpp index 0f23d2b7a8a0d7962cb45aed860604a6d503daba..c67b9023271c1f313d029e3c6df7f5dabd177917 100644 --- a/module-services/service-db/test/test-settings/test-service-db-settings-testapps.hpp +++ b/module-services/service-db/test/test-settings/test-service-db-settings-testapps.hpp @@ -66,6 +66,21 @@ namespace settings std::string last_v; std::vector v; + void setState(State state) + { + printf("state change: [%s]->[%s]\n", + std::string(magic_enum::enum_name(this->state)).c_str(), + std::string(magic_enum::enum_name(state)).c_str()); + this->state = state; + } + bool isState(State cmp) + { + printf("state compare: [%s]->[%s]\n", + std::string(magic_enum::enum_name(this->state)).c_str(), + std::string(magic_enum::enum_name(state)).c_str()); + return this->state == cmp; + } + AppTest(std::string name, std::shared_ptr setter, std::shared_ptr getter, @@ -75,7 +90,7 @@ namespace settings {} sys::ReturnCodes InitHandler() override { - state = State::Unk; + setState(State::Unk); return sys::ReturnCodes::Success; } sys::ReturnCodes DeinitHandler() override @@ -88,48 +103,48 @@ namespace settings if (nullptr != dynamic_cast(msg)) { testStart->lock(); testStart->unlock(); - if (state != State::Unk) { + if (!isState(State::Unk)) { closeSystem(); } else { - state = State::Start; + setState(State::Start); auto msg = std::make_shared("brightness", "none"); bus.sendUnicast(std::move(msg), getter->GetName()); } } else if (nullptr != dynamic_cast(msg)) { - if (state == State::Start) { - state = State::Register; + if (isState(State::Start)) { + setState(State::Register); } } else if (auto m = dynamic_cast(msg)) { - if (state == State::Register) { - state = State::RegisterStartVal; + if (isState(State::Register)) { + setState(State::RegisterStartVal); v.push_back(m->value); auto msg = std::make_shared("brightness", v[0] + "1"); bus.sendUnicast(std::move(msg), setter->GetName()); } - else if (state == State::RegisterSetVal) { + else if (isState(State::RegisterSetVal)) { if (m->value == v[0] + "1") { v.push_back(m->value); auto msg = std::make_shared("brightness", "empty"); bus.sendUnicast(std::move(msg), getter->GetName()); - state = State::UnregisterWait; + setState(State::UnregisterWait); } } } else if (nullptr != dynamic_cast(msg)) { - if (state == State::UnregisterWait) { - state = State::Unregister; + if (isState(State::UnregisterWait)) { + setState(State::Unregister); auto msg = std::make_shared("brightness", v.back() + "2"); bus.sendUnicast(std::move(msg), setter->GetName()); } } else if (auto m = dynamic_cast(msg)) { - if (state == State::RegisterStartVal) { - state = State::RegisterSetVal; + if (isState(State::RegisterStartVal)) { + setState(State::RegisterSetVal); } - else if (state == State::Unregister) { + else if (isState(State::Unregister)) { std::this_thread::sleep_for(std::chrono::milliseconds(200)); v.push_back(m->value); auto msg = std::make_shared(); @@ -137,7 +152,7 @@ namespace settings } } else if (nullptr != dynamic_cast(msg)) { - if (state == State::Unregister) { + if (isState(State::Unregister)) { closeSystem(); } } @@ -168,69 +183,69 @@ namespace settings if (nullptr != dynamic_cast(msg)) { testStart->lock(); testStart->unlock(); - if (state != State::Unk) { + if (!isState(State::Unk)) { closeSystem(); } else { - state = State::Start; + setState(State::Start); auto msg = std::make_shared(); bus.sendUnicast(std::move(msg), getter->GetName()); } } else if (nullptr != dynamic_cast(msg)) { - if (state == State::Start) { - state = State::Register; + if (isState(State::Start)) { + setState(State::Register); } } else if (auto m = dynamic_cast(msg)) { - if (state == State::Register) { - state = State::RegisterStartVal; + if (isState(State::Register)) { + setState(State::RegisterStartVal); v.push_back(m->name); auto msg = std::make_shared(m->name + "1"); bus.sendUnicast(std::move(msg), setter->GetName()); } - else if (state == State::RegisterSetVal) { + else if (isState(State::RegisterSetVal)) { if (m->name == v[0] + "1") { v.push_back(m->name); auto msg = std::make_shared(); bus.sendUnicast(std::move(msg), getter->GetName()); - state = State::UnregisterWait; + setState(State::UnregisterWait); } } } else if (nullptr != dynamic_cast(msg)) { - if (state == State::UnregisterWait) { - state = State::Unregister; + if (isState(State::UnregisterWait)) { + setState(State::Unregister); auto msg = std::make_shared(v.back() + "2"); bus.sendUnicast(std::move(msg), setter->GetName()); } } else if (auto m = dynamic_cast(msg)) { - if (state == State::RegisterStartVal) { - state = State::RegisterSetVal; + if (isState(State::RegisterStartVal)) { + setState(State::RegisterSetVal); } - else if (state == State::Unregister) { + else if (isState(State::Unregister)) { v.push_back(m->name); auto msg = std::make_shared(); bus.sendUnicast(std::move(msg), getter->GetName()); } } else if (nullptr != dynamic_cast(msg)) { - if (state == State::Unregister) { - state = State::RegisterAllWait; + if (isState(State::Unregister)) { + setState(State::RegisterAllWait); } } else if (auto m = dynamic_cast(msg)) { - if (state == State::RegisterAllWait) { - state = State::RegisterAll; + if (isState(State::RegisterAllWait)) { + setState(State::RegisterAll); for (auto prof : m->profiles) { v.push_back(prof); } auto msg = std::make_shared("other"); bus.sendUnicast(std::move(msg), setter->GetName()); } - else if (state == State::RegisterAllAddWait) { - state = State::RegisterAllAdd; + else if (isState(State::RegisterAllAddWait)) { + setState(State::RegisterAllAdd); for (auto prof : m->profiles) { v.push_back(prof); } @@ -240,12 +255,12 @@ namespace settings } } else if (nullptr != dynamic_cast(msg)) { - if (state == State::RegisterAll) { - state = State::RegisterAllAddWait; + if (isState(State::RegisterAll)) { + setState(State::RegisterAllAddWait); } } else if (nullptr != dynamic_cast(msg)) { - if (state == State::RegisterAllAdd) { + if (isState(State::RegisterAllAdd)) { closeSystem(); } } diff --git a/module-services/service-db/test/test-settings/test-service-db-settings-testservices.hpp b/module-services/service-db/test/test-settings/test-service-db-settings-testservices.hpp index 9aebee407e88f51d8b8e6f4875cdada8f20b1fae..84bd3e205d1dcde71599eec5c3db3f0b3e5a6a2f 100644 --- a/module-services/service-db/test/test-settings/test-service-db-settings-testservices.hpp +++ b/module-services/service-db/test/test-settings/test-service-db-settings-testservices.hpp @@ -1,6 +1,8 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md +#include + namespace settings { class MyService : public sys::Service @@ -8,7 +10,6 @@ namespace settings public: MyService(const std::string &name) : sys::Service(name) { - mySettings = std::make_shared(this); } std::shared_ptr mySettings; std::vector valChanged; @@ -59,11 +60,15 @@ namespace settings } sys::ReturnCodes InitHandler() override { - std::cout << "inithandler thr_id: " << std::this_thread::get_id() << std::endl << std::flush; + std::cout << "InitHandler thr_id: " << std::this_thread::get_id() << "name: " << GetName() << std::endl + << std::flush; + mySettings = std::make_shared(); + mySettings->init(service::ServiceProxy(shared_from_this())); return sys::ReturnCodes::Success; } sys::ReturnCodes DeinitHandler() override { + mySettings->deinit(); std::cout << "deinithandler thr_id: " << std::this_thread::get_id() << std::endl << std::flush; return sys::ReturnCodes::Success; } @@ -71,115 +76,11 @@ namespace settings { return sys::ReturnCodes::Success; } - }; - class ServiceProfile : public MyService - { - public: - ServiceProfile(const std::string &name) : MyService(name) - {} - settings::Settings::ListOfProfiles profiles; - std::string profile; - sys::MessagePointer DataReceivedHandler(sys::DataMessage *req, sys::ResponseMessage *resp) override + std::shared_ptr getSettings() { - if (auto msg = dynamic_cast(req)) { - debug("ReqRegProfileChg", msg->name, msg->value); - whoRequestedNotifyOnChange = msg->sender; - mySettings->registerProfileChange(([this](const std::string &profile) { - this->profile = profile; - auto cnf = std::make_shared(profile); - bus.sendUnicast(std::move(cnf), whoRequestedNotifyOnChange); - })); - auto cnf = std::make_shared(); - bus.sendUnicast(std::move(cnf), whoRequestedNotifyOnChange); - } - else if (auto msg = dynamic_cast(req)) { - // unregister - debug("ReqUnRegProfileChg", msg->name, msg->value); - mySettings->unregisterProfileChange(); - auto cnf = std::make_shared(); - bus.sendUnicast(std::move(cnf), msg->sender); - } - else if (auto msg = dynamic_cast(req)) { - // set value - debug("ReqSetCurrentProfile", msg->name, msg->value); - mySettings->setCurrentProfile(msg->name); - auto cnf = std::make_shared(msg->name); - bus.sendUnicast(std::move(cnf), msg->sender); - } - else if (auto msg = dynamic_cast(req)) { - debug("ReqGetAllProfiles", msg->name, msg->value); - mySettings->getAllProfiles(([this](const settings::Settings::ListOfProfiles &profiles) { - this->profiles = profiles; - auto cnf = std::make_shared(profiles); - bus.sendUnicast(std::move(cnf), whoRequestedNotifyOnChange); - })); - auto cnf = std::make_shared(); - bus.sendUnicast(std::move(cnf), msg->sender); - } - else if (auto msg = dynamic_cast(req)) { - debug("ReqAddProfile", msg->name, msg->value); - mySettings->addProfile(msg->name); - auto cnf = std::make_shared(msg->name); - bus.sendUnicast(std::move(cnf), msg->sender); - } - - return std::make_shared(); + return mySettings; } }; - class ServiceMode : public MyService - { - public: - ServiceMode(const std::string &name) : MyService(name) - {} - settings::Settings::ListOfModes modes; - std::string mode; - sys::MessagePointer DataReceivedHandler(sys::DataMessage *req, sys::ResponseMessage *resp) override - { - if (auto msg = dynamic_cast(req)) { - debug("ReqRegProfileChg", msg->name, msg->value); - whoRequestedNotifyOnChange = msg->sender; - mySettings->registerModeChange(([this](const std::string &mode) { - this->mode = mode; - auto cnf = std::make_shared(mode); - bus.sendUnicast(std::move(cnf), whoRequestedNotifyOnChange); - })); - auto cnf = std::make_shared(); - bus.sendUnicast(std::move(cnf), whoRequestedNotifyOnChange); - } - else if (auto msg = dynamic_cast(req)) { - // unregister - debug("ReqUnRegProfileChg", msg->name, msg->value); - mySettings->unregisterModeChange(); - auto cnf = std::make_shared(); - bus.sendUnicast(std::move(cnf), msg->sender); - } - else if (auto msg = dynamic_cast(req)) { - // set value - debug("ReqSetCurrentProfile", msg->name, msg->value); - mySettings->setCurrentMode(msg->name); - auto cnf = std::make_shared(msg->name); - bus.sendUnicast(std::move(cnf), msg->sender); - } - else if (auto msg = dynamic_cast(req)) { - debug("ReqGetAllProfiles", msg->name, msg->value); - mySettings->getAllModes(([this](const settings::Settings::ListOfModes &modes) { - this->modes = modes; - auto cnf = std::make_shared(modes); - bus.sendUnicast(std::move(cnf), whoRequestedNotifyOnChange); - })); - auto cnf = std::make_shared(); - bus.sendUnicast(std::move(cnf), msg->sender); - } - else if (auto msg = dynamic_cast(req)) { - debug("ReqAddProfile", msg->name, msg->value); - mySettings->addMode(msg->name); - auto cnf = std::make_shared(msg->name); - bus.sendUnicast(std::move(cnf), msg->sender); - } - - return std::make_shared(); - } - }; } // namespace settings diff --git a/module-services/service-desktop/ServiceDesktop.cpp b/module-services/service-desktop/ServiceDesktop.cpp index 2f86ac0598df8dbbe5151db333c97026b2c7891f..f4568b22179fb714364bccefd1fc9588d84b3583 100644 --- a/module-services/service-desktop/ServiceDesktop.cpp +++ b/module-services/service-desktop/ServiceDesktop.cpp @@ -68,8 +68,6 @@ ServiceDesktop::ServiceDesktop() bus.channels.push_back(sys::BusChannel::PhoneLockChanges); updateOS = std::make_unique(this); - settings = std::make_unique(this); - usbSecurityModel = std::make_unique(this, settings.get()); } ServiceDesktop::~ServiceDesktop() @@ -79,6 +77,10 @@ ServiceDesktop::~ServiceDesktop() sys::ReturnCodes ServiceDesktop::InitHandler() { + + settings = std::make_unique(); + settings->init(service::ServiceProxy(shared_from_this())); + usbSecurityModel = std::make_unique(this, settings.get()); desktopWorker = std::make_unique(this, *usbSecurityModel.get()); const bool ret = desktopWorker->init({{sdesktop::RECEIVE_QUEUE_BUFFER_NAME, sizeof(std::string *), sdesktop::cdc_queue_len}, @@ -295,6 +297,7 @@ sys::ReturnCodes ServiceDesktop::InitHandler() sys::ReturnCodes ServiceDesktop::DeinitHandler() { + settings->deinit(); desktopWorker->deinit(); return sys::ReturnCodes::Success; } diff --git a/module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp b/module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp index 3c701ee82726070edd87316b986e3ab641f7e6eb..034a63300ac1ad589a83ade867dba291fbd3defb 100644 --- a/module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp +++ b/module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp @@ -2,6 +2,7 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "DeveloperModeHelper.hpp" +#include "service-db/SettingsMessages.hpp" #include #include diff --git a/module-services/service-evtmgr/EventManager.cpp b/module-services/service-evtmgr/EventManager.cpp index e3505c0964bbeffe38d7be98185ee8e54ff4e86f..e843e363a46fdcb0f384c1e3a332fcaf608bee8b 100644 --- a/module-services/service-evtmgr/EventManager.cpp +++ b/module-services/service-evtmgr/EventManager.cpp @@ -55,13 +55,11 @@ namespace } // namespace EventManager::EventManager(const std::string &name) - : sys::Service(name, "", stackDepth), - settings(std::make_shared(this)), loggerTimer{sys::TimerFactory::createPeriodicTimer( - this, - loggerTimerName, - std::chrono::milliseconds{loggerDelayMs}, - [this](sys::Timer & /*timer*/) { dumpLogsToFile(); })}, - screenLightControl(std::make_unique(settings, this)), + : sys::Service(name, "", stackDepth), loggerTimer{sys::TimerFactory::createPeriodicTimer( + this, + loggerTimerName, + std::chrono::milliseconds{loggerDelayMs}, + [this](sys::Timer & /*timer*/) { dumpLogsToFile(); })}, Vibra(std::make_unique(this)) { LOG_INFO("[%s] Initializing", name.c_str()); @@ -209,6 +207,8 @@ sys::MessagePointer EventManager::DataReceivedHandler(sys::DataMessage *msgl, sy // Invoked during initialization sys::ReturnCodes EventManager::InitHandler() { + settings->init(service::ServiceProxy(shared_from_this())); + screenLightControl = std::make_unique(settings, this); connect(sdesktop::developerMode::DeveloperModeRequest(), [&](sys::Message *msg) { using namespace sdesktop::developerMode; @@ -329,6 +329,8 @@ sys::ReturnCodes EventManager::InitHandler() sys::ReturnCodes EventManager::DeinitHandler() { + settings->deinit(); + EventWorker->close(); EventWorker.reset(); EventWorker = nullptr; diff --git a/module-services/service-evtmgr/service-evtmgr/EventManager.hpp b/module-services/service-evtmgr/service-evtmgr/EventManager.hpp index d02d16598194727229d3640abd131cc2ec136767..1241c38b87a17d968a022775c3b025f775f816c7 100644 --- a/module-services/service-evtmgr/service-evtmgr/EventManager.hpp +++ b/module-services/service-evtmgr/service-evtmgr/EventManager.hpp @@ -38,7 +38,7 @@ class EventManager : public sys::Service void toggleTorchOnOff(); void toggleTorchColor(); - std::shared_ptr settings; + std::shared_ptr settings = std::make_shared(); sys::TimerHandle loggerTimer; sys::TimerHandle keypadLightTimer; bsp::keypad_backlight::State keypadLightState{bsp::keypad_backlight::State::off}; diff --git a/module-sys/Service/Common.hpp b/module-sys/Service/Common.hpp index 2737669dc9fbf5d1a77bb66d937cbc747501f913..407a1bdc9ef59e2242a98d3fcf101ae57ae27c18 100644 --- a/module-sys/Service/Common.hpp +++ b/module-sys/Service/Common.hpp @@ -3,7 +3,6 @@ #pragma once -#include "FreeRTOSConfig.h" #include "SystemReturnCodes.hpp" namespace sys diff --git a/module-sys/Service/Service.hpp b/module-sys/Service/Service.hpp index 5db4f4c7485a922fa157c913dd233f68664964fc..55fe9737c2eda68192d1bbd01752b9db23edb60f 100644 --- a/module-sys/Service/Service.hpp +++ b/module-sys/Service/Service.hpp @@ -3,6 +3,7 @@ #pragma once +#include "ServiceForward.hpp" #include "BusProxy.hpp" #include "Common.hpp" // for ReturnCodes, ServicePriority, BusChannels #include "Mailbox.hpp" // for Mailbox @@ -25,19 +26,6 @@ namespace sys { - struct Proxy; - class Timer; - - namespace timer - { - class SystemTimer; - } // namespace timer -} // namespace sys - -namespace sys -{ - using MessageHandler = std::function; - class Service : public cpp_freertos::Thread, public std::enable_shared_from_this { public: diff --git a/module-sys/Service/ServiceForward.hpp b/module-sys/Service/ServiceForward.hpp new file mode 100644 index 0000000000000000000000000000000000000000..71eefd7f8775fcfa0bc200849cb998a0091bf333 --- /dev/null +++ b/module-sys/Service/ServiceForward.hpp @@ -0,0 +1,20 @@ +// 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 "MessageForward.hpp" +#include + +namespace sys +{ + using MessageHandler = std::function; + + struct Proxy; + class Timer; + + namespace timer + { + class SystemTimer; + } // namespace timer +} // namespace sys diff --git a/module-sys/Service/ServiceProxy.hpp b/module-sys/Service/ServiceProxy.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d56733012bad271c1aee76275a399eb700430938 --- /dev/null +++ b/module-sys/Service/ServiceProxy.hpp @@ -0,0 +1,46 @@ +// 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 +#include +#include + +namespace sys +{ + class Service; +} + +namespace service +{ + /// Proxy class for classes using Service raw pointer + /// - initialized in InitHandler + /// - provides weak bounding with Service (to avoid infinite shared ptr loop) + /// - used to provide Class <-> System interface + /// - invalid ServiceProxy will throw runtime error instead of crash on invalid Service* ptr + class ServiceProxy + { + private: + std::weak_ptr service; + + protected: + [[nodiscard]] std::shared_ptr getService() + { + if (auto val = service.lock(); val != nullptr) { + return val; + } + throw std::runtime_error("no service"); + } + + public: + explicit ServiceProxy(std::weak_ptr service) : service(std::move(service)) + {} + ServiceProxy() = default; + virtual ~ServiceProxy() = default; + [[nodiscard]] bool isValid() const noexcept + { + return !service.expired(); + } + }; +} // namespace service diff --git a/module-utils/Split.hpp b/module-utils/Split.hpp new file mode 100644 index 0000000000000000000000000000000000000000..975b6d05bf9675341e16e1f162230af574236b69 --- /dev/null +++ b/module-utils/Split.hpp @@ -0,0 +1,51 @@ +// 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 +#include + +namespace utils +{ + template void split(const std::string &s, char delim, Out result) + { + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) { + *(result++) = item; + } + } + + static inline std::vector split(const std::string &s, char delim) + { + std::vector elems; + split(s, delim, std::back_inserter(elems)); + return elems; + } + + static inline std::vector split(const std::string &s, + const std::string &delimiter, + const bool skipEmptyTokens = true) + { + size_t pos_start = 0, pos_end, delim_len = delimiter.length(); + std::string token; + std::vector res; + uint32_t tokenCount = 0; + + while (((pos_end = s.find(delimiter, pos_start)) != std::string::npos)) { + token = s.substr(pos_start, pos_end - pos_start); + pos_start = pos_end + delim_len; + if (!skipEmptyTokens || !token.empty()) { + tokenCount++; + res.push_back(token); + } + } + + token = s.substr(pos_start); + if (!skipEmptyTokens || !token.empty()) { + res.push_back(token); + } + return res; + } +} // namespace utils diff --git a/module-utils/Utils.hpp b/module-utils/Utils.hpp index e052c855947efb34189ad868e9200410b64d1400..1cec68ce207762b7d2ee38f1a8238d2c05d9facb 100644 --- a/module-utils/Utils.hpp +++ b/module-utils/Utils.hpp @@ -1,7 +1,8 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once +#include "Split.hpp" #include "i18n/i18n.hpp" #include // std::find_if_not #include @@ -29,46 +30,6 @@ namespace utils s << std::setw(sizeof(T) * 2) << std::hex << static_cast(c); return s.str(); } - template void split(const std::string &s, char delim, Out result) - { - std::stringstream ss(s); - std::string item; - while (std::getline(ss, item, delim)) { - *(result++) = item; - } - } - - static inline std::vector split(const std::string &s, char delim) - { - std::vector elems; - split(s, delim, std::back_inserter(elems)); - return elems; - } - - static inline std::vector split(const std::string &s, - const std::string &delimiter, - const bool skipEmptyTokens = true) - { - size_t pos_start = 0, pos_end, delim_len = delimiter.length(); - std::string token; - std::vector res; - uint32_t tokenCount = 0; - - while (((pos_end = s.find(delimiter, pos_start)) != std::string::npos)) { - token = s.substr(pos_start, pos_end - pos_start); - pos_start = pos_end + delim_len; - if (!skipEmptyTokens || !token.empty()) { - tokenCount++; - res.push_back(token); - } - } - - token = s.substr(pos_start); - if (!skipEmptyTokens || !token.empty()) { - res.push_back(token); - } - return res; - } static inline std::string removeNewLines(const std::string &s) {