<xs:restriction base="xs:string">
<xs:enumeration value="none"/>
<xs:enumeration value="lock"/>
+ <xs:enumeration value="essential"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
MODES_NAMESPACE_USE;
Action::Action()
- : isChanged(false), type(SYNC), plugin(nullptr), piAction(nullptr), stopOnErr(false), restriction(REQ_NONE), locked(false)
+ : isChanged(false), type(SYNC), plugin(nullptr), piAction(nullptr), stopOnErr(false), restriction(NONE), locked(false)
{
}
Action::Action(const std::string &name)
- : ruleName(name), isChanged(false), type(SYNC), plugin(nullptr), piAction(nullptr), stopOnErr(false), restriction(REQ_NONE), locked(false)
+ : ruleName(name), isChanged(false), type(SYNC), plugin(nullptr), piAction(nullptr), stopOnErr(false), restriction(NONE), locked(false)
{
}
return privilege;
}
+void Action::attachObserver(ActionObserver *obs)
+{
+ observers.push_back(obs);
+}
+
+void Action::detachObserver(ActionObserver *obs)
+{
+ observers.remove(obs);
+}
+
+void Action::notifyObservers()
+{
+ piAction->unSetChangedCallback(valueChangedCallback, this);
+ isChanged = true;
+
+ for (auto it = observers.begin(); it != observers.end(); ++it)
+ (*it)->update(ruleName);
+}
+
void Action::valueChangedCallback(void *userData)
{
Action *action = (Action*)userData;
RET_IF(NULL == action);
- action->isChanged = true;
- action->piAction->unSetChangedCallback(valueChangedCallback, userData);
+ action->notifyObservers();
+
DBG("Action(%s) Changed", action->ruleName.c_str());
}
*/
#pragma once
+#include <list>
#include <string>
#include "mdss.h"
#include "Plugin.h"
#include "PluginAction.h"
+#include "ActionObserver.h"
MODES_NAMESPACE_BEGIN
class Action {
public:
typedef enum {
- REQ_NONE,
- REQ_LOCK
+ NONE,
+ LOCK,
+ ESSENTIAL
} ActionRestrict;
typedef enum {
void setPlugin(Plugin *pi);
void setPrivilege(const std::string &val);
std::string getPrivilege();
+ void attachObserver(ActionObserver *obs);
+ void detachObserver(ActionObserver *obs);
virtual int setValue(const std::string &val) = 0;
virtual std::string getStringOfValue() = 0;
virtual int apply() = 0;
Plugin *plugin;
PluginAction *piAction;
private:
+ void notifyObservers();
std::string id;
std::string privilege;
bool stopOnErr;
ActionRestrict restriction;
bool locked;
+ std::list<ActionObserver*> observers;
};
MODES_NAMESPACE_END
--- /dev/null
+/*
+ * Copyright (c) 2019-2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <string>
+#include "mdss.h"
+
+MODES_NAMESPACE_BEGIN
+
+class ActionObserver {
+public:
+ virtual void update(const std::string &rule) = 0;
+};
+
+MODES_NAMESPACE_END
MODES_NAMESPACE_USE;
guint ClientConnection::ownerId = 0;
-mdsDbus* ClientConnection::dbusHandle = NULL;
-
-void ClientConnection::addRequestHandler(const std::string &method, GCallback cb)
-{
- g_signal_connect(dbusHandle, method.c_str(), cb, NULL);
-}
-
-void ClientConnection::onBusAcquired(GDBusConnection *conn, const gchar *name, gpointer userData)
-{
- GError *error = NULL;
-
- g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(dbusHandle),
- conn, MODES_DBUS_OBJPATH, &error);
- if (error) {
- ERR("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
- g_error_free(error);
- }
-}
+mdsDbus *ClientConnection::dbusHandle = NULL;
void ClientConnection::startDbus()
{
dbusHandle = NULL;
ownerId = 0;
}
+
+void ClientConnection::addRequestHandler(const std::string &method, GCallback cb)
+{
+ g_signal_connect(dbusHandle, method.c_str(), cb, NULL);
+}
+
+void ClientConnection::update(const std::string &name, ModeState state)
+{
+ mds_dbus_emit_changed_mode(dbusHandle, name.c_str(), state);
+}
+
+void ClientConnection::onBusAcquired(GDBusConnection *conn, const gchar *name, gpointer userData)
+{
+ GError *error = NULL;
+
+ g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(dbusHandle),
+ conn, MODES_DBUS_OBJPATH, &error);
+ if (error) {
+ ERR("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
+ g_error_free(error);
+ }
+}
#include <string>
#include "common/dbus.h"
#include "mdss.h"
+#include "ModeObserver.h"
MODES_NAMESPACE_BEGIN
-class ClientConnection {
+class ClientConnection : public ModeObserver {
public:
void startDbus();
void stopDbus();
void addRequestHandler(const std::string &method, GCallback cb);
+ void update(const std::string &name, ModeState state);
private:
static void onBusAcquired(GDBusConnection *conn,
const gchar *name, gpointer user_data);
MODES_NAMESPACE_USE;
Mode::Mode()
- : type(MODE_NORMAL), hidden(false)
+ : type(MODE_NORMAL), hidden(false), essential(false)
{
}
return hidden;
}
+void Mode::setEssential(bool val)
+{
+ essential = val;
+}
+
+bool Mode::hasEssential() const
+{
+ return essential;
+}
+
int Mode::apply()
{
std::list<std::shared_ptr<Action>>::iterator it;
void setHidden(bool val);
bool isHidden() const;
+ void setEssential(bool val);
+ bool hasEssential() const;
+
void addAction(Action *action);
std::list<std::shared_ptr<Action>> getActionList() const;
std::string name;
ModeType type;
bool hidden;
+ bool essential;
std::list<std::shared_ptr<Action>> actionList;
std::list<std::shared_ptr<Action>> undoList;
#ifdef MDS_TEST
for (auto actionIt = actionList.begin(); actionIt != actionList.end(); actionIt++)
if ((*actionIt)->getRuleName() == ruleName
- && (*actionIt)->getRestrict() == Action::REQ_LOCK) {
+ && (*actionIt)->getRestrict() == Action::LOCK) {
ERR("%s is restricted", ruleName.c_str());
return true;
}
bool isExclusive();
bool checkConflictAction(const Mode &mode);
private:
+ void handleEssentialAction();
bool findLockedAction(const std::string &ruleName);
std::map<std::string, Mode> savedModes;
std::string undoDir;
#include <exception>
#include "mdss.h"
#include "ModesEx.h"
+#include "ModeObserver.h"
+#include "XMLGenerator.h"
#include "ModeXMLParser.h"
#include "UndoInfoParser.h"
-#include "XMLGenerator.h"
#include "ConflictManager.h"
using std::string;
void ModeManager::init()
{
modeMap.clear();
+ essentialMap.clear();
for (auto it = modeDirList.begin(); it != modeDirList.end(); ++it) {
makeModeMap(*it);
DBG("[%d] modeName : %s, modePath : %s, hidden : %s", modeMap.size(), modeName.c_str(), path.c_str(), hidden? "true": "false");
}
+bool ModeManager::handleEssentialAction(const Mode &mode)
+{
+ bool stopOnErr = false;
+ std::list<std::shared_ptr<Action>> actionList = mode.getActionList();
+ for (auto it = actionList.begin(); it != actionList.end(); it++) {
+ if ((*it)->getRestrict() == Action::ESSENTIAL) {
+ essentialMap.insert(std::make_pair(mode.getName(), (*it)->getRuleName()));
+ (*it)->attachObserver(this);
+ }
+ }
+ return stopOnErr;
+}
+
int ModeManager::applyMode(const string &modeName, ClientPrivilege &priv, bool isTest)
{
auto found = modeMap.find(modeName);
return ret;
}
careTaker.pushMode(mode);
+ if (mode.hasEssential())
+ handleEssentialAction(mode);
}
} catch (ModesEx &e) {
//Ususally, it is reached by Invalid Mode File
ERR("apply Fail(%s)", e.what());
return MODES_ERROR_NO_DATA;
}
+ notifyObservers(modeName, ModeObserver::ON);
return MODES_ERROR_NONE;
}
return ret;
}
mode.undo();
+ for (auto it = essentialMap.begin(); it != essentialMap.end(); ) {
+ if (it->second == modeName)
+ it = essentialMap.erase(it);
+ else
+ ++it;
+ }
+ notifyObservers(modeName, ModeObserver::OFF);
return MODES_ERROR_NONE;
}
return modeList;
}
+void ModeManager::attachObserver(ModeObserver *obs)
+{
+ observers.push_back(obs);
+}
+
+void ModeManager::detachObserver(ModeObserver *obs)
+{
+ observers.remove(obs);
+}
+
+void ModeManager::notifyObservers(const string &modeName, ModeObserver::ModeState state)
+{
+ for (auto it = observers.begin(); it != observers.end(); ++it)
+ (*it)->update(modeName, state);
+}
+
+void ModeManager::update(const std::string &rule)
+{
+ auto found = essentialMap.find(rule);
+ if (essentialMap.end() == found) {
+ ERR("No Mode related with essential rule(%s)", rule.c_str());
+ throw ModesEx(ModesEx::NO_DATA);
+ }
+
+ undoMode(found->second);
+}
+
bool ModeManager::makeModeMap(const string &dirPath)
{
DBG("dirPath : [%s]", dirPath.c_str());
modeDirList.insert(dirPath);
}
+
#include "ModeParser.h"
#include "RuleManager.h"
#include "ModeCareTaker.h"
+#include "ModeObserver.h"
+#include "ActionObserver.h"
#include "ClientPrivilege.h"
+
#ifndef MODES_MODE_DEFAULT_DIR
#define MODES_MODE_DEFAULT_DIR "/usr/share/modes/mode"
#warning "MODES_MODE_DEFAULT_DIR is redefined"
MODES_NAMESPACE_BEGIN
-class ModeManager {
+class ModeManager : public ActionObserver {
public:
ModeManager(RuleManager &rMgr);
int registerMode(const Mode &mode);
int undoMode(const std::string &modeName);
std::list<std::tuple<std::string, int>> getModes();
+ void attachObserver(ModeObserver *obs);
+ void detachObserver(ModeObserver *obs);
+ void update(const std::string &rule);
private:
+ bool handleEssentialAction(const Mode &mode);
+ void notifyObservers(const std::string &modeName, ModeObserver::ModeState state);
bool makeModeMap(const std::string &dirPath);
bool restoreUndoInfo(const std::string &dirPath);
void addModeAttributes(ModeParser *parser, const std::string &path);
ModeParser* getModeParser(const std::string &path);
std::map<std::string, std::pair<std::string, bool>> modeMap;
+ std::map<std::string, std::string> essentialMap;
std::set<std::string> modeDirList;
std::string undoDir;
std::string modeSyntaxFile;
RuleManager &ruleMgr;
ModeCareTaker careTaker;
-
+ std::list<ModeObserver*> observers;
#ifdef MDS_TEST
friend class ModeManagerTest;
friend class ConflictTest;
--- /dev/null
+/*
+ * Copyright (c) 2019-2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <string>
+#include "mdss.h"
+
+MODES_NAMESPACE_BEGIN
+
+class ModeObserver {
+public:
+ typedef enum {
+ OFF = 0,
+ ON = 1
+ } ModeState;
+ virtual void update(const std::string &mode, ModeState state) = 0;
+};
+
+MODES_NAMESPACE_END
void ModeXMLParser::parseActionAttr(xmlNodePtr node, Action *action)
{
- char *restictProp = (char*)xmlGetProp(node, ModesXMLTag::RESTICT);
- if (restictProp && MDS_EQUAL == strcmp(restictProp, ModesXMLTag::RESTICT_LOCK))
- action->setRestrict(Action::REQ_LOCK);
- else
- action->setRestrict(Action::REQ_NONE);
- xmlFree(restictProp);
+ char *restictProp = (char*)xmlGetProp(node, ModesXMLTag::RESTRICT);
+ action->setRestrict(Action::NONE);
+ if (restictProp) {
+ if (MDS_EQUAL == strcmp(restictProp, ModesXMLTag::RESTRICT_LOCK)) {
+ action->setRestrict(Action::LOCK);
+ } else if (MDS_EQUAL == strcmp(restictProp, ModesXMLTag::RESTRICT_ESSENTIAL)) {
+ action->setRestrict(Action::ESSENTIAL);
+ mode.setEssential(true);
+ }
+
+ xmlFree(restictProp);
+ }
char *stopOnErrProp = (char*)xmlGetProp(node, ModesXMLTag::STOP_ON_ERR);
if (stopOnErrProp && MDS_EQUAL == strcmp(stopOnErrProp, "true"))
const xmlChar* const ModesXMLTag::UNDO = (xmlChar*)"undo";
const xmlChar* const ModesXMLTag::RULE = (xmlChar*)"rule";
const xmlChar* const ModesXMLTag::STOP_ON_ERR = (xmlChar*)"stopOnErr";
-const xmlChar* const ModesXMLTag::RESTICT = (xmlChar*)"restrict";
-const char* const ModesXMLTag::RESTICT_LOCK = "lock";
+const xmlChar* const ModesXMLTag::RESTRICT = (xmlChar*)"restrict";
+const char* const ModesXMLTag::RESTRICT_LOCK = "lock";
+const char* const ModesXMLTag::RESTRICT_ESSENTIAL = "essential";
const xmlChar* const ModesXMLTag::ID = (xmlChar*)"ID";
//UndoInfo
const xmlChar* const ModesXMLTag::UNDO_INFO = (xmlChar*)"UndoInfo";
static const xmlChar* const UNDO;
static const xmlChar* const RULE;
static const xmlChar* const STOP_ON_ERR;
- static const xmlChar* const RESTICT;
- static const char* const RESTICT_LOCK;
+ static const xmlChar* const RESTRICT;
+ static const char* const RESTRICT_LOCK;
+ static const char* const RESTRICT_ESSENTIAL;
static const xmlChar* const ID;
//UndoInfo
static const xmlChar* const UNDO_INFO;
MODES_NAMESPACE_USE;
-ModeManager* RequestHandler::modeMgr = NULL;
+ModeManager *RequestHandler::modeMgr = NULL;
RuleManager *RequestHandler::ruleMgr = NULL;
void RequestHandler::setModeManager(ModeManager *mgr)
int ret = modeMgr->applyMode(modeName, privInfo, false);
mds_dbus_complete_apply_mode(object, invocation, ret);
- if (MODES_ERROR_NONE == ret)
- mds_dbus_emit_changed_mode(object, modeName, 1);
return TRUE;
}
int ret = modeMgr->undoMode(modeName);
mds_dbus_complete_undo_mode(object, invocation, ret);
- if (MODES_ERROR_NONE == ret)
- mds_dbus_emit_changed_mode(object, modeName, 0);
return TRUE;
}
if (id)
action->setID(id);
- action->setRestrict(Action::REQ_NONE); //It is not allowed to set Restrict of Action by API.
+ action->setRestrict(Action::NONE); //It is not allowed to set Restrict of Action by API.
action->setValue(val);
action->printInfo();
clientConn.startDbus();
ruleMgr.start();
modeMgr.init();
+ modeMgr.attachObserver(&clientConn);
}
catch (ModesEx &e) {
ERR("Supervisor init() Fail(%s)", e.what());
void Supervisor::deInit()
{
+ modeMgr.detachObserver(&clientConn);
ruleMgr.stop();
clientConn.stopDbus();
RequestHandler::setModeManager(NULL);
RETVM_IF(NULL == plugin, MODES_ERROR_NO_DATA, "Action(%s) : No plugin", ruleName.c_str());
int pos = ruleName.find_first_of(".");
- PluginAction *tmpAction = plugin->getUndoAction(ruleName.substr(pos + 1), info);
- if (nullptr == tmpAction) {
+ piAction = plugin->getUndoAction(ruleName.substr(pos + 1), info);
+ if (nullptr == piAction) {
ERR("plugin(%s) getUndoAction() Fail", plugin->getName().c_str());
return MODES_ERROR_NOT_SUPPORTED;
}
- tmpAction->setChangedCallback(valueChangedCallback, this);
+ piAction->setChangedCallback(valueChangedCallback, this);
- piAction = tmpAction;
return MODES_ERROR_NONE;
}
xmlSetProp(actionNode, ModesXMLTag::RULE, (xmlChar*)(*it)->getRuleName().c_str());
- if (restriction == Action::ActionRestrict::REQ_LOCK)
- xmlSetProp(actionNode, ModesXMLTag::RESTICT, (xmlChar*)ModesXMLTag::RESTICT_LOCK);
+ if (restriction == Action::ActionRestrict::LOCK)
+ xmlSetProp(actionNode, ModesXMLTag::RESTRICT, (xmlChar*)ModesXMLTag::RESTRICT_LOCK);
xmlNodeSetContent(actionNode, (xmlChar*)(*it)->getStringOfValue().c_str());