trigger: implement API functions using the internal job scheduler API 94/142194/6
authorMu-Woong Lee <muwoong.lee@samsung.com>
Thu, 3 Aug 2017 04:20:10 +0000 (13:20 +0900)
committerMu-Woong Lee <muwoong.lee@samsung.com>
Fri, 4 Aug 2017 07:03:37 +0000 (16:03 +0900)
Change-Id: Idf903ba2903c469117c0698f79919e2e8b88d5e4
Signed-off-by: Mu-Woong Lee <muwoong.lee@samsung.com>
src/trigger/context_trigger.cpp

index 512510a..46d5298 100644 (file)
@@ -88,6 +88,7 @@ typedef struct _context_trigger_rule_entry_s {
        int type;
        std::string uri;
        ctx_sched_job_context_h jobContext;
+       std::set<std::string> conjunctionKeys;
        std::set<std::string> disjunctionKeys;
 
        _context_trigger_rule_entry_s(int c, int t, const char* u) :
@@ -194,158 +195,726 @@ static Scheduler __scheduler;
 
 EXPORT_API int context_trigger_add_rule(context_trigger_rule_h rule, int* rule_id)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(rule && rule_id);
+
+       int err = ctx_sched_add_job(SCHED, rule->job, rule_id);
+
+       if (err == E_PARAM)
+               return E_INV_RULE;
+
+       return err;
 }
 
 EXPORT_API int context_trigger_remove_rule(int rule_id)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       if (rule_id <= 0)
+               return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER;
+
+       int err = ctx_sched_remove_job(SCHED, rule_id);
+
+       if (err == E_RULE_ON)
+               return CONTEXT_TRIGGER_ERROR_RULE_ENABLED;
+       else if (err == E_PARAM)
+               return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST;
+
+       return err;
 }
 
 EXPORT_API int context_trigger_enable_rule(int rule_id)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       if (rule_id <= 0)
+               return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER;
+
+       int err = ctx_sched_start_job(SCHED, rule_id);
+
+       if (err == E_PARAM)
+               return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST;
+
+       return err;
 }
 
 EXPORT_API int context_trigger_disable_rule(int rule_id)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       if (rule_id <= 0)
+               return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER;
+
+       int err = ctx_sched_stop_job(SCHED, rule_id);
+
+       if (err == E_PARAM)
+               return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST;
+
+       return err;
+}
+
+static bool __foreach_job_cb(ctx_sched_h scheduler, ctx_sched_job_h job, void *user_data)
+{
+       auto jobs = static_cast<std::vector<ctx_sched_job_h>*>(user_data);
+       jobs->push_back(job);
+       return true;
 }
 
 EXPORT_API int context_trigger_get_own_rule_ids(int** enabled_rule_ids, int* enabled_rule_count, int** disabled_rule_ids, int* disabled_rule_count)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(enabled_rule_ids && enabled_rule_count && disabled_rule_ids && disabled_rule_count);
+
+       std::vector<ctx_sched_job_h> jobs;
+
+       int err = ctx_sched_foreach_job(SCHED, __foreach_job_cb, &jobs);
+
+       if (err == E_NO_DATA) {
+               *enabled_rule_ids = NULL;
+               *enabled_rule_count = 0;
+               *disabled_rule_ids = NULL;
+               *disabled_rule_count = 0;
+               return E_NONE;
+       }
+
+       IF_FAIL_RETURN(IS_SUCCESS(err), err);
+
+       std::vector<int> startedJobIds;
+       std::vector<int> stoppedJobIds;
+
+       for (auto& job : jobs) {
+               bool started = false;
+               int jobId = 0;
+
+               ctx_sched_job_is_started(job, &started);
+               ctx_sched_job_get_id(job, &jobId);
+               ctx_sched_job_destroy(job);
+
+               if (started)
+                       startedJobIds.push_back(jobId);
+               else
+                       stoppedJobIds.push_back(jobId);
+       }
+
+       *enabled_rule_count = startedJobIds.size();
+
+       if (*enabled_rule_count > 0)
+               *enabled_rule_ids = static_cast<int*>(g_memdup(startedJobIds.data(), startedJobIds.size() * sizeof(int)));
+       else
+               *enabled_rule_ids = NULL;
+
+       *disabled_rule_count = stoppedJobIds.size();
+
+       if (*disabled_rule_count > 0)
+               *disabled_rule_ids = static_cast<int*>(g_memdup(stoppedJobIds.data(), stoppedJobIds.size() * sizeof(int)));
+       else
+               *disabled_rule_ids = NULL;
+
+       return E_NONE;
 }
 
 EXPORT_API int context_trigger_get_rule_by_id(int rule_id, context_trigger_rule_h* rule)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(rule);
