2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <TriggerTypes.h>
19 #include <TriggerRuleTypes.h>
20 #include <package_manager.h>
22 #include "RuleManager.h"
23 #include "ContextMonitor.h"
26 #define RULE_TABLE "ContextTriggerRule"
27 #define RULE_IDS_JSON "{ \"" TRIG_KEY_ENABLED_IDS "\" : [ ] , \"" TRIG_KEY_DISABLED_IDS "\" : [ ] }";
30 using namespace ctx::trigger;
32 static int __stringToInt(std::string str)
35 std::istringstream convert(str);
43 static std::string __intToString(int i)
45 std::ostringstream convert;
47 std::string str = convert.str();
51 RuleManager::RuleManager()
55 RuleManager::~RuleManager()
57 // Release rule instances
58 _D("Release rule instances");
59 for (auto it = __ruleMap.begin(); it != __ruleMap.end(); ++it) {
60 Rule* rule = static_cast<Rule*>(it->second);
62 int error = rule->stop();
63 if (error != ERR_NONE) {
64 _E("Failed to stop rule%d", it->first);
72 bool RuleManager::init()
77 // Create tables into db (rule, template)
78 std::string q1 = std::string("status INTEGER DEFAULT 0 NOT NULL, creator TEXT DEFAULT '' NOT NULL,")
79 + "packageId TEXT DEFAULT '' NOT NULL, description TEXT DEFAULT '',"
80 + "details TEXT DEFAULT '' NOT NULL";
81 ret = __dbManager.createTableSync(RULE_TABLE, q1.c_str(), NULL);
82 IF_FAIL_RETURN_TAG(ret, false, _E, "Create rule table failed");
84 // Before re-enable rules, handle uninstalled app's rules
85 if (__getUninstalledApp() > 0) {
86 error = __clearRuleOfUninstalledPackage(true);
87 IF_FAIL_RETURN_TAG(error == ERR_NONE, false, _E, "Failed to remove uninstalled apps' rules while initialization");
89 ret = __reenableRule();
94 void RuleManager::handleRuleOfUninstalledPackage(std::string pkgId)
96 __uninstalledPackages.insert(pkgId);
97 __clearRuleOfUninstalledPackage();
100 int RuleManager::__getUninstalledApp(void)
102 // Return number of uninstalled apps
103 std::string q1 = "SELECT DISTINCT packageId FROM ContextTriggerRule";
105 std::vector<Json> record;
106 bool ret = __dbManager.executeSync(q1.c_str(), &record);
107 IF_FAIL_RETURN_TAG(ret, -1, _E, "Query package ids of registered rules failed");
109 std::vector<Json>::iterator vecEnd = record.end();
110 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
113 elem.get(NULL, "packageId", &pkgId);
115 if (isUninstalledPackage(pkgId)) {
116 __uninstalledPackages.insert(pkgId);
120 return __uninstalledPackages.size();
123 bool RuleManager::isUninstalledPackage(std::string pkgId)
125 IF_FAIL_RETURN_TAG(!pkgId.empty(), false, _D, "Empty package id");
127 package_info_h pkgInfo;
128 int error = package_manager_get_package_info(pkgId.c_str(), &pkgInfo);
130 if (error == PACKAGE_MANAGER_ERROR_NONE) {
131 package_info_destroy(pkgInfo);
132 } else if (error == PACKAGE_MANAGER_ERROR_NO_SUCH_PACKAGE) {
133 // Uninstalled package found
134 _D("Uninstalled package found: %s", pkgId.c_str());
137 _E("Failed to get package info(%s): %d", pkgId.c_str(), error);
143 int RuleManager::__clearRuleOfUninstalledPackage(bool isInit)
145 if (__uninstalledPackages.size() <= 0) {
152 _D("Clear uninstalled packages' rule started");
154 std::string pkgList = "(";
155 std::set<std::string>::iterator it = __uninstalledPackages.begin();
156 pkgList += "packageId = '" + *it + "'";
158 for (; it != __uninstalledPackages.end(); ++it) {
159 pkgList += " OR packageId = '" + *it + "'";
163 // After event received, disable all the enabled rules of uninstalled apps
165 std::string q1 = "SELECT rowId FROM ContextTriggerRule WHERE status = 2 and (";
169 std::vector<Json> record;
170 ret = __dbManager.executeSync(q1.c_str(), &record);
171 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to query enabled rules of uninstalled packages");
173 std::vector<Json>::iterator vecEnd = record.end();
174 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
177 elem.get(NULL, "rowId", &ruleId);
178 error = disableRule(ruleId);
179 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to disable rule");
181 _D("Uninstalled packages' rules are disabled");
184 // Delete rules of uninstalled packages from DB
185 std::string q2 = "DELETE FROM ContextTriggerRule WHERE " + pkgList;
186 std::vector<Json> dummy;
187 ret = __dbManager.executeSync(q2.c_str(), &dummy);
188 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to remove rules from db");
189 _D("Uninstalled packages' rules are deleted from db");
191 __uninstalledPackages.clear();
196 int RuleManager::pauseRuleWithItem(std::string& subject)
198 std::string q = "SELECT rowId FROM ContextTriggerRule WHERE (status=2) AND (details LIKE '%\"ITEM_NAME\":\"" + subject + "\"%');";
199 std::vector<Json> record;
200 bool ret = __dbManager.executeSync(q.c_str(), &record);
201 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to query rowIds to be paused");
202 IF_FAIL_RETURN(record.size() > 0, ERR_NONE);
204 _D("Pause rules related to %s", subject.c_str());
205 std::vector<Json>::iterator vecEnd = record.end();
206 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
209 elem.get(NULL, "rowId", &rowId);
211 int error = pauseRule(rowId);
212 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to disable rules using custom item");
218 int RuleManager::resumeRuleWithItem(std::string& subject)
220 std::string q = "SELECT rowId FROM ContextTriggerRule WHERE (status=1) AND (details LIKE '%\"ITEM_NAME\":\"" + subject + "\"%');";
221 std::vector<Json> record;
222 bool ret = __dbManager.executeSync(q.c_str(), &record);
223 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Query paused rule ids failed");
224 IF_FAIL_RETURN(record.size() > 0, ERR_NONE);
226 _D("Resume rules related to %s", subject.c_str());
228 std::vector<Json>::iterator vecEnd = record.end();
229 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
232 elem.get(NULL, "rowId", &rowId);
234 int error = enableRule(rowId);
235 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to resume rule");
241 bool RuleManager::__reenableRule(void)
244 std::string q = "SELECT rowId FROM ContextTriggerRule WHERE status = 2";
246 std::vector<Json> record;
247 bool ret = __dbManager.executeSync(q.c_str(), &record);
248 IF_FAIL_RETURN_TAG(ret, false, _E, "Query rowIds of enabled rules failed");
249 IF_FAIL_RETURN_TAG(record.size() > 0, true, _D, "No rule to re-enable");
251 _D(YELLOW("Re-enable rule started"));
255 std::vector<Json>::iterator vecEnd = record.end();
256 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
259 elem.get(NULL, "rowId", &rowId);
261 error = enableRule(rowId);
262 if (error == ERR_NOT_SUPPORTED) {
263 qRowId += "(rowId = " + __intToString(rowId) + ") OR ";
264 } else if (error != ERR_NONE) {
265 _E("Re-enable rule%d failed(%d)", rowId, error);
268 IF_FAIL_RETURN(!qRowId.empty(), true);
269 qRowId = qRowId.substr(0, qRowId.length() - 4);
271 // For rules which is failed to re-enable
272 std::string qUpdate = "UPDATE ContextTriggerRule SET status = 1 WHERE " + qRowId;
273 std::vector<Json> record2;
274 ret = __dbManager.executeSync(qUpdate.c_str(), &record2);
275 IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to update rules as paused");
280 bool RuleManager::__ruleEquals(Json& lRule, Json& rRule)
284 lRule.get(NULL, TRIG_RULE_KEY_EVENT, &lEvent);
285 rRule.get(NULL, TRIG_RULE_KEY_EVENT, &rEvent);
287 std::string lEOp, rEOp;
288 lRule.get(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_EVENT_LOGICAL_OP, &lEOp);
289 rRule.get(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_EVENT_LOGICAL_OP, &rEOp);
291 if (lEOp != rEOp || lEvent != rEvent)
294 // Compare conditions
295 int lCondCnt, rCondCnt;
296 lCondCnt = lRule.getSize(NULL, TRIG_RULE_KEY_CONDITION);
297 rCondCnt = rRule.getSize(NULL, TRIG_RULE_KEY_CONDITION);
298 if (lCondCnt != rCondCnt)
301 std::string lOp, rOp;
302 lRule.get(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_RULE_LOGICAL_OP, &lOp);
303 rRule.get(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_RULE_LOGICAL_OP, &rOp);
307 for (int i = 0; i < lCondCnt; i++) {
310 lRule.getAt(NULL, TRIG_RULE_KEY_CONDITION, i, &lCond);
313 lRule.getAt(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_CONDITION_LOGICAL_OP, i, &lCOp);
315 for (int j = 0; j < lCondCnt; j++) {
317 rRule.getAt(NULL, TRIG_RULE_KEY_CONDITION, j, &rCond);
320 rRule.getAt(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_CONDITION_LOGICAL_OP, j, &rCOp);
322 if (lCOp == rCOp && lCond == rCond) {
332 Json lAction, rAction;
333 lRule.get(NULL, TRIG_RULE_KEY_ACTION, &lAction);
334 rRule.get(NULL, TRIG_RULE_KEY_ACTION, &rAction);
335 if (lAction != rAction)
341 int64_t RuleManager::__getDuplicatedRuleId(std::string pkgId, Json& rule)
343 std::string q = "SELECT rowId, description, details FROM ContextTriggerRule WHERE packageId = '";
347 std::vector<Json> record;
348 bool ret = __dbManager.executeSync(q.c_str(), &record);
349 IF_FAIL_RETURN_TAG(ret, false, _E, "Query rowId, details by package id failed");
352 rule.get(NULL, TRIG_RULE_KEY_DESCRIPTION, &rDesc);
353 Json rDetails = rule.str();
354 rDetails.remove(NULL, TRIG_RULE_KEY_DESCRIPTION);
356 std::vector<Json>::iterator vecEnd = record.end();
357 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
362 elem.get(NULL, "details", &dStr);
365 if (__ruleEquals(rDetails, details)) {
367 elem.get(NULL, "rowId", &rowId);
369 // Description comparison
371 elem.get(NULL, "description", &desc);
372 if (rDesc.compare(desc)) {
373 // Only description is changed
374 std::string qUpdate = "UPDATE ContextTriggerRule SET description='" + rDesc + "' WHERE rowId = " + __intToString(rowId);
376 std::vector<Json> dummy;
377 ret = __dbManager.executeSync(qUpdate.c_str(), &dummy);
379 _D("Rule%lld description is updated", rowId);
381 _W("Failed to update description of rule%lld", rowId);
392 int RuleManager::__verifyRule(Json& rule, const char* creator)
394 ContextMonitor* ctxMonitor = ContextMonitor::getInstance();
395 IF_FAIL_RETURN_TAG(ctxMonitor, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed");
399 rule.get(NULL, TRIG_RULE_KEY_EVENT, &event);
401 std::list<std::string> eventKey;
402 event.getKeys(&eventKey);
403 IF_FAIL_RETURN_TAG(eventKey.size() == 1, ERR_INVALID_PARAMETER, _E, "Invalid event");
405 std::string eventName = *eventKey.begin();
406 IF_FAIL_RETURN_TAG(ctxMonitor->isSupported(eventName), ERR_NOT_SUPPORTED, _I, "Event(%s) is not supported", eventName.c_str());
408 if (!ctxMonitor->isAllowed(creator, eventName.c_str())) {
409 _W("Permission denied for '%s'", eventName.c_str());
410 return ERR_PERMISSION_DENIED;
415 for (int i = 0; rule.getAt(NULL, TRIG_RULE_KEY_CONDITION, i, &cond); i++) {
416 std::list<std::string> condKey;
417 cond.getKeys(&condKey);
418 IF_FAIL_RETURN_TAG(condKey.size() == 1, ERR_INVALID_PARAMETER, _E, "Invalid condition");
420 std::string condName = *condKey.begin();
421 IF_FAIL_RETURN_TAG(ctxMonitor->isSupported(condName), ERR_NOT_SUPPORTED, _I, "Condition(%s) is not supported", condName.c_str());
423 if (!ctxMonitor->isAllowed(creator, condName.c_str())) {
424 _W("Permission denied for '%s'", condName.c_str());
425 return ERR_PERMISSION_DENIED;
432 int RuleManager::addRule(std::string creator, const char* pkgId, Json rule, Json* ruleId)
437 // Check if all items are supported && allowed to access
438 int err = __verifyRule(rule, creator.c_str());
439 IF_FAIL_RETURN(err == ERR_NONE, err);
441 // Check if duplicated rule exits
442 if ((rid = __getDuplicatedRuleId(pkgId, rule)) > 0) {
444 ruleId->set(NULL, TRIG_KEY_RULE_ID, rid);
445 _D("Duplicated rule found");
449 // Insert rule to rule table, get rule id
451 std::string description;
452 rule.get(NULL, TRIG_RULE_KEY_DESCRIPTION, &description);
454 Json details = rule.str();
455 details.remove(NULL, TRIG_RULE_KEY_DESCRIPTION);
456 record.set(NULL, "details", details.str());
458 record.set(NULL, "creator", creator);
460 record.set(NULL, "packageId", pkgId);
462 record.set(NULL, "description", description);
464 ret = __dbManager.insertSync(RULE_TABLE, record, &rid);
465 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Insert rule to db failed");
468 ruleId->set(NULL, TRIG_KEY_RULE_ID, rid);
470 _D("Add rule%d succeeded", (int)rid);
475 int RuleManager::removeRule(int ruleId)
479 // Delete rule from DB
480 std::string query = "DELETE FROM 'ContextTriggerRule' where rowId = ";
481 query += __intToString(ruleId);
483 std::vector<Json> record;
484 ret = __dbManager.executeSync(query.c_str(), &record);
485 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Remove rule from db failed");
487 _D("Remove rule%d succeeded", ruleId);
492 int RuleManager::enableRule(int ruleId)
496 std::vector<Json> record;
497 std::vector<Json> dummy;
501 std::string idStr = __intToString(ruleId);
505 // Get rule Json by rule id;
506 query = "SELECT details, packageId FROM ContextTriggerRule WHERE rowId = ";
508 error = (__dbManager.executeSync(query.c_str(), &record))? ERR_NONE : ERR_OPERATION_FAILED;
509 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Query rule by rule id failed");
511 record[0].get(NULL, "details", &tmp);
513 record[0].get(NULL, "packageId", &pkgId);
515 // Create a rule instance
516 rule = new(std::nothrow) Rule(ruleId, jRule, pkgId.c_str(), this);
517 IF_FAIL_RETURN_TAG(rule, ERR_OUT_OF_MEMORY, _E, "Failed to create rule instance");
520 error = rule->start();
521 IF_FAIL_CATCH_TAG(error == ERR_NONE, _E, "Failed to start rule%d", ruleId);
523 // Update db to set 'enabled'
524 query = "UPDATE ContextTriggerRule SET status = 2 WHERE rowId = ";
526 error = (__dbManager.executeSync(query.c_str(), &dummy))? ERR_NONE : ERR_OPERATION_FAILED;
527 IF_FAIL_CATCH_TAG(error == ERR_NONE, _E, "Update db failed");
529 // Add rule instance to __ruleMap
530 __ruleMap[ruleId] = rule;
532 _D(YELLOW("Enable Rule%d succeeded"), ruleId);
542 int RuleManager::disableRule(int ruleId)
547 auto it = __ruleMap.find(ruleId);
548 bool paused = (it == __ruleMap.end());
550 // For 'enabled' rule, not 'paused'
553 Rule* rule = static_cast<Rule*>(it->second);
554 error = rule->stop();
555 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to stop rule%d", ruleId);
557 // Remove rule instance from __ruleMap
562 // Update db to set 'disabled' // TODO skip while clear uninstalled rule
563 std::string query = "UPDATE ContextTriggerRule SET status = 0 WHERE rowId = ";
564 query += __intToString(ruleId);
565 std::vector<Json> record;
566 ret = __dbManager.executeSync(query.c_str(), &record);
567 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Update db failed");
569 _D(YELLOW("Disable Rule%d succeeded"), ruleId);
573 int RuleManager::pauseRule(int ruleId)
578 auto it = __ruleMap.find(ruleId);
579 IF_FAIL_RETURN_TAG(it != __ruleMap.end(), ERR_OPERATION_FAILED, _E, "Rule instance not found");
582 Rule* rule = static_cast<Rule*>(it->second);
583 error = rule->stop();
584 IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to stop rule%d", ruleId);
586 // Update db to set 'paused'
587 std::string query = "UPDATE ContextTriggerRule SET status = 1 WHERE rowId = ";
589 query += __intToString(ruleId);
590 std::vector<Json> record;
591 ret = __dbManager.executeSync(query.c_str(), &record);
592 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Update db failed");
594 // Remove rule instance from __ruleMap
598 _D(YELLOW("Pause Rule%d"), ruleId);
602 int RuleManager::checkRule(std::string pkgId, int ruleId)
605 std::string q = "SELECT packageId FROM ContextTriggerRule WHERE rowId =";
606 q += __intToString(ruleId);
608 std::vector<Json> record;
609 bool ret = __dbManager.executeSync(q.c_str(), &record);
610 IF_FAIL_RETURN_TAG(ret, false, _E, "Query package id by rule id failed");
612 if (record.size() == 0) {
617 record[0].get(NULL, "packageId", &p);
619 if (p.compare(pkgId) == 0) {
626 bool RuleManager::isRuleEnabled(int ruleId)
628 std::string q = "SELECT status FROM ContextTriggerRule WHERE rowId =";
629 q += __intToString(ruleId);
631 std::vector<Json> record;
632 bool ret = __dbManager.executeSync(q.c_str(), &record);
633 IF_FAIL_RETURN_TAG(ret, false, _E, "Query enabled by rule id failed");
636 record[0].get(NULL, "status", &status);
638 return (status != 0);
641 int RuleManager::getRuleById(std::string pkgId, int ruleId, Json* requestResult)
643 std::string q = "SELECT description FROM ContextTriggerRule WHERE (packageId = '";
645 q += "') and (rowId = ";
646 q += __intToString(ruleId);
649 std::vector<Json> record;
650 bool ret = __dbManager.executeSync(q.c_str(), &record);
651 IF_FAIL_RETURN_TAG(ret, false, _E, "Query rule by rule id failed");
653 if (record.size() == 0) {
655 } else if (record.size() != 1) {
656 return ERR_OPERATION_FAILED;
659 std::string description;
660 record[0].get(NULL, "description", &description);
662 (*requestResult).set(NULL, TRIG_KEY_RULE_ID, ruleId);
663 (*requestResult).set(NULL, TRIG_RULE_KEY_DESCRIPTION, description);
668 int RuleManager::getRuleIds(std::string pkgId, Json* requestResult)
670 (*requestResult) = RULE_IDS_JSON;
672 std::string q = "SELECT rowId, status FROM ContextTriggerRule WHERE (packageId = '";
676 std::vector<Json> record;
677 bool ret = __dbManager.executeSync(q.c_str(), &record);
678 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Query rules failed");
680 std::vector<Json>::iterator vecEnd = record.end();
681 for (std::vector<Json>::iterator vecPos = record.begin(); vecPos != vecEnd; ++vecPos) {
686 elem.get(NULL, "rowId", &id);
687 elem.get(NULL, "status", &status);
690 (*requestResult).append(NULL, TRIG_KEY_ENABLED_IDS, __stringToInt(id));
691 } else if (status == 0) {
692 (*requestResult).append(NULL, TRIG_KEY_DISABLED_IDS, __stringToInt(id));