~aleteoryx/muditaos

fb36efb873fb5158f4c0977617c7c22e7d9fb187 — RobertPiet 5 years ago 2dc0bc3
[EGD-4960] Settings Interface added parameter do distinguish global/app settings
[EGD-4960] global/local setting determined by enum value, unregister all variables in one call, ut updated
[EGD-4960] SettingsScope usage in SettingsMessages
M module-apps/Application.cpp => module-apps/Application.cpp +5 -2
@@ 84,13 84,16 @@ namespace app
        connect(typeid(AppRefreshMessage),
                [this](sys::Message *msg) -> sys::MessagePointer { return handleAppRefresh(msg); });

        settings->registerValueChange(settings::SystemProperties::timeFormat12,
                                      [this](std::string value) { timeFormatChanged(value); });
        settings->registerValueChange(
            settings::SystemProperties::timeFormat12,
            [this](std::string value) { timeFormatChanged(value); },
            settings::SettingsScope::Global);
    }

    Application::~Application() noexcept
    {
        windowsStack.windows.clear();
        settings->unregisterValueChange();
    }

    Application::State Application::getState()

M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +9 -4
@@ 323,11 323,15 @@ namespace app
            std::make_shared<sdesktop::UpdateOsMessage>(updateos::UpdateMessageType::UpdateCheckForUpdateOnce);
        sys::Bus::SendUnicast(msgToSend, service::name::service_desktop, this);

        settings->registerValueChange(settings::SystemProperties::activeSim,
                                      [this](std::string value) { activeSimChanged(value); });
        settings->registerValueChange(
            settings::SystemProperties::activeSim,
            [this](std::string value) { activeSimChanged(value); },
            settings::SettingsScope::Global);
        Store::GSM::get()->selected = Store::GSM::SIM::NONE;
        settings->registerValueChange(settings::SystemProperties::lockPassHash,
                                      [this](std::string value) { lockPassHashChanged(value); });
        settings->registerValueChange(
            settings::SystemProperties::lockPassHash,
            [this](std::string value) { lockPassHashChanged(value); },
            settings::SettingsScope::Global);

        return sys::ReturnCodes::Success;
    }


@@ 335,6 339,7 @@ namespace app
    sys::ReturnCodes ApplicationDesktop::DeinitHandler()
    {
        LOG_INFO("DeinitHandler");
        settings->unregisterValueChange();
        return sys::ReturnCodes::Success;
    }


M module-apps/application-settings/ApplicationSettings.cpp => module-apps/application-settings/ApplicationSettings.cpp +11 -8
@@ 47,16 47,18 @@ namespace app
            switchWindow(app::sim_select);
            return msgHandled();
        });
        settings->registerValueChange(settings::SystemProperties::lockPassHash,
                                      [this](std::string value) { lockPassChanged(value); });
        settings->registerValueChange(settings::SystemProperties::timeDateFormat,
                                      [this](std::string value) { timeDateChanged(value); });
        settings->registerValueChange(
            settings::SystemProperties::lockPassHash,
            [this](std::string value) { lockPassChanged(value); },
            settings::SettingsScope::Global);
        settings->registerValueChange(
            settings::SystemProperties::timeDateFormat,
            [this](std::string value) { timeDateChanged(value); },
            settings::SettingsScope::Global);
    }

    ApplicationSettings::~ApplicationSettings()
    {
        settings->unregisterValueChange(settings::SystemProperties::lockPassHash);
        settings->unregisterValueChange(settings::SystemProperties::timeDateFormat);
    }

    // Invoked upon receiving data message


@@ 173,13 175,14 @@ namespace app

    void ApplicationSettings::setPin(unsigned int value)
    {
        settings->setValue(settings::SystemProperties::lockPassHash, std::to_string(value));
        settings->setValue(
            settings::SystemProperties::lockPassHash, std::to_string(value), settings::SettingsScope::Global);
        lockPassHash = value;
    }

    void ApplicationSettings::clearPin()
    {
        settings->setValue(settings::SystemProperties::lockPassHash, "");
        settings->setValue(settings::SystemProperties::lockPassHash, "", settings::SettingsScope::Global);
        lockPassHash = 0U;
    }