+       if (rule_id <= 0)
+               return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER;
+
+       ctx_sched_job_h job = NULL;
+
+       int err = ctx_sched_get_job(SCHED, rule_id, &job);
+
+       if (err == E_PARAM)
+               return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST;
+       else if (err != E_NONE)
+               return err;
+
+       *rule = new(std::nothrow) _context_trigger_rule_h(job);
+       if (*rule == NULL) {
+               _E_ALLOC;
+               ctx_sched_job_destroy(job);
+               return E_NO_MEM;
+       }
+
+       return E_NONE;
 }
 
 EXPORT_API int context_trigger_rule_create(context_trigger_logical_type_e logical_type, context_trigger_rule_h* rule)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       ASSERT_NOT_NULL(rule);
+       IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM);
+
+       *rule = new(std::nothrow) _context_trigger_rule_h();
+       ASSERT_ALLOC(*rule);
+       if ((*rule)->job == NULL) {
+               _E_ALLOC;
+               delete *rule;
+               return E_NO_MEM;
+       }
+
+       ctx_sched_job_set_disjunction((*rule)->job, logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION);
+
+       return E_NONE;
 }
 
 EXPORT_API int context_trigger_rule_destroy(context_trigger_rule_h rule)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(rule);
+
+       delete rule;
+
+       return E_NONE;
+}
+
+static int __set_event(context_trigger_rule_h rule, context_trigger_rule_entry_h event)
+{
+       IF_FAIL_RETURN(event->jobContext, E_PARAM);
+       IF_FAIL_RETURN_TAG(!rule->hasEvent, E_INV_RULE, _E, "The rule already has the event");
+
+       EventItem contextItem(event->type);
+       IF_FAIL_RETURN_TAG(contextItem.isValid(event->jobContext), E_INV_RULE, _E, "Incomplete event");
+
+       ctx_sched_job_context_h dup = ctx_sched_job_context_duplicate(event->jobContext);
+       ASSERT_ALLOC(dup);
+
+       int err = ctx_sched_job_add_trigger(rule->job, dup);
+       if (IS_FAILED(err)) {
+               ctx_sched_job_context_destroy(dup);
+               return err;
+       }
+
+       rule->hasEvent = true;
+
+       return E_NONE;
+}
+
+static int __add_condition(context_trigger_rule_h rule, context_trigger_rule_entry_h condition)
+{
+       IF_FAIL_RETURN(condition->jobContext, E_PARAM);
+
+       bool exist = (rule->conditions.find(condition->uri) != rule->conditions.end());
+       IF_FAIL_RETURN_TAG(!exist, E_INV_RULE, _E, "The same condition exists");
+
+       ConditionItem contextItem(condition->type);
+       IF_FAIL_RETURN_TAG(contextItem.isValid(condition->jobContext), E_INV_RULE, _E, "Incomplete condition");
+
+       ctx_sched_job_context_h dup = ctx_sched_job_context_duplicate(condition->jobContext);
+       ASSERT_ALLOC(dup);
+
+       int err = ctx_sched_job_add_requirement(rule->job, dup);
+       if (IS_FAILED(err)) {
+               ctx_sched_job_context_destroy(dup);
+               return err;
+       }
+
+       return E_NONE;
 }
 
 EXPORT_API int context_trigger_rule_add_entry(context_trigger_rule_h rule, context_trigger_rule_entry_h entry)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       ASSERT_NOT_NULL(rule && entry);
+       IF_FAIL_RETURN_TAG(!rule->readOnly, E_PARAM,
+                       _E, "A rule acquired by context_trigger_get_rule_by_id() is not allowed to be modified.");
+
+       if (entry->category == CATEGORY_EVENT)
+               return __set_event(rule, entry);
+       else
+               return __add_condition(rule, entry);
+}
+
+static bool __is_call_operation(app_control_h ctrl)
+{
+       char *op = NULL;
+       int err = app_control_get_operation(ctrl, &op);
+       IF_FAIL_RETURN_TAG(err == APP_CONTROL_ERROR_NONE, false, _E, "Getting operation of app control failed");
+
+       bool ret = STR_EQ(op, APP_CONTROL_OPERATION_CALL);
+       g_free(op);
+
+       return ret;
+}
+
+static bool __is_ui_app(app_control_h ctrl)
+{
+       char* appId = NULL;
+       int err = app_control_get_app_id(ctrl, &appId);
+
+       IF_FAIL_RETURN_TAG(err == E_NONE, false, _E, "Failed to get the app id");
+
+       pkgmgrinfo_appinfo_h appInfo;
+       err = pkgmgrinfo_appinfo_get_usr_appinfo(appId, getuid(), &appInfo);
+       g_free(appId);
+
+       IF_FAIL_RETURN_TAG(err == PMINFO_R_OK, false, _E, "No such app");
+
+       char *appType = NULL;
+       pkgmgrinfo_appinfo_get_component_type(appInfo, &appType);
+
+       bool ret = STR_EQ(appType, "uiapp");
+
+       pkgmgrinfo_appinfo_destroy_appinfo(appInfo);
+
+       return ret;
 }
 
 EXPORT_API int context_trigger_rule_set_action_app_control(context_trigger_rule_h rule, app_control_h app_control)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(rule && app_control);
+
+       if (!PrivilegeChecker::hasPrivilege("http://tizen.org/privilege/appmanager.launch")) {
+               _E("Privilege denied");
+               return E_ACCESS;
+       }
+
+       if (__is_call_operation(app_control) &&
+                       !PrivilegeChecker::hasPrivilege("http://tizen.org/privilege/call")) {
+               _E("Privilege denied");
+               return E_ACCESS;
+       }
+
+       IF_FAIL_RETURN_TAG(!rule->hasAction, E_INV_RULE, _E, "The rule has an action");
+       IF_FAIL_RETURN_TAG(__is_ui_app(app_control), E_INV_RULE, _E, "Invalid app-control");
+
+       bundle* bn = NULL;
+       app_control_export_as_bundle(app_control, &bn);
+       IF_FAIL_RETURN_TAG(bn, E_PARAM, _E, "Converting failed");
+
+       int ret = ctx_sched_job_set_app_control(rule->job, bn);
+
+       if (ret == E_NONE)
+               rule->hasAction = true;
+
+       return ret;
 }
 
-EXPORT_API int context_trigger_rule_set_action_notification(context_trigger_rule_h rule, const char* title, const char* content, const char* icon_path, app_control_h app_control)
+static bool __is_valid_app_control(app_control_h ctrl)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       if (!ctrl) return true;
+
+       char* appId = NULL;
+       int err = app_control_get_app_id(ctrl, &appId);
+       IF_FAIL_RETURN_TAG(err == E_NONE, false, _E, "Failed to get the app id");
+
+       pkgmgrinfo_appinfo_h appInfo;
+       err = pkgmgrinfo_appinfo_get_usr_appinfo(appId, getuid(), &appInfo);
+       g_free(appId);
+       IF_FAIL_RETURN_TAG(err == PMINFO_R_OK, false, _E, "No such app");
+
+       pkgmgrinfo_appinfo_destroy_appinfo(appInfo);
+
+       return true;
+}
+
+EXPORT_API int context_trigger_rule_set_action_notification(context_trigger_rule_h rule,
+               const char* title, const char* content, const char* icon_path, app_control_h app_control)
+{
+       INIT_SCHED;
+       ASSERT_NOT_NULL(rule && title && content);
+
+       if (!PrivilegeChecker::hasPrivilege("http://tizen.org/privilege/notification")) {
+               _E("Privilege denied");
+               return E_ACCESS;
+       }
+
+       IF_FAIL_RETURN_TAG(!rule->hasAction, E_INV_RULE, _E, "The rule has an action");
+       IF_FAIL_RETURN_TAG(__is_valid_app_control(app_control), E_INV_RULE, _E, "Invalid app-control");
+
+       bundle* bn = NULL;
+       if (app_control) {
+               app_control_export_as_bundle(app_control, &bn);
+               IF_FAIL_RETURN_TAG(bn, E_PARAM, _E, "Converting failed");
+       }
+
+       int ret = ctx_sched_job_set_notification(rule->job, title, content, icon_path, bn);
+
+       if (ret == E_NONE)
+               rule->hasAction = true;
+
+       return ret;
 }
 
 //LCOV_EXCL_START
 EXPORT_API int context_trigger_rule_set_action_dbus_call(context_trigger_rule_h rule,
                const char *bus_name, const char *object_path, const char *interface_name, const char *method_name, GVariant *param)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       ASSERT_NOT_NULL(rule && bus_name && object_path && interface_name && method_name);