M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +16 -8
@@ 106,12 106,18 @@ namespace app::manager
    {
        registerMessageHandlers();
        blockingTimer->connect([this](sys::Timer &) { onPhoneLocked(); });
        settings->registerValueChange(settings::SystemProperties::displayLanguage,
                                      [this](std::string value) { displayLanguageChanged(value); });
        settings->registerValueChange(settings::SystemProperties::inputLanguage,
                                      [this](std::string value) { inputLanguageChanged(value); });
        settings->registerValueChange(settings::SystemProperties::lockTime,
                                      [this](std::string value) { lockTimeChanged(value); });
        settings->registerValueChange(
            settings::SystemProperties::displayLanguage,
            [this](std::string value) { displayLanguageChanged(value); },
            settings::SettingsScope::Global);
        settings->registerValueChange(
            settings::SystemProperties::inputLanguage,
            [this](std::string value) { inputLanguageChanged(value); },
            settings::SettingsScope::Global);
        settings->registerValueChange(
            settings::SystemProperties::lockTime,
            [this](std::string value) { lockTimeChanged(value); },
            settings::SettingsScope::Global);
    }

    sys::ReturnCodes ApplicationManager::InitHandler()


@@ 161,6 167,7 @@ namespace app::manager

    sys::ReturnCodes ApplicationManager::DeinitHandler()
    {
        settings->unregisterValueChange();
        closeApplications();
        closeServices();
        return sys::ReturnCodes::Success;


@@ 540,7 547,8 @@ namespace app::manager
            return false;
        }
        displayLanguage = requestedLanguage;
        settings->setValue(settings::SystemProperties::displayLanguage, displayLanguage);
        settings->setValue(
            settings::SystemProperties::displayLanguage, displayLanguage, settings::SettingsScope::Global);
        utils::localize.setDisplayLanguage(displayLanguage);
        rebuildActiveApplications();
        return true;


@@ 555,7 563,7 @@ namespace app::manager
            return false;
        }
        inputLanguage = requestedLanguage;
        settings->setValue(settings::SystemProperties::inputLanguage, inputLanguage);
        settings->setValue(settings::SystemProperties::inputLanguage, inputLanguage, settings::SettingsScope::Global);
        utils::localize.setInputLanguage(inputLanguage);
        return true;
    }