+       IF_FAIL_RETURN_TAG(!rule->hasAction, E_INV_RULE, _E, "The rule has an action");
+
+       int ret = ctx_sched_job_set_dbus(rule->job, bus_name, object_path, interface_name, method_name, param);
+
+       if (ret == E_NONE)
+               rule->hasAction = true;
+
+       return ret;
 }
 //LCOV_EXCL_STOP
 
 EXPORT_API int context_trigger_rule_set_description(context_trigger_rule_h rule, const char* description)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       ASSERT_NOT_NULL(rule && description);
+       IF_FAIL_RETURN(strlen(description) > 0, E_PARAM);
+
+       return ctx_sched_job_set_user_data(rule->job, description, strlen(description) + 1);
 }
 
 EXPORT_API int context_trigger_rule_get_description(context_trigger_rule_h rule, char** description)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       ASSERT_NOT_NULL(rule && description);
+
+       char* val = NULL;
+       size_t len = 0;
+       int err = ctx_sched_job_get_user_data(rule->job, &val, &len);
+       IF_FAIL_RETURN(IS_SUCCESS(err), err);
+       IF_FAIL_RETURN(val, E_NONE);
+
+       *description = val;
+
+       return E_NONE;
 }
 
 EXPORT_API int context_trigger_rule_event_create(context_trigger_event_e event_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(entry);
+       IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM);
+
+       EventItem contextItem(event_item);
+       IF_FAIL_RETURN_TAG(contextItem.getUri(), E_PARAM, _E, "Unknown Event: %d", event_item);
+
+       if (contextItem.deprecated())
+               _DEPRECATED_EVENT(event_item);
+
+       IF_FAIL_RETURN_TAG(contextItem.allowed(), E_ACCESS, _E, "Privilege denied");
+
+       bool supported = false;
+       ctx_sched_job_trigger_is_supported(SCHED, contextItem.getUri(), &supported);
+       IF_FAIL_RETURN_TAG(supported, E_SUPPORT, _E, "Event-%d is not supported", event_item);
+
+       *entry = new(std::nothrow) _context_trigger_rule_entry_h(CATEGORY_EVENT, event_item, contextItem.getUri());
+       ASSERT_ALLOC(*entry);
+
+       ctx_sched_job_context_set_disjunction((*entry)->jobContext, (logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION));
+
+       return E_NONE;
+}
+
+static bool __is_valid_pkg_id(const char* pkgId)
+{
+       IF_FAIL_RETURN(pkgId, false);
+
+       pkgmgrinfo_pkginfo_h pkgInfo;
+       int err = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId, getuid(), &pkgInfo);
+       pkgmgrinfo_pkginfo_destroy_pkginfo(pkgInfo);
+
+       return (PMINFO_R_OK == err);
 }
 
 EXPORT_API int context_trigger_rule_custom_event_create(const char* event_item, const char* provider, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(event_item && provider && entry);
+       IF_FAIL_RETURN_TAG(__is_valid_pkg_id(provider), CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "No such package");
+
+       std::string uri = __get_custom_uri(event_item, provider);
+
+       bool registered = false;
+       ctx_sched_custom_is_registered(SCHED, uri.c_str(), provider, &registered);
+       IF_FAIL_RETURN_TAG(registered, E_SUPPORT, _W, "%s is not registered yet", event_item);
+
+       *entry = new(std::nothrow) _context_trigger_rule_entry_h(CATEGORY_EVENT, 0, uri.c_str());
+       ASSERT_ALLOC(*entry);
+
+       return E_NONE;
 }
 
 EXPORT_API int context_trigger_rule_event_is_supported(context_trigger_event_e event_item, bool* supported)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(supported);
+
+       EventItem contextItem(event_item);
+       IF_FAIL_RETURN_TAG(contextItem.getUri(), E_PARAM, _E, "Unknown Event: %d", event_item);
+
+       return ctx_sched_job_trigger_is_supported(SCHED, contextItem.getUri(), supported);
 }
 
 EXPORT_API int context_trigger_rule_condition_create(context_trigger_condition_e condition_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(entry);
+       IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM);
+
+       ConditionItem contextItem(condition_item);
+       IF_FAIL_RETURN_TAG(contextItem.getUri(), E_PARAM, _E, "Unknown Condition: %d", condition_item);
+
+       if (contextItem.deprecated())
+               _DEPRECATED_COND(condition_item);
+
+       IF_FAIL_RETURN_TAG(contextItem.allowed(), E_ACCESS, _E, "Privilege denied");
+
+       bool supported = false;
+       ctx_sched_job_requirement_is_supported(SCHED, contextItem.getUri(), &supported);
+       IF_FAIL_RETURN_TAG(supported, E_SUPPORT, _E, "Condition-%d is not supported", condition_item);
+
+       *entry = new(std::nothrow) _context_trigger_rule_entry_h(CATEGORY_CONDITION, condition_item, contextItem.getUri());
+       ASSERT_ALLOC(*entry);
+
+       ctx_sched_job_context_set_disjunction((*entry)->jobContext, (logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION));
+
+       return E_NONE;
 }
 
 EXPORT_API int context_trigger_rule_custom_condition_create(const char* condition_item, const char* provider, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(condition_item && provider && entry);
+       IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM);
+       IF_FAIL_RETURN_TAG(__is_valid_pkg_id(provider), CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "No such package");
+
+       std::string uri = __get_custom_uri(condition_item, provider);
+
+       bool registered = false;
+       ctx_sched_custom_is_registered(SCHED, uri.c_str(), provider, &registered);
+       IF_FAIL_RETURN_TAG(registered, E_SUPPORT, _W, "%s is not registered yet", condition_item);
+
+       *entry = new(std::nothrow) _context_trigger_rule_entry_h(CATEGORY_CONDITION, 0, uri.c_str());
+       ASSERT_ALLOC(*entry);
+
+       return E_NONE;
 }
 
 EXPORT_API int context_trigger_rule_condition_is_supported(context_trigger_condition_e condition_item, bool* supported)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(supported);
+
+       ConditionItem contextItem(condition_item);
+       IF_FAIL_RETURN_TAG(contextItem.getUri(), E_PARAM, _E, "Unknown Condition: %d", condition_item);
+
+       return ctx_sched_job_requirement_is_supported(SCHED, contextItem.getUri(), supported);
 }
 
 EXPORT_API int context_trigger_rule_entry_destroy(context_trigger_rule_entry_h entry)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(entry);
+
+       delete entry;
+
+       return E_NONE;
 }
 
 EXPORT_API int context_trigger_rule_entry_add_option_int(context_trigger_rule_entry_h entry, const char* option_key, int value)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       ASSERT_NOT_NULL(entry && option_key);
+
+       ContextItem* contextItem = __get_context_item(entry);
+       IF_FAIL_RETURN(contextItem, E_FAILED);
+
+       bool valid = contextItem->isValid(option_key, value);
+       delete contextItem;
+       IF_FAIL_RETURN(valid, E_INV_RULE);
+
+       ctx_sched_job_context_prepare_attribute_int(entry->jobContext, option_key);
+       return ctx_sched_job_context_attribute_add_eq_int(entry->jobContext, option_key, value);
 }
 
 EXPORT_API int context_trigger_rule_entry_add_option_string(context_trigger_rule_entry_h entry, const char* option_key, const char* value)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       _DEPRECATED_FUNC;