M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +3 -1
@@ 1284,7 1284,9 @@ bool ServiceCellular::handleSimState(at::SimState state, const std::string messa
    switch (state) {
    case at::SimState::Ready:
        Store::GSM::get()->sim = Store::GSM::get()->selected;
        settings->setValue(settings::SystemProperties::activeSim, utils::enumToString(Store::GSM::get()->selected));
        settings->setValue(settings::SystemProperties::activeSim,
                           utils::enumToString(Store::GSM::get()->selected),
                           settings::SettingsScope::Global);
        // SIM causes SIM INIT, only on ready
        response =
            std::move(std::make_unique<CellularNotificationMessage>(CellularNotificationMessage::Type::SIM_READY));

M module-services/service-db/agents/settings/Settings.cpp => module-services/service-db/agents/settings/Settings.cpp +44 -23
@@ 52,9 52,9 @@ namespace settings
    {
        LOG_DEBUG("handleVariableChanged");
        if (auto msg = dynamic_cast<settings::Messages::VariableChanged *>(req)) {
            auto key = msg->getPath().variable;
            auto key = msg->getPath();
            auto val = msg->getValue();
            LOG_DEBUG("handleVariableChanged: (k=v): (%s=%s)", key.c_str(), val.value_or("").c_str());
            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;


@@ 62,13 62,13 @@ namespace settings
                    // in case of two callbacks there is a need to duplicate the value
                    auto value = std::move(val.value_or(""));
                    cb(std::string{value});
                    cbWithName(key, std::move(value));
                    cbWithName(key.variable, std::move(value));
                }
                else if (nullptr != cb) {
                    cb(std::move(val.value_or("")));
                }
                else {
                    cbWithName(key, std::move(val.value_or("")));
                    cbWithName(key.variable, std::move(val.value_or("")));
                }
            }
        }


@@ 115,56 115,77 @@ namespace settings
        return std::make_shared<sys::ResponseMessage>();
    }

    void Settings::registerValueChange(const std::string &variableName, ValueChangedCallback cb)
    void Settings::registerValueChange(const std::string &variableName, ValueChangedCallback cb, SettingsScope scope)
    {
        ValueCb::iterator it_cb = cbValues.find(variableName);
        if (cbValues.end() != it_cb && nullptr != it_cb->second.first) {
            LOG_INFO("Callback function on value change (%s) already exists, rewriting", variableName.c_str());
        }
        cbValues[variableName].first = cb;
        EntryPath path;
        path.variable = variableName;
        path.service  = app->GetName();
        path.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());
        }
        cbValues[path].first = cb;

        auto msg      = std::make_shared<settings::Messages::RegisterOnVariableChange>(path);
        sendMsg(std::move(msg));
    }

    void Settings::registerValueChange(const std::string &variableName, ValueChangedCallbackWithName cb)
    void Settings::registerValueChange(const std::string &variableName,
                                       ValueChangedCallbackWithName cb,
                                       SettingsScope scope)
    {
        auto it_cb = cbValues.find(variableName);
        if (cbValues.end() != it_cb && nullptr != it_cb->second.second) {
            LOG_INFO("Callback function on value change (%s) already exists, rewriting", variableName.c_str());
        }
        cbValues[variableName].second = cb;
        EntryPath path;
        path.variable = variableName;
        path.service  = app->GetName();
        path.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());
        }
        cbValues[path].second = cb;

        auto msg      = std::make_shared<settings::Messages::RegisterOnVariableChange>(path);
        sendMsg(std::move(msg));
    }

    void Settings::unregisterValueChange(const std::string &variableName)
    void Settings::unregisterValueChange(const std::string &variableName, SettingsScope scope)
    {
        ValueCb::iterator it_cb = cbValues.find(variableName);
        EntryPath path;
        path.variable = variableName;
        path.service  = app->GetName();
        path.scope    = scope;

        auto it_cb = cbValues.find(path);
        if (cbValues.end() == it_cb) {
            LOG_INFO("Callback function on value change (%s) does not exist", variableName.c_str());
            LOG_INFO("Callback function on value change (%s) does not exist", path.to_string().c_str());
        }
        else {
            cbValues.erase(it_cb);
        }

        EntryPath path;
        path.variable = variableName;
        path.service  = app->GetName();
        auto msg      = std::make_shared<settings::Messages::UnregisterOnVariableChange>(path);
        sendMsg(std::move(msg));
    }

    void Settings::setValue(const std::string &variableName, const std::string &variableValue)
    void Settings::unregisterValueChange()
    {
        for (auto it_cb : cbValues) {
            auto msg = std::make_shared<settings::Messages::UnregisterOnVariableChange>(it_cb.first);
            sendMsg(std::move(msg));
        }
        cbValues.clear();
        LOG_INFO("Unregistered all settings variable change on application (%s)", app->GetName().c_str());
    }

    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<settings::Messages::SetVariable>(path, variableValue);
        sendMsg(std::move(msg));
    }

M module-services/service-db/agents/settings/SettingsAgent.cpp => module-services/service-db/agents/settings/SettingsAgent.cpp +13 -26
@@ 4,8 4,6 @@
#include "SettingsAgent.hpp"
#include "Settings_queries.hpp"

#include <service-db/SettingsMessages.hpp>

#include <Database/Database.hpp>
#include <Service/Service.hpp>
#include <module-sys/Service/Bus.hpp>