+       ASSERT_NOT_NULL(entry && option_key && value);
+
+       ContextItem* contextItem = __get_context_item(entry);
+       IF_FAIL_RETURN(contextItem, E_FAILED);
+
+       bool valid = contextItem->isValid(option_key, value);
+       delete contextItem;
+       IF_FAIL_RETURN(valid, E_INV_RULE);
+
+       ctx_sched_job_context_prepare_attribute_str(entry->jobContext, option_key);
+       return ctx_sched_job_context_attribute_add_eq_str(entry->jobContext, option_key, value);
 }
 
 EXPORT_API int context_trigger_rule_entry_add_option(context_trigger_rule_entry_h entry, const char* option_key, const char* event_data_key)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       _DEPRECATED_FUNC;
+       ASSERT_NOT_NULL(entry && option_key && event_data_key);
+       IF_FAIL_RETURN(entry->category == CATEGORY_CONDITION, E_INV_RULE);
+
+       ConditionItem contextItem(entry->type);
+       IF_FAIL_RETURN(contextItem.isValid(option_key), E_INV_RULE);
+
+       ctx_sched_job_context_prepare_attribute_str(entry->jobContext, option_key);
+       return ctx_sched_job_context_attribute_add_eq_str(entry->jobContext, option_key, event_data_key);
+}
+
+static bool __is_member_key(context_trigger_rule_entry_h entry, const char* key)
+{
+       if (entry->conjunctionKeys.find(key) != entry->conjunctionKeys.end() ||
+                       entry->disjunctionKeys.find(key) != entry->disjunctionKeys.end()) {
+               _D("'%s' found", key);
+               return true;
+       }
+
+       _D("'%s' not found", key);
+       return false;
 }
 
 EXPORT_API int context_trigger_rule_entry_add_key(context_trigger_rule_entry_h entry, context_trigger_logical_type_e logical_type, const char* key)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       ASSERT_NOT_NULL(entry && key);
+       IF_FAIL_RETURN(logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION || logical_type == CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, E_PARAM);
+
+       ContextItem* contextItem = __get_context_item(entry);
+       IF_FAIL_RETURN(contextItem, E_FAILED);
+
+       bool valid = contextItem->isValid(key);
+       delete contextItem;
+       IF_FAIL_RETURN_TAG(valid, E_INV_RULE, _E, "Invalid parameter");
+       IF_FAIL_RETURN(!__is_member_key(entry, key), E_INV_RULE);
+
+       if (logical_type == CONTEXT_TRIGGER_LOGICAL_CONJUNCTION)
+               entry->conjunctionKeys.insert(key);
+       else
+               entry->disjunctionKeys.insert(key);
+
+       return E_NONE;
 }
 
 EXPORT_API int context_trigger_rule_entry_add_comparison(context_trigger_rule_entry_h entry, const char* key, const char* op, const char* event_data_key)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       _DEPRECATED_FUNC;
+       ASSERT_NOT_NULL(entry && key && op && event_data_key);
+       IF_FAIL_RETURN(entry->category == CATEGORY_CONDITION, E_INV_RULE);
+
+       ConditionItem contextItem(entry->type);
+       IF_FAIL_RETURN(contextItem.isValid(key), E_INV_RULE);
+       IF_FAIL_RETURN(__is_member_key(entry, key), E_NO_DATA);
+
+       ctx_sched_job_context_prepare_attribute_str(entry->jobContext, key);
+
+       if (__getOpType(op) == OpType::EQ)
+               return ctx_sched_job_context_attribute_add_eq_str(entry->jobContext, key, event_data_key);
+
+       if (__getOpType(op) == OpType::NE)
+               return ctx_sched_job_context_attribute_add_ne_str(entry->jobContext, key, event_data_key);
+
+       _E("Invalid operator");
+       return E_INV_RULE;
 }
 
 EXPORT_API int context_trigger_rule_entry_add_comparison_int(context_trigger_rule_entry_h entry, const char* key, const char* op, int value)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       ASSERT_NOT_NULL(entry && key && op);
+
+       ContextItem* contextItem = __get_context_item(entry);
+       IF_FAIL_RETURN(contextItem, E_FAILED);
+
+       bool valid = contextItem->isValid(key, value);
+       delete contextItem;
+       IF_FAIL_RETURN_TAG(valid, E_INV_RULE, _E, "Invalid parameter");
+       IF_FAIL_RETURN(__is_member_key(entry, key), E_NO_DATA);
+
+       ctx_sched_job_context_prepare_attribute_int(entry->jobContext, key);
+
+       if (__getOpType(op) == OpType::EQ)
+               return ctx_sched_job_context_attribute_add_eq_int(entry->jobContext, key, value);
+
+       if (__getOpType(op) == OpType::NE)
+               return ctx_sched_job_context_attribute_add_ne_int(entry->jobContext, key, value);
+
+       //TODO: Consider logical disjunction
+       if (__getOpType(op) == OpType::GT)
+               return ctx_sched_job_context_attribute_set_gt_int(entry->jobContext, key, value);
+
+       if (__getOpType(op) == OpType::GE)
+               return ctx_sched_job_context_attribute_set_ge_int(entry->jobContext, key, value);
+
+       if (__getOpType(op) == OpType::LT)
+               return ctx_sched_job_context_attribute_set_lt_int(entry->jobContext, key, value);
+
+       if (__getOpType(op) == OpType::LE)
+               return ctx_sched_job_context_attribute_set_le_int(entry->jobContext, key, value);
+
+       _E("Invalid operator");
+       return E_INV_RULE;
 }
 
 EXPORT_API int context_trigger_rule_entry_add_comparison_string(context_trigger_rule_entry_h entry, const char* key, const char* op, const char* value)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       ASSERT_NOT_NULL(entry && key && op && value);
+
+       ContextItem* contextItem = __get_context_item(entry);
+       IF_FAIL_RETURN(contextItem, E_FAILED);
+
+       bool valid = contextItem->isValid(key, value);
+       delete contextItem;
+       IF_FAIL_RETURN_TAG(valid, E_INV_RULE, _E, "Invalid parameter");
+       IF_FAIL_RETURN(__is_member_key(entry, key), E_NO_DATA);
+
+       ctx_sched_job_context_prepare_attribute_str(entry->jobContext, key);
+
+       if (__getOpType(op) == OpType::EQ)
+               return ctx_sched_job_context_attribute_add_eq_str(entry->jobContext, key, value);
+
+       if (__getOpType(op) == OpType::NE)
+               return ctx_sched_job_context_attribute_add_ne_str(entry->jobContext, key, value);
+
+       _E("Invalid operator");
+       return E_INV_RULE;
 }
 
 EXPORT_API int context_trigger_custom_register(const char* name, const char* attr_template)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(name && attr_template);
+
+       //TODO: Is it allowed to overwrite a template?
+       CustomTemplate::remove(name);
+
+       bool success = CustomTemplate::add(name, attr_template);
+       IF_FAIL_RETURN_TAG(success, CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "Invalid template");
+
+       const char* pkgId = __get_pkg_id();
+       IF_FAIL_RETURN_TAG(pkgId, E_SUPPORT, _E, "PkgId is required");
+
+       std::string uri = __get_custom_uri(name, pkgId);
+
+       int err = ctx_sched_custom_register(SCHED, uri.c_str());
+       IF_FAIL_RETURN(err == E_NONE, E_FAILED);
+
+       return E_NONE;
 }
 
 EXPORT_API int context_trigger_custom_unregister(const char* name)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(name);
+
+       CustomTemplate::remove(name);
+
+       const char* pkgId = __get_pkg_id();
+       IF_FAIL_RETURN_TAG(pkgId, E_SUPPORT, _E, "PkgId is required");
+
+       std::string uri = __get_custom_uri(name, pkgId);
+
+       ctx_sched_custom_unregister(SCHED, uri.c_str());
+
+       return E_NONE;
 }
 
 EXPORT_API int context_trigger_custom_publish(const char* name, const char* fact)
 {
-       return CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
+       INIT_SCHED;
+       ASSERT_NOT_NULL(name && fact);
+
+       CustomTemplate* customTemplate = CustomTemplate::get(name);
+       IF_FAIL_RETURN_TAG(customTemplate, E_PARAM, _E, "Unknown custom name");
+       IF_FAIL_RETURN(customTemplate->match(fact), CONTEXT_TRIGGER_ERROR_INVALID_DATA);
+
+       const char* pkgId = __get_pkg_id();
+       IF_FAIL_RETURN_TAG(pkgId, E_SUPPORT, _E, "PkgId is required");
+
+       std::string uri = __get_custom_uri(name, pkgId);
+
+       return ctx_sched_publish_context_json(SCHED, uri.c_str(), fact);
 }