@@ 24,16 22,6 @@ SettingsAgent::SettingsAgent(sys::Service *parentService) : DatabaseAgent(parent

void SettingsAgent::initDb()
{
    auto notifications = database->query(settings::Statements::getAllNotifications);
    if (nullptr == notifications || 0 == notifications->getRowCount()) {
        return;
    }
    do {
        variableChangeRecipents[(*notifications)[0].getString()].insert((*notifications)[1].getString());
        /*what about mode/profile
        modeChangeRecipents;
        profileChangeRecipents;*/
    } while (notifications->nextRow());
}

void SettingsAgent::deinitDb()


@@ 95,8 83,7 @@ auto SettingsAgent::getAgentName() -> const std::string
// dbSingleVar
auto SettingsAgent::dbGetValue(settings::EntryPath path) -> std::optional<std::string>
{
    // auto retQuery = database->query(settings::Statements::getValue, path.to_string());
    auto retQuery = database->query(settings::Statements::getValue, path.variable.c_str());
    auto retQuery = database->query(settings::Statements::getValue, path.to_string().c_str());
    if (nullptr == retQuery || 1 != retQuery->getRowCount()) {
        return std::string{};
    }


@@ 106,17 93,18 @@ auto SettingsAgent::dbGetValue(settings::EntryPath path) -> std::optional<std::s
auto SettingsAgent::dbSetValue(settings::EntryPath path, std::string value) -> bool
{
    /// insert or update
    return database->execute(settings::Statements::insertValue, path.variable.c_str(), value.c_str());
    return database->execute(settings::Statements::insertValue, path.to_string().c_str(), value.c_str());
}

auto SettingsAgent::dbRegisterValueChange(settings::EntryPath path) -> bool
{
    return database->execute(settings::Statements::setNotification, path.variable.c_str(), path.service.c_str());
    return database->execute(settings::Statements::setNotification, path.to_string().c_str(), path.service.c_str());
}

auto SettingsAgent::dbUnregisterValueChange(settings::EntryPath path) -> bool
{
    return database->execute(settings::Statements::clearNotificationdRow, path.variable.c_str());
    return database->execute(
        settings::Statements::clearNotificationdRow, path.to_string().c_str(), path.service.c_str());
}

// db Profile


@@ 223,12 211,11 @@ auto SettingsAgent::handleSetVariable(sys::Message *req) -> sys::MessagePointer
        auto oldValue = dbGetValue(path);
        if (oldValue.has_value() && oldValue.value() != value) {
            dbSetValue(path, value);
            // for (auto service : variableChangeRecipents[path.to_string()]) {
            for (auto service : variableChangeRecipents[path.variable]) {
                if (service != path.service) {
            for (auto regPath : variableChangeRecipents[path.to_string()]) {
                if (regPath.service != path.service) {
                    auto updateMsg =
                        std::make_shared<settings::Messages::VariableChanged>(path, value, oldValue.value_or(""));
                    sys::Bus::SendUnicast(std::move(updateMsg), service, parentService);
                        std::make_shared<settings::Messages::VariableChanged>(regPath, value, oldValue.value_or(""));
                    sys::Bus::SendUnicast(std::move(updateMsg), regPath.service, parentService);
                }
            }
        }


@@ 242,14 229,14 @@ auto SettingsAgent::handleRegisterOnVariableChange(sys::Message *req) -> sys::Me
        auto path = msg->getPath();
        if (dbRegisterValueChange(path)) {
            auto it = variableChangeRecipents.find(path.to_string());
            if (variableChangeRecipents.end() == it || it->second.end() == it->second.find(path.service)) {
                variableChangeRecipents[path.to_string()] = {path.service};
            if (variableChangeRecipents.end() == it || it->second.end() == it->second.find(path)) {
                variableChangeRecipents[path.to_string()] = {path};
                auto currentValue                         = dbGetValue(path).value_or("");
                auto msgValue = std::make_shared<::settings::Messages::VariableChanged>(path, currentValue, "");
                sys::Bus::SendUnicast(std::move(msgValue), msg->sender, parentService);
            }
            else {
                it->second.insert(path.service);
                it->second.insert(path);
            }
        }
    }


@@ 263,7 250,7 @@ auto SettingsAgent::handleUnregisterOnVariableChange(sys::Message *req) -> sys::
        if (dbUnregisterValueChange(path)) {
            auto it = variableChangeRecipents.find(path.to_string());
            if (variableChangeRecipents.end() != it) {
                it->second.erase(path.service);
                it->second.erase(path);
            }
        }
    }

M module-services/service-db/agents/settings/SettingsAgent.hpp => module-services/service-db/agents/settings/SettingsAgent.hpp +2 -1
@@ 32,7 32,8 @@ class SettingsAgent : public DatabaseAgent
    auto getAgentName() -> const std::string override;

  private:
    using MapOfRecipentsToBeNotified = std::map<std::string, std::set<std::string>>;
    // using MapOfRecipentsToBeNotified = std::map<std::string, std::set<std::string>>;
    using MapOfRecipentsToBeNotified = std::map<std::string, std::set<settings::EntryPath>>;
    MapOfRecipentsToBeNotified variableChangeRecipents;
    using SetOfRecipents = std::set<std::string>;
    SetOfRecipents profileChangedRecipents;

M module-services/service-db/service-db/Settings.hpp => module-services/service-db/service-db/Settings.hpp +15 -10
@@ 5,6 5,8 @@

#include <module-sys/Service/Message.hpp>
#include <service-db/DBServiceName.hpp>
#include "SettingsScope.hpp"
#include "SettingsMessages.hpp"

#include <cstdint>
#include <functional>


@@ 16,11 18,6 @@

namespace settings
{
    namespace Messages
    {
        class SettingsMessage;
    }

    class Settings
    {
      public:


@@ 36,10 33,18 @@ namespace settings
        Settings(sys::Service *app, const std::string &dbAgentName = service::name::db);
        virtual ~Settings();

        void setValue(const std::string &variableName, const std::string &variableValue);
        void registerValueChange(const std::string &variableName, ValueChangedCallback cb);
        void registerValueChange(const std::string &variableName, ValueChangedCallbackWithName cb);
        void unregisterValueChange(const std::string &variableName);
        void setValue(const std::string &variableName,
                      const std::string &variableValue,
                      SettingsScope scope = SettingsScope::AppLocal);
        void registerValueChange(const std::string &variableName,
                                 ValueChangedCallback cb,
                                 SettingsScope scope = SettingsScope::AppLocal);
        void registerValueChange(const std::string &variableName,
                                 ValueChangedCallbackWithName cb,
                                 SettingsScope scope = SettingsScope::AppLocal);
        void unregisterValueChange(const std::string &variableName, SettingsScope scope = SettingsScope::AppLocal);
        /// unregisters all registered variables (both global and local)
        void unregisterValueChange();

        void getAllProfiles(OnAllProfilesRetrievedCallback cb);
        void setCurrentProfile(const std::string &profile);


@@ 61,7 66,7 @@ namespace settings
        std::string phoneMode;
        std::string profile;

        using ValueCb = std::map<std::string, std::pair<ValueChangedCallback, ValueChangedCallbackWithName>>;
        using ValueCb = std::map<EntryPath, std::pair<ValueChangedCallback, ValueChangedCallbackWithName>>;
        ValueCb cbValues;
        ModeChangedCallback cbMode;
        OnAllModesRetrievedCallback cbAllModes;

M module-services/service-db/service-db/SettingsMessages.hpp => module-services/service-db/service-db/SettingsMessages.hpp +30 -0
@@ 5,6 5,7 @@

#include <MessageType.hpp>
#include <Service/Message.hpp>
#include <service-db/SettingsScope.hpp>

#include <list>
#include <memory>


@@ 20,11 21,40 @@ namespace settings
        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;
        }

        bool operator<(const EntryPath &other) const
        {
            if (mode < other.mode)
                return true;
            if (mode > other.mode)
                return false;
            if (service < other.service)
                return true;
            if (service > other.service)
                return false;
            if (profile < other.profile)
                return true;
            if (profile > other.profile)
                return false;
            if (variable < other.variable)
                return true;
            if (variable > other.variable)
                return false;
            if (scope < other.scope)
                return true;
            if (scope > other.scope)
                return false;
            return false;
        }
    };

    namespace Messages

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

#pragma once
namespace settings
{
    enum class SettingsScope
    {
        Global,
        AppLocal
    };
}

M module-services/service-db/test/test-service-db-settings-messages.cpp => module-services/service-db/test/test-service-db-settings-messages.cpp +4 -4
@@ 118,13 118,13 @@ TEST_CASE("Settings Messages")
        settings::Service settings("settings");
        settings.InitHandler();

        sys::Bus::SendUnicast(std::make_shared<settings::Messages::RegisterOnVariableChange>(
                                  settings::EntryPath({"mode", "service", "profile", "variable"})),
        sys::Bus::SendUnicast(std::make_shared<settings::Messages::RegisterOnVariableChange>(settings::EntryPath(
                                  {"mode", "service", "profile", "variable", settings::SettingsScope::AppLocal})),
                              "db-worker",
                              &settings);

        sys::Bus::SendUnicast(std::make_shared<settings::Messages::UnregisterOnVariableChange>(
                                  settings::EntryPath({"mode", "service", "profile", "variable"})),
        sys::Bus::SendUnicast(std::make_shared<settings::Messages::UnregisterOnVariableChange>(settings::EntryPath(
                                  {"mode", "service", "profile", "variable", settings::SettingsScope::AppLocal})),
                              "db-worker",
                              &settings);
    }

M module-services/service-db/test/test-service-db-settings-testservices.hpp => module-services/service-db/test/test-service-db-settings-testservices.hpp +6 -4
@@ 28,26 28,28 @@ namespace settings
            if (auto msg = dynamic_cast<settings::UTMsg::ReqRegValChg *>(req)) {
                debug("ReqRegValChg", msg->name, msg->value);
                whoRequestedNotifyOnChange = msg->sender;
                mySettings->registerValueChange(msg->name, ([this](std::string value) {
                mySettings->registerValueChange(msg->name,
                                                ([this](std::string value) {
                                                    ValueChanged(value);
                                                    auto cnf = std::make_shared<settings::UTMsg::CnfValChg>("", value);
                                                    sys::Bus::SendUnicast(
                                                        std::move(cnf), whoRequestedNotifyOnChange, this);
                                                }));
                                                }),
                                                settings::SettingsScope::Global);
                auto cnf = std::make_shared<settings::UTMsg::CnfRegValChg>(msg->name, msg->value);
                sys::Bus::SendUnicast(std::move(cnf), whoRequestedNotifyOnChange, this);
            }
            else if (auto msg = dynamic_cast<settings::UTMsg::ReqUnRegValChg *>(req)) {
                // unregister
                debug("ReqUnRegValChg", msg->name, msg->value);
                mySettings->unregisterValueChange(msg->name);
                mySettings->unregisterValueChange(msg->name, settings::SettingsScope::Global);
                auto cnf = std::make_shared<settings::UTMsg::CnfUnRegValChg>(msg->name, msg->value);
                sys::Bus::SendUnicast(std::move(cnf), msg->sender, this);
            }
            else if (auto msg = dynamic_cast<settings::UTMsg::ReqSetVal *>(req)) {
                // set value
                debug("ReqSetVal", msg->name, msg->value);
                mySettings->setValue(msg->name, msg->value);
                mySettings->setValue(msg->name, msg->value, settings::SettingsScope::Global);
                auto cnf = std::make_shared<settings::UTMsg::CnfReqSetVal>(msg->name, msg->value);
                sys::Bus::SendUnicast(std::move(cnf), msg->sender, this);
            }