summaryrefslogtreecommitdiff
path: root/notification/src
diff options
context:
space:
mode:
Diffstat (limited to 'notification/src')
-rw-r--r--notification/src/notification.c2035
-rw-r--r--notification/src/notification_db.c229
-rw-r--r--notification/src/notification_db_query.h359
-rw-r--r--notification/src/notification_error.c60
-rw-r--r--notification/src/notification_group.c181
-rw-r--r--notification/src/notification_init.c84
-rw-r--r--notification/src/notification_internal.c2133
-rw-r--r--notification/src/notification_ipc.c2726
-rw-r--r--notification/src/notification_ipc_socket.c173
-rw-r--r--notification/src/notification_list.c376
-rw-r--r--notification/src/notification_noti.c2299
-rw-r--r--notification/src/notification_ongoing.c273
-rw-r--r--notification/src/notification_setting.c1125
-rw-r--r--notification/src/notification_setting_service.c931
-rw-r--r--notification/src/notification_shared_file.c1185
-rw-r--r--notification/src/notification_status.c197
-rw-r--r--notification/src/notification_viewer.c113
17 files changed, 14479 insertions, 0 deletions
diff --git a/notification/src/notification.c b/notification/src/notification.c
new file mode 100644
index 0000000..698b150
--- /dev/null
+++ b/notification/src/notification.c
@@ -0,0 +1,2035 @@
+/*
+ * Copyright (c) 2000 - 2017 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libintl.h>
+#include <dbus/dbus.h>
+
+#include <app_control.h>
+#include <app_control_internal.h>
+#include <package_manager.h>
+#include <aul.h>
+#include <tizen.h>
+#include <pkgmgr-info.h>
+#include <pkgmgrinfo_type.h>
+
+#include <notification.h>
+#include <notification_list.h>
+#include <notification_debug.h>
+#include <notification_private.h>
+#include <notification_noti.h>
+#include <notification_ongoing.h>
+#include <notification_group.h>
+#include <notification_ipc.h>
+#include <notification_internal.h>
+#include <notification_shared_file.h>
+
+static void (*posted_toast_message_cb)(void *data);
+
+#define NOTI_TEXT_RESULT_LEN 4096
+#define REGULAR_UID_MIN 5000
+
+char *notification_get_app_id_by_pid(int pid)
+{
+#define NOTI_APP_ID_LEN 512
+ char app_id[NOTI_APP_ID_LEN + 1] = { 0, };
+ int ret = AUL_R_OK;
+ int fd;
+ char *dup_app_id;
+ char buf[NOTI_APP_ID_LEN + 1] = { 0, };
+
+ ret = aul_app_get_appid_bypid(pid, app_id, sizeof(app_id));
+ if (ret != AUL_R_OK) {
+
+ snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
+
+ fd = open(buf, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+
+ ret = read(fd, app_id, sizeof(app_id) - 1);
+ close(fd);
+
+ if (ret <= 0)
+ return NULL;
+
+ app_id[ret] = '\0';
+ /*!
+ * \NOTE
+ * "ret" is not able to be larger than "sizeof(app_id) - 1",
+ * if the system is not going wrong.
+ */
+ } else {
+ if (strlen(app_id) <= 0)
+ return NULL;
+ }
+
+ dup_app_id = strdup(app_id);
+ if (!dup_app_id)
+ ERR("Failed to strdup, errno[%d]", errno);
+
+ return dup_app_id;
+}
+
+EXPORT_API int notification_set_image(notification_h noti,
+ notification_image_type_e type,
+ const char *image_path)
+{
+ bundle *b = NULL;
+ bundle *priv_b = NULL;
+ char buf_key[32] = { 0, };
+ char *ret_val = NULL;
+ char *priv_path = NULL;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_IMAGE_TYPE_NONE
+ || type > NOTIFICATION_IMAGE_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->b_image_path) {
+ b = noti->b_image_path;
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ if (image_path != NULL)
+ bundle_add_str(b, buf_key, image_path);
+ } else {
+ if (image_path == NULL)
+ return NOTIFICATION_ERROR_NONE;
+
+ b = bundle_create();
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+ bundle_add_str(b, buf_key, image_path);
+ noti->b_image_path = b;
+ }
+
+ priv_path = notification_check_file_path_is_private(noti->pkg_id, image_path);
+ if (noti->b_priv_image_path) {
+ priv_b = noti->b_priv_image_path;
+
+ ret_val = NULL;
+ bundle_get_str(priv_b, buf_key, &ret_val);
+ if (ret_val)
+ bundle_del(b, buf_key);
+
+ if (priv_path != NULL)
+ bundle_add_str(priv_b, buf_key, priv_path);
+ } else if (priv_path != NULL) {
+ priv_b = bundle_create();
+ bundle_add_str(priv_b, buf_key, priv_path);
+ noti->b_priv_image_path = priv_b;
+ }
+
+ if (priv_path)
+ free(priv_path);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_image(notification_h noti,
+ notification_image_type_e type,
+ char **image_path)
+{
+ bundle *b = NULL;
+ char buf_key[32] = { 0, };
+ char *ret_val = NULL;
+
+ if (noti == NULL || image_path == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_IMAGE_TYPE_NONE
+ || type > NOTIFICATION_IMAGE_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->b_image_path) {
+ b = noti->b_image_path;
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+
+ *image_path = ret_val;
+ } else {
+ /* If image path bundle does not exist, image path is NULL */
+ *image_path = NULL;
+ }
+
+ /* If image path is NULL and type is ICON, icon path set from AIL */
+ /* order : user icon -> launch_app_id icon -> caller_app_id icon -> service app icon */
+ if (*image_path == NULL && type == NOTIFICATION_IMAGE_TYPE_ICON) {
+ if (noti->app_icon_path != NULL)
+ *image_path = noti->app_icon_path;
+ else
+ *image_path = NULL;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_time(notification_h noti, time_t input_time)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (input_time == 0)
+ noti->time = time(NULL);
+ else
+ noti->time = input_time;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_time(notification_h noti, time_t *ret_time)
+{
+ if (noti == NULL || ret_time == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *ret_time = noti->time;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_insert_time(notification_h noti,
+ time_t *ret_time)
+{
+ if (noti == NULL || ret_time == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *ret_time = noti->insert_time;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_text(notification_h noti,
+ notification_text_type_e type, const char *text,
+ const char *key, int args_type, ...)
+{
+ bundle *b = NULL;
+ char buf_key[32] = { 0, };
+ char buf_val[NOTI_TEXT_RESULT_LEN] = { 0, };
+ char *ret_val = NULL;
+ va_list var_args;
+ notification_variable_type_e var_type;
+ int num_args = 0;
+ int noti_err = NOTIFICATION_ERROR_NONE;
+ int var_value_int = 0;
+ double var_value_double = 0.0;
+ char *var_value_string = NULL;
+ notification_count_pos_type_e var_value_count =
+ NOTIFICATION_COUNT_POS_NONE;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_TEXT_TYPE_NONE
+ || type > NOTIFICATION_TEXT_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (text != NULL) {
+ if (noti->b_text != NULL) {
+ b = noti->b_text;
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ snprintf(buf_val, sizeof(buf_val), "%s", text);
+
+ bundle_add_str(b, buf_key, buf_val);
+ } else {
+ b = bundle_create();
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+ snprintf(buf_val, sizeof(buf_val), "%s", text);
+
+ bundle_add_str(b, buf_key, buf_val);
+
+ noti->b_text = b;
+ }
+ } else {
+ if (noti->b_text != NULL) {
+ b = noti->b_text;
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+ }
+ }
+
+ if (key != NULL) {
+ if (noti->b_key != NULL) {
+ b = noti->b_key;
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ snprintf(buf_val, sizeof(buf_val), "%s", key);
+
+ bundle_add_str(b, buf_key, buf_val);
+ } else {
+ b = bundle_create();
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+
+ snprintf(buf_val, sizeof(buf_val), "%s", key);
+
+ bundle_add_str(b, buf_key, buf_val);
+
+ noti->b_key = b;
+ }
+ } else {
+ if (noti->b_key != NULL) {
+ b = noti->b_key;
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+ }
+ }
+
+ if (noti->b_format_args != NULL)
+ b = noti->b_format_args;
+ else
+ b = bundle_create();
+
+ va_start(var_args, args_type);
+
+ var_type = args_type;
+ num_args = 0;
+
+ while (var_type != NOTIFICATION_VARIABLE_TYPE_NONE) {
+ /* Type */
+ snprintf(buf_key, sizeof(buf_key), "%dtype%d", type, num_args);
+ snprintf(buf_val, sizeof(buf_val), "%d", var_type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, buf_val);
+
+ switch (var_type) {
+ case NOTIFICATION_VARIABLE_TYPE_INT:
+ var_value_int = va_arg(var_args, int);
+
+ /* Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
+ num_args);
+ snprintf(buf_val, sizeof(buf_val), "%d", var_value_int);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, buf_val);
+ break;
+
+ case NOTIFICATION_VARIABLE_TYPE_DOUBLE:
+ var_value_double = va_arg(var_args, double);
+
+ /* Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
+ num_args);
+ snprintf(buf_val, sizeof(buf_val), "%.2f",
+ var_value_double);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, buf_val);
+ break;
+
+ case NOTIFICATION_VARIABLE_TYPE_STRING:
+ var_value_string = va_arg(var_args, char *);
+
+ /* Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
+ num_args);
+ snprintf(buf_val, sizeof(buf_val), "%s",
+ var_value_string);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, buf_val);
+ break;
+
+ case NOTIFICATION_VARIABLE_TYPE_COUNT:
+ var_value_count =
+ va_arg(var_args, notification_count_pos_type_e);
+
+ /* Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
+ num_args);
+ snprintf(buf_val, sizeof(buf_val), "%d",
+ var_value_count);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, buf_val);
+ break;
+
+ default:
+ ERR("Invalid variable type. : %d", var_type);
+ noti_err = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ break;
+ }
+
+ num_args++;
+ var_type = va_arg(var_args, notification_variable_type_e);
+ }
+ va_end(var_args);
+
+ if (noti_err == NOTIFICATION_ERROR_NONE)
+ noti->num_format_args = num_args;
+ else
+ noti->num_format_args = 0;
+
+ snprintf(buf_key, sizeof(buf_key), "num%d", type);
+ snprintf(buf_val, sizeof(buf_val), "%d", noti->num_format_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, buf_val);
+
+ noti->b_format_args = b;
+
+ return noti_err;
+}
+
+EXPORT_API int notification_get_text(notification_h noti,
+ notification_text_type_e type,
+ char **text)
+{
+ char result_str[NOTI_TEXT_RESULT_LEN] = { 0, };
+ char buf_str[NOTI_TEXT_RESULT_LEN] = { 0, };
+ char buf_key[32] = { 0, };
+ char *ret_val = NULL;
+ char *get_str = NULL;
+ char *temp_str = NULL;
+ char *translated_str = NULL;
+ bundle *b = NULL;
+ int num_args = 0;
+ int src_len = 0;
+ int max_len = 0;
+ int ret_variable_int = 0;
+ double ret_variable_double = 0.0;
+ notification_text_type_e text_type = NOTIFICATION_TEXT_TYPE_NONE;
+ notification_variable_type_e ret_var_type = 0;
+
+ if (noti == NULL || text == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_TEXT_TYPE_NONE
+ || type > NOTIFICATION_TEXT_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ text_type = type;
+
+ if (noti->b_key != NULL) {
+ b = noti->b_key;
+
+ /* Get text domain and dir */
+ /* _notification_get_text_domain(noti); */
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+ bundle_get_str(b, buf_key, &ret_val);
+
+ if (noti->is_translation == false) {
+ if (ret_val != NULL && noti->domain != NULL
+ && noti->dir != NULL) {
+ /* Get application string */
+ bindtextdomain(noti->domain, noti->dir);
+
+ get_str = dgettext(noti->domain, ret_val);
+ if (get_str == ret_val) /* not found */
+ get_str = NULL;
+ } else if (ret_val != NULL) {
+ /* Get system string */
+ get_str = dgettext("sys_string", ret_val);
+ if (get_str == ret_val) /* not found */
+ get_str = NULL;
+ } else {
+ get_str = NULL;
+ }
+ }
+ }
+
+ if (get_str == NULL && noti->b_text != NULL) {
+ b = noti->b_text;
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+ bundle_get_str(b, buf_key, &get_str);
+ }
+
+ if (get_str == NULL && ret_val != NULL)
+ get_str = ret_val; /* fallback for printing anything */
+
+ if (get_str == NULL) {
+ *text = NULL;
+ return NOTIFICATION_ERROR_NONE;
+ }
+
+ /* Get number format args */
+ noti->num_format_args = 0;
+
+ b = noti->b_format_args;
+ if (b != NULL) {
+ snprintf(buf_key, sizeof(buf_key), "num%d", text_type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ noti->num_format_args = atoi(ret_val);
+ }
+
+ if (noti->num_format_args == 0 || noti->is_translation == true) {
+ *text = (char *)get_str;
+ return NOTIFICATION_ERROR_NONE;
+ }
+
+ /* Check first variable is count, LEFT pos */
+ snprintf(buf_key, sizeof(buf_key), "%dtype%d", text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_var_type = atoi(ret_val);
+
+ if (ret_var_type == NOTIFICATION_VARIABLE_TYPE_COUNT) {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d",
+ text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_variable_int = atoi(ret_val);
+
+ if (ret_variable_int == NOTIFICATION_COUNT_POS_LEFT) {
+ notification_get_count(noti->type,
+ noti->caller_app_id,
+ noti->group_id,
+ noti->priv_id,
+ &ret_variable_int);
+ snprintf(buf_str, sizeof(buf_str),
+ "%d ", ret_variable_int);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+ num_args++;
+ }
+ }
+
+ /* Check variable IN pos */
+ for (temp_str = (char *)get_str; *temp_str != '\0'; temp_str++) {
+ if (*temp_str != '%') {
+ if (NOTI_TEXT_RESULT_LEN - 1 > strlen(result_str)) {
+ strncat(result_str, temp_str, 1);
+ } else {
+ WARN("The buffer is full");
+ break;
+ }
+ } else {
+ if (*(temp_str + 1) == '%') {
+ if (NOTI_TEXT_RESULT_LEN - 1 > strlen(result_str)) {
+ strncat(result_str, temp_str, 1);
+ } else {
+ WARN("The buffer is full");
+ break;
+ }
+ } else if (*(temp_str + 1) == 'd') {
+ /* Get var Type */
+ ret_variable_int = 0;
+
+ snprintf(buf_key, sizeof(buf_key), "%dtype%d",
+ text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_var_type = atoi(ret_val);
+
+ if (ret_var_type ==
+ NOTIFICATION_VARIABLE_TYPE_COUNT) {
+ /* Get notification count */
+ notification_get_count(noti->type,
+ noti->caller_app_id,
+ noti->group_id,
+ noti->priv_id,
+ &ret_variable_int);
+ } else {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key),
+ "%dvalue%d", text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_variable_int = atoi(ret_val);
+ }
+
+ snprintf(buf_str, sizeof(buf_str), "%d",
+ ret_variable_int);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+
+ temp_str++;
+ num_args++;
+ } else if (*(temp_str + 1) == 's') {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d",
+ text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+
+ if (ret_val != NULL && noti->domain != NULL
+ && noti->dir != NULL) {
+ /* Get application string */
+ bindtextdomain(noti->domain, noti->dir);
+ translated_str =
+ dgettext(noti->domain, ret_val);
+ INFO("translated_str[%s]", translated_str);
+ } else if (ret_val != NULL) {
+ /* Get system string */
+ translated_str =
+ dgettext("sys_string", ret_val);
+ INFO("translated_str[%s]", translated_str);
+ } else {
+ translated_str = NULL;
+ }
+
+ if (translated_str != NULL) {
+ strncpy(buf_str, translated_str,
+ sizeof(buf_str) - 1);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+ }
+
+ temp_str++;
+ num_args++;
+ } else if (*(temp_str + 1) == 'f') {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d",
+ text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_variable_double = atof(ret_val);
+
+ snprintf(buf_str, sizeof(buf_str), "%.2f",
+ ret_variable_double);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+
+ temp_str++;
+ num_args++;
+ } else if (*(temp_str + 1) >= '1' && *(temp_str + 1) <= '9') {
+ if (*(temp_str + 3) == 'd') {
+ /* Get var Type */
+ ret_variable_int = 0;
+
+ snprintf(buf_key, sizeof(buf_key),
+ "%dtype%d", text_type,
+ num_args + *(temp_str + 1) - 49);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_var_type = atoi(ret_val);
+
+ if (ret_var_type ==
+ NOTIFICATION_VARIABLE_TYPE_COUNT) {
+ /* Get notification count */
+ notification_get_count(noti->type,
+ noti->caller_app_id,
+ noti->group_id,
+ noti->priv_id,
+ &ret_variable_int);
+ } else {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key),
+ "%dvalue%d", text_type,
+ num_args + *(temp_str + 1) - 49);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_variable_int = atoi(ret_val);
+ }
+
+ snprintf(buf_str, sizeof(buf_str), "%d",
+ ret_variable_int);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+
+ temp_str += 3;
+ } else if (*(temp_str + 3) == 's') {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key),
+ "%dvalue%d", text_type,
+ num_args + *(temp_str + 1) - 49);
+
+ bundle_get_str(b, buf_key, &ret_val);
+
+ snprintf(buf_str, sizeof(buf_str), "%s",
+ ret_val);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+
+ temp_str += 3;
+ } else if (*(temp_str + 3) == 'f') {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key),
+ "%dvalue%d", text_type,
+ num_args + *(temp_str + 1) - 49);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_variable_double = atof(ret_val);
+
+ snprintf(buf_str, sizeof(buf_str),
+ "%.2f", ret_variable_double);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+
+ temp_str += 3;
+ } else {
+ if (NOTI_TEXT_RESULT_LEN - 1 > strlen(result_str)) {
+ strncat(result_str, temp_str, 1);
+ } else {
+ WARN("The buffer is full");
+ break;
+ }
+ }
+ } else {
+ if (NOTI_TEXT_RESULT_LEN - 1 > strlen(result_str)) {
+ strncat(result_str, temp_str, 1);
+ } else {
+ WARN("The buffer is full");
+ break;
+ }
+ }
+ }
+ }
+
+ /* Check last variable is count, LEFT pos */
+ if (num_args < noti->num_format_args) {
+ snprintf(buf_key, sizeof(buf_key), "%dtype%d",
+ text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_var_type = atoi(ret_val);
+
+ if (ret_var_type == NOTIFICATION_VARIABLE_TYPE_COUNT) {
+ /* Get var Value */
+ snprintf(buf_key, sizeof(buf_key), "%dvalue%d",
+ text_type, num_args);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ ret_variable_int = atoi(ret_val);
+
+ if (ret_variable_int == NOTIFICATION_COUNT_POS_RIGHT) {
+ notification_get_count(noti->type,
+ noti->caller_app_id,
+ noti->group_id,
+ noti->priv_id,
+ &ret_variable_int);
+ snprintf(buf_str, sizeof(buf_str), " %d",
+ ret_variable_int);
+
+ src_len = strlen(result_str);
+ max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
+ strncat(result_str, buf_str, max_len);
+
+ num_args++;
+ }
+ }
+ }
+
+ switch (text_type) {
+ case NOTIFICATION_TEXT_TYPE_TITLE:
+ case NOTIFICATION_TEXT_TYPE_GROUP_TITLE:
+ if (noti->temp_title != NULL)
+ free(noti->temp_title);
+
+ noti->temp_title = strdup(result_str);
+
+ *text = noti->temp_title;
+ break;
+ case NOTIFICATION_TEXT_TYPE_CONTENT:
+ case NOTIFICATION_TEXT_TYPE_CONTENT_FOR_DISPLAY_OPTION_IS_OFF:
+ case NOTIFICATION_TEXT_TYPE_GROUP_CONTENT:
+ case NOTIFICATION_TEXT_TYPE_GROUP_CONTENT_FOR_DISPLAY_OPTION_IS_OFF:
+ if (noti->temp_content !=
+ NULL)
+ free(noti->temp_content);
+
+ noti->temp_content = strdup(result_str);
+
+ *text = noti->temp_content;
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_text_domain(notification_h noti,
+ const char *domain,
+ const char *dir)
+{
+ if (noti == NULL || domain == NULL || dir == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->domain)
+ free(noti->domain);
+
+ noti->domain = strdup(domain);
+
+ if (noti->dir)
+ free(noti->dir);
+
+ noti->dir = strdup(dir);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_text_domain(notification_h noti,
+ char **domain,
+ char **dir)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (domain != NULL && noti->domain != NULL)
+ *domain = noti->domain;
+
+ if (dir != NULL && noti->dir != NULL)
+ *dir = noti->dir;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_time_to_text(notification_h noti, notification_text_type_e type,
+ time_t time)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char buf[256] = { 0, };
+ char buf_tag[512] = { 0, };
+
+ if (noti == NULL || time <= 0)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_TEXT_TYPE_NONE
+ || type > NOTIFICATION_TEXT_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ snprintf(buf, sizeof(buf), "%lu", time);
+ ret = notification_noti_set_tag(TAG_TIME, buf, buf_tag, sizeof(buf_tag));
+
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ return notification_set_text(noti, type, buf_tag, NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+}
+
+EXPORT_API int notification_get_time_from_text(notification_h noti, notification_text_type_e type,
+ time_t *time)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *ret_text = NULL;
+ char *tag_value;
+
+ if (noti == NULL || time == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_TEXT_TYPE_NONE
+ || type > NOTIFICATION_TEXT_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_get_text(noti, type, &ret_text);
+ if (ret != NOTIFICATION_ERROR_NONE || ret_text == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (notification_noti_get_tag_type(ret_text) == TAG_TYPE_INVALID)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ tag_value = notification_noti_strip_tag(ret_text);
+ if (tag_value == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *time = atol(tag_value);
+ free(tag_value);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_sound(notification_h noti,
+ notification_sound_type_e type,
+ const char *path)
+{
+ char *priv_path = NULL;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type < NOTIFICATION_SOUND_TYPE_NONE
+ || type > NOTIFICATION_SOUND_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->sound_type = type;
+
+ /* Save sound path if user data type */
+ if (type == NOTIFICATION_SOUND_TYPE_USER_DATA && path != NULL) {
+ if (noti->sound_path != NULL)
+ free(noti->sound_path);
+ noti->sound_path = strdup(path);
+
+ if (noti->priv_sound_path != NULL)
+ free(noti->priv_sound_path);
+
+ priv_path = notification_check_file_path_is_private(noti->pkg_id, path);
+ if (priv_path)
+ noti->priv_sound_path = priv_path;
+ } else {
+ if (noti->sound_path != NULL) {
+ free(noti->sound_path);
+ noti->sound_path = NULL;
+ }
+
+ if (noti->priv_sound_path != NULL) {
+ free(noti->priv_sound_path);
+ noti->priv_sound_path = NULL;
+ }
+
+ if (type == NOTIFICATION_SOUND_TYPE_USER_DATA) {
+ noti->sound_type = NOTIFICATION_SOUND_TYPE_DEFAULT;
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_sound(notification_h noti,
+ notification_sound_type_e *type,
+ const char **path)
+{
+ if (noti == NULL || type == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *type = noti->sound_type;
+
+ /* Set sound path if user data type */
+ if (noti->sound_type == NOTIFICATION_SOUND_TYPE_USER_DATA
+ && path != NULL)
+ *path = noti->sound_path;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_vibration(notification_h noti,
+ notification_vibration_type_e type,
+ const char *path)
+{
+ char *priv_path = NULL;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type < NOTIFICATION_VIBRATION_TYPE_NONE
+ || type > NOTIFICATION_VIBRATION_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->vibration_type = type;
+
+ /* Save sound path if user data type */
+ if (type == NOTIFICATION_VIBRATION_TYPE_USER_DATA && path != NULL) {
+ if (noti->vibration_path != NULL) {
+ free(noti->vibration_path);
+ noti->vibration_path = NULL;
+ }
+ noti->vibration_path = strdup(path);
+
+ if (noti->priv_vibration_path != NULL) {
+ free(noti->priv_vibration_path);
+ noti->priv_vibration_path = NULL;
+ }
+ priv_path = notification_check_file_path_is_private(noti->pkg_id, path);
+ if (priv_path)
+ noti->priv_vibration_path = priv_path;
+ } else {
+ if (noti->vibration_path != NULL) {
+ free(noti->vibration_path);
+ noti->vibration_path = NULL;
+ }
+ if (noti->priv_vibration_path != NULL) {
+ free(noti->priv_vibration_path);
+ noti->priv_vibration_path = NULL;
+ }
+
+ if (type == NOTIFICATION_VIBRATION_TYPE_USER_DATA) {
+ noti->vibration_type = NOTIFICATION_VIBRATION_TYPE_DEFAULT;
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_vibration(notification_h noti,
+ notification_vibration_type_e *type,
+ const char **path)
+{
+ if (noti == NULL || type == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *type = noti->vibration_type;
+ /* Set sound path if user data type */
+ if (noti->vibration_type == NOTIFICATION_VIBRATION_TYPE_USER_DATA
+ && path != NULL)
+ *path = noti->vibration_path;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_led(notification_h noti,
+ notification_led_op_e operation,
+ int led_argb)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (operation < NOTIFICATION_LED_OP_OFF
+ || operation > NOTIFICATION_LED_OP_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->led_operation = operation;
+
+ /* Save led argb if operation is turning on LED with custom color */
+ if (operation == NOTIFICATION_LED_OP_ON_CUSTOM_COLOR)
+ noti->led_argb = led_argb;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_led(notification_h noti,
+ notification_led_op_e *operation,
+ int *led_argb)
+{
+ if (noti == NULL || operation == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *operation = noti->led_operation;
+
+ /* Save led argb if operation is turning on LED with custom color */
+ if (noti->led_operation == NOTIFICATION_LED_OP_ON_CUSTOM_COLOR
+ && led_argb != NULL)
+ *led_argb = noti->led_argb;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_led_time_period(notification_h noti,
+ int on_ms, int off_ms)
+{
+ if (noti == NULL || on_ms < 0 || off_ms < 0)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->led_on_ms = on_ms;
+ noti->led_off_ms = off_ms;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_led_time_period(notification_h noti,
+ int *on_ms, int *off_ms)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (on_ms)
+ *(on_ms) = noti->led_on_ms;
+ if (off_ms)
+ *(off_ms) = noti->led_off_ms;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_launch_option(notification_h noti,
+ notification_launch_option_type type, void *option)
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ int ret = 0;
+ bundle *b = NULL;
+ app_control_h app_control = option;
+
+ if (noti == NULL || app_control == NULL || type != NOTIFICATION_LAUNCH_OPTION_APP_CONTROL) {
+ err = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = app_control_export_as_bundle(app_control, &b);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ ERR("Failed to convert appcontrol to bundle[%d]", ret);
+ err = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ goto out;
+ }
+
+ err = notification_set_execute_option(noti, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL, b);
+
+out:
+ if (b)
+ bundle_free(b);
+
+ return err;
+}
+
+EXPORT_API int notification_get_launch_option(notification_h noti,
+ notification_launch_option_type type, void *option)
+{
+ int ret = 0;
+ bundle *b = NULL;
+ app_control_h *app_control = (app_control_h *)option;
+ app_control_h app_control_new = NULL;
+
+ if (noti == NULL || app_control == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type != NOTIFICATION_LAUNCH_OPTION_APP_CONTROL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_get_execute_option(noti,
+ NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH,
+ NULL,
+ &b);
+ if (ret == NOTIFICATION_ERROR_NONE && b != NULL) {
+ ret = app_control_create(&app_control_new);
+ if (ret == APP_CONTROL_ERROR_NONE && app_control_new != NULL) {
+ ret = app_control_import_from_bundle(app_control_new, b);
+ if (ret == APP_CONTROL_ERROR_NONE) {
+ *app_control = app_control_new;
+ } else {
+ /* LCOV_EXCL_START */
+ app_control_destroy(app_control_new);
+ ERR("Failed to import app control from bundle[%d]", ret);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ /* LCOV_EXCL_STOP */
+ }
+ } else {
+ /* LCOV_EXCL_START */
+ ERR("Failed to create app control[%d]", ret);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ /* LCOV_EXCL_STOP */
+ }
+ } else {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get execute option[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_event_handler(notification_h noti, notification_event_type_e event_type, app_control_h event_handler)
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ bundle *app_control_bundle = NULL;
+
+ if (noti == NULL) {
+ err = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ ERR("Invalid notification handle");
+ goto out;
+ }
+
+ if (event_type < NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1
+ || event_type > NOTIFICATION_EVENT_TYPE_MAX) {
+ ERR("Invalid event type");
+ err = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ goto out;
+ }
+
+ err = app_control_export_as_bundle(event_handler, &app_control_bundle);
+ if (err != APP_CONTROL_ERROR_NONE) {
+ ERR("Failed to export app_control to bundle[%d]", err);
+ goto out;
+ }
+
+ if (noti->b_event_handler[event_type] != NULL)
+ bundle_free(noti->b_event_handler[event_type]);
+
+ noti->b_event_handler[event_type] = app_control_bundle;
+
+out:
+ return err;
+}
+
+EXPORT_API int notification_get_event_handler(notification_h noti, notification_event_type_e event_type, app_control_h *event_handler)
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ bundle *b = NULL;
+ app_control_h app_control_new = NULL;
+
+ if (noti == NULL || event_handler == NULL) {
+ err = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ ERR("Invalid handle");
+ goto out;
+ }
+
+ if (event_type < NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1
+ || event_type > NOTIFICATION_EVENT_TYPE_MAX) {
+ /* LCOV_EXCL_START */
+ ERR("Invalid event type");
+ err = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ b = noti->b_event_handler[event_type];
+ if (b == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("No event handler");
+ err = NOTIFICATION_ERROR_NOT_EXIST_ID;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = app_control_create(&app_control_new);
+ if (err != APP_CONTROL_ERROR_NONE || app_control_new == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to create app_control[%d]", err);
+ err = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = app_control_import_from_bundle(app_control_new, b);
+ if (err == APP_CONTROL_ERROR_NONE) {
+ *event_handler = app_control_new;
+ } else {
+ /* LCOV_EXCL_START */
+ app_control_destroy(app_control_new);
+ app_control_new = NULL;
+ ERR("Failed to import app control from bundle[%d]", err);
+ err = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+out:
+ if (event_handler)
+ *event_handler = app_control_new;
+
+ return err;
+}
+
+EXPORT_API int notification_set_property(notification_h noti,
+ int flags)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->flags_for_property = flags;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_property(notification_h noti,
+ int *flags)
+{
+ if (noti == NULL || flags == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *flags = noti->flags_for_property;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_display_applist(notification_h noti,
+ int applist)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (applist == 0xffffffff) /* 0xffffffff means old NOTIFICATION_DISPLAY_APP_ALL */
+ applist = NOTIFICATION_DISPLAY_APP_ALL;
+
+ noti->display_applist = applist;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_display_applist(notification_h noti,
+ int *applist)
+{
+ if (noti == NULL || applist == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *applist = noti->display_applist;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_size(notification_h noti,
+ double size)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->progress_size = size;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_size(notification_h noti,
+ double *size)
+{
+ if (noti == NULL || size == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *size = noti->progress_size;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_progress(notification_h noti,
+ double percentage)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->progress_percentage = percentage;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_progress(notification_h noti,
+ double *percentage)
+{
+ if (noti == NULL || percentage == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *percentage = noti->progress_percentage;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_pkgname(notification_h noti,
+ char **pkgname)
+{
+ if (noti == NULL || pkgname == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->caller_app_id)
+ *pkgname = noti->caller_app_id;
+ else
+ *pkgname = NULL;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_layout(notification_h noti,
+ notification_ly_type_e layout)
+{
+ if (noti == NULL || (layout < NOTIFICATION_LY_NONE || layout > NOTIFICATION_LY_MAX))
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->layout = layout;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_layout(notification_h noti,
+ notification_ly_type_e *layout)
+{
+ if (noti == NULL || layout == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *layout = noti->layout;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_type(notification_h noti,
+ notification_type_e *type)
+{
+ if (noti == NULL || type == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *type = noti->type;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_post(notification_h noti)
+{
+ return notification_post_for_uid(noti, getuid());
+}
+
+EXPORT_API int notification_update(notification_h noti)
+{
+ return notification_update_for_uid(noti, getuid());
+}
+
+EXPORT_API int notification_delete_all(notification_type_e type)
+{
+ return notification_delete_all_for_uid(type, getuid());
+}
+
+EXPORT_API int notification_delete(notification_h noti)
+{
+ return notification_delete_for_uid(noti, getuid());
+}
+
+static int _notification_get_domain_name(const char *app_id, char **name)
+{
+ char *name_token = NULL;
+
+ if (app_id == NULL)
+ return -1;
+
+ /* com.vendor.name -> name */
+ name_token = strrchr(app_id, '.');
+ if (name_token == NULL)
+ return -1;
+
+ name_token++;
+
+ *name = strdup(name_token);
+ if (*name == NULL)
+ return -1;
+
+ return 0;
+}
+
+static notification_h _notification_create(notification_type_e type)
+{
+#define NOTI_PKG_ID_LEN 512
+ notification_h noti = NULL;
+ package_info_h package_info = NULL;
+ pkgmgrinfo_appinfo_h appinfo = NULL;
+ char *domain_name = NULL;
+ char *app_root_path = NULL;
+ char *label = NULL;
+ char locale_directory[PATH_MAX] = { 0, }; /* PATH_MAX 4096 */
+ char pkg_id[NOTI_PKG_ID_LEN + 1] = { 0, };
+ int err = 0;
+
+ if (type <= NOTIFICATION_TYPE_NONE || type > NOTIFICATION_TYPE_MAX) {
+ ERR("Invalid notification type[%d]", type);
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ noti = (notification_h)calloc(1, sizeof(struct _notification));
+ if (noti == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ noti->type = type;
+
+ if (type == NOTIFICATION_TYPE_NOTI)
+ noti->layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
+ else if (type == NOTIFICATION_TYPE_ONGOING)
+ noti->layout = NOTIFICATION_LY_ONGOING_PROGRESS;
+
+ noti->group_id = NOTIFICATION_GROUP_ID_NONE;
+ noti->sound_type = NOTIFICATION_SOUND_TYPE_NONE;
+ noti->vibration_type = NOTIFICATION_VIBRATION_TYPE_NONE;
+ noti->led_operation = NOTIFICATION_LED_OP_OFF;
+ noti->display_applist = NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY |
+ NOTIFICATION_DISPLAY_APP_LOCK |
+ NOTIFICATION_DISPLAY_APP_TICKER |
+ NOTIFICATION_DISPLAY_APP_INDICATOR;
+ noti->auto_remove = true;
+ noti->caller_app_id = notification_get_app_id_by_pid(getpid());
+ if (noti->caller_app_id == NULL) {
+ ERR("Failed to get caller_app_id");
+ err = -1;
+ goto out;
+ }
+
+ if (getuid() < REGULAR_UID_MIN) {
+ noti->pkg_id = strdup(noti->caller_app_id);
+ if (noti->pkg_id == NULL)
+ err = -1;
+ } else {
+ err = aul_app_get_pkgid_bypid(getpid(), pkg_id, sizeof(pkg_id));
+ if (err != AUL_R_OK)
+ noti->pkg_id = strdup(noti->caller_app_id);
+ else
+ noti->pkg_id = strdup(pkg_id);
+
+ if (noti->pkg_id == NULL) {
+ err = -1;
+ goto out;
+ }
+
+ err = _notification_get_domain_name(pkg_id, &domain_name);
+ if (err != 0 || domain_name == NULL) {
+ WARN("Failed to get domain_name");
+ err = 0;
+ /* In the case of the web app,
+ the domain can not be obtained. */
+ goto out;
+ }
+
+ noti->domain = strdup(domain_name);
+
+ err = package_info_create(pkg_id, &package_info);
+ if (err != PACKAGE_MANAGER_ERROR_NONE || package_info == NULL) {
+ /* LCOV_EXCL_START */
+ WARN("Failed to create package_info err[%d] pkg_id[%s]",
+ err, pkg_id);
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = package_info_get_root_path(package_info, &app_root_path);
+ if (err != PACKAGE_MANAGER_ERROR_NONE || app_root_path == NULL) {
+ /* LCOV_EXCL_START */
+ WARN("Failed to get root path err[%d] path[%p]",
+ err, app_root_path);
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ snprintf(locale_directory, PATH_MAX, "%s/res/locale", app_root_path);
+ noti->dir = strdup(locale_directory);
+
+ err = pkgmgrinfo_appinfo_get_usr_appinfo(noti->caller_app_id,
+ getuid(), &appinfo);
+ if (err != PMINFO_R_OK || appinfo == NULL) {
+ WARN("Failed to get appinfo err[%d] caller_app_id[%s]",
+ err, noti->caller_app_id);
+ err = 0;
+ goto out;
+ }
+
+ err = pkgmgrinfo_appinfo_get_label(appinfo, &label);
+ if (err != PMINFO_R_OK || label == NULL) {
+ WARN("Failed to get app_label err[%d]", err);
+ err = 0;
+ goto out;
+ }
+
+ noti->app_label = strdup(label);
+ }
+
+out:
+ if (domain_name)
+ free(domain_name);
+
+ if (app_root_path)
+ free(app_root_path);
+
+ if (package_info)
+ package_info_destroy(package_info);
+
+ if (appinfo)
+ pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
+
+ if (err != 0) {
+ notification_free(noti);
+ noti = NULL;
+ set_last_result(NOTIFICATION_ERROR_IO_ERROR);
+ } else {
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ }
+
+ /*!
+ * \NOTE
+ * Other fields are already initialized with ZERO.
+ */
+
+ return noti;
+}
+
+EXPORT_API notification_h notification_create(notification_type_e type)
+{
+ return _notification_create(type);
+}
+
+EXPORT_API notification_h notification_load_by_tag(const char *tag)
+{
+ return notification_load_by_tag_for_uid(tag, getuid());
+}
+
+EXPORT_API int notification_clone(notification_h noti, notification_h *clone)
+{
+ int i = 0;
+ notification_h new_noti = NULL;
+
+ if (noti == NULL || clone == NULL) {
+ ERR("Invalid handle");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ new_noti = (notification_h) calloc(1, sizeof(struct _notification));
+ if (new_noti == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ new_noti->type = noti->type;
+ new_noti->layout = noti->layout;
+ new_noti->group_id = noti->group_id;
+ new_noti->internal_group_id = noti->internal_group_id;
+ new_noti->priv_id = noti->priv_id;
+
+ if (noti->pkg_id != NULL)
+ new_noti->pkg_id = strdup(noti->pkg_id);
+
+ if (noti->caller_app_id != NULL)
+ new_noti->caller_app_id = strdup(noti->caller_app_id);
+
+ if (noti->launch_app_id != NULL)
+ new_noti->launch_app_id = strdup(noti->launch_app_id);
+
+ if (noti->args != NULL)
+ new_noti->args = bundle_dup(noti->args);
+
+ if (noti->group_args != NULL)
+ new_noti->group_args = bundle_dup(noti->group_args);
+
+ if (noti->b_execute_option != NULL)
+ new_noti->b_execute_option = bundle_dup(noti->b_execute_option);
+
+ if (noti->b_service_responding != NULL)
+ new_noti->b_service_responding = bundle_dup(noti->b_service_responding);
+
+ if (noti->b_service_single_launch != NULL)
+ new_noti->b_service_single_launch = bundle_dup(noti->b_service_single_launch);
+
+ if (noti->b_service_multi_launch != NULL)
+ new_noti->b_service_multi_launch = bundle_dup(noti->b_service_multi_launch);
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++) {
+ if (noti->b_event_handler[i] != NULL)
+ new_noti->b_event_handler[i] = bundle_dup(noti->b_event_handler[i]);
+ }
+
+ if (noti->domain != NULL)
+ new_noti->domain = strdup(noti->domain);
+
+ if (noti->dir != NULL)
+ new_noti->dir = strdup(noti->dir);
+
+ if (noti->b_text != NULL)
+ new_noti->b_text = bundle_dup(noti->b_text);
+
+ if (noti->b_key != NULL)
+ new_noti->b_key = bundle_dup(noti->b_key);
+
+ if (noti->b_format_args != NULL)
+ new_noti->b_format_args = bundle_dup(noti->b_format_args);
+
+ new_noti->num_format_args = noti->num_format_args;
+
+ if (noti->b_image_path != NULL)
+ new_noti->b_image_path = bundle_dup(noti->b_image_path);
+
+ if (noti->b_priv_image_path != NULL)
+ new_noti->b_priv_image_path = bundle_dup(noti->b_priv_image_path);
+
+ new_noti->sound_type = noti->sound_type;
+
+ if (noti->sound_path != NULL)
+ new_noti->sound_path = strdup(noti->sound_path);
+
+ if (noti->priv_sound_path != NULL)
+ new_noti->priv_sound_path = strdup(noti->priv_sound_path);
+
+ new_noti->vibration_type = noti->vibration_type;
+
+ if (noti->vibration_path != NULL)
+ new_noti->vibration_path = strdup(noti->vibration_path);
+
+ if (noti->priv_vibration_path != NULL)
+ new_noti->priv_vibration_path = strdup(noti->priv_vibration_path);
+
+ new_noti->led_operation = noti->led_operation;
+ new_noti->led_argb = noti->led_argb;
+ new_noti->led_on_ms = noti->led_on_ms;
+ new_noti->led_off_ms = noti->led_off_ms;
+ new_noti->time = noti->time;
+ new_noti->insert_time = noti->insert_time;
+ new_noti->flags_for_property = noti->flags_for_property;
+ new_noti->display_applist = noti->display_applist;
+ new_noti->progress_size = noti->progress_size;
+ new_noti->progress_percentage = noti->progress_percentage;
+
+ if (noti->tag != NULL)
+ new_noti->tag = strdup(noti->tag);
+
+ new_noti->ongoing_flag = noti->ongoing_flag;
+ new_noti->ongoing_value_type = noti->ongoing_value_type;
+ new_noti->ongoing_current = noti->ongoing_current;
+ new_noti->ongoing_duration = noti->ongoing_duration;
+ new_noti->auto_remove = noti->auto_remove;
+ new_noti->default_button_index = noti->default_button_index;
+ new_noti->hide_timeout = noti->hide_timeout;
+ new_noti->delete_timeout = noti->delete_timeout;
+ new_noti->text_input_max_length = noti->text_input_max_length;
+ new_noti->event_flag = noti->event_flag;
+ new_noti->is_translation = noti->is_translation;
+ new_noti->extension_image_size = noti->extension_image_size;
+
+ if (noti->app_label != NULL)
+ new_noti->app_label = strdup(noti->app_label);
+
+ new_noti->uid = noti->uid;
+
+ *clone = new_noti;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_free(notification_h noti)
+{
+ int i = 0;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->pkg_id)
+ free(noti->pkg_id);
+
+ if (noti->caller_app_id)
+ free(noti->caller_app_id);
+
+ if (noti->launch_app_id)
+ free(noti->launch_app_id);
+
+ if (noti->args)
+ bundle_free(noti->args);
+
+ if (noti->group_args)
+ bundle_free(noti->group_args);
+
+ if (noti->b_execute_option)
+ bundle_free(noti->b_execute_option);
+
+ if (noti->b_service_responding)
+ bundle_free(noti->b_service_responding);
+
+ if (noti->b_service_single_launch)
+ bundle_free(noti->b_service_single_launch);
+
+ if (noti->b_service_multi_launch)
+ bundle_free(noti->b_service_multi_launch);
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++) {
+ if (noti->b_event_handler[i] != NULL)
+ bundle_free(noti->b_event_handler[i]);
+ }
+
+ if (noti->b_image_path)
+ bundle_free(noti->b_image_path);
+
+ if (noti->b_priv_image_path)
+ bundle_free(noti->b_priv_image_path);
+
+ if (noti->sound_path)
+ free(noti->sound_path);
+
+ if (noti->priv_sound_path)
+ free(noti->priv_sound_path);
+
+ if (noti->vibration_path)
+ free(noti->vibration_path);
+
+ if (noti->priv_vibration_path)
+ free(noti->priv_vibration_path);
+
+ if (noti->domain)
+ free(noti->domain);
+
+ if (noti->dir)
+ free(noti->dir);
+
+ if (noti->b_text)
+ bundle_free(noti->b_text);
+
+ if (noti->b_key)
+ bundle_free(noti->b_key);
+
+ if (noti->b_format_args)
+ bundle_free(noti->b_format_args);
+
+ if (noti->app_icon_path)
+ free(noti->app_icon_path);
+
+ if (noti->app_label)
+ free(noti->app_label);
+
+ if (noti->temp_title)
+ free(noti->temp_title);
+
+ if (noti->temp_content)
+ free(noti->temp_content);
+
+ if (noti->tag)
+ free(noti->tag);
+
+ free(noti);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_tag(notification_h noti, const char *tag)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (tag != NULL) {
+ if (noti->tag != NULL)
+ free(noti->tag);
+
+ noti->tag = strdup(tag);
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_tag(notification_h noti, const char **tag)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *tag = noti->tag;
+ return NOTIFICATION_ERROR_NONE;
+}
+
+/* LCOV_EXCL_START */
+void notification_call_posted_toast_cb(const char *message)
+{
+ if (posted_toast_message_cb != NULL)
+ posted_toast_message_cb((void *)message);
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_set_ongoing_flag(notification_h noti, bool ongoing_flag)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->ongoing_flag = ongoing_flag;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_ongoing_flag(notification_h noti, bool *ongoing_flag)
+{
+ if (noti == NULL || ongoing_flag == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *ongoing_flag = noti->ongoing_flag;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_add_button(notification_h noti, notification_button_index_e button_index)
+{
+ if (noti == NULL ||
+ !((button_index >= NOTIFICATION_BUTTON_1 && button_index <= NOTIFICATION_BUTTON_6) ||
+ (button_index >= NOTIFICATION_BUTTON_7 && button_index <= NOTIFICATION_BUTTON_10)))
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_remove_button(notification_h noti, notification_button_index_e button_index)
+{
+ if (noti == NULL ||
+ !((button_index >= NOTIFICATION_BUTTON_1 && button_index <= NOTIFICATION_BUTTON_6) ||
+ (button_index >= NOTIFICATION_BUTTON_7 && button_index <= NOTIFICATION_BUTTON_10)))
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->b_event_handler[button_index - 1]) {
+ bundle_free(noti->b_event_handler[button_index - 1]);
+ noti->b_event_handler[button_index - 1] = NULL;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_auto_remove(notification_h noti, bool auto_remove)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->auto_remove = auto_remove;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_auto_remove(notification_h noti, bool *auto_remove)
+{
+ if (noti == NULL || auto_remove == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *auto_remove = noti->auto_remove;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_save_as_template(notification_h noti, const char *template_name)
+{
+ if (noti == NULL || template_name == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return notification_ipc_request_save_as_template(noti, template_name);
+}
+
+EXPORT_API notification_h notification_create_from_template(const char *template_name)
+{
+ int ret = 0;
+ notification_h noti = NULL;
+
+ if (template_name == NULL) {
+ ERR("Invalid parameter");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ noti = (notification_h)calloc(1, sizeof(struct _notification));
+ if (noti == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_ipc_request_create_from_template(noti, template_name);
+
+ set_last_result(ret);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return NULL;
+ }
+
+ return noti;
+}
+
+EXPORT_API int notification_get_noti_block_state(notification_block_state_e *state)
+{
+ int ret;
+ char *app_id;
+ int do_not_disturb;
+ int do_not_disturb_except;
+ int allow_to_notify;
+
+ if (state == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ app_id = notification_get_app_id_by_pid(getpid());
+
+ ret = notification_ipc_get_noti_block_state(app_id, &do_not_disturb, &do_not_disturb_except, &allow_to_notify, getuid());
+
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ if (app_id)
+ free(app_id);
+ return ret;
+ }
+
+ if (allow_to_notify) {
+ *state = NOTIFICATION_BLOCK_STATE_ALLOWED;
+ if (do_not_disturb && !do_not_disturb_except)
+ *state = NOTIFICATION_BLOCK_STATE_DO_NOT_DISTURB;
+ } else {
+ *state = NOTIFICATION_BLOCK_STATE_BLOCKED;
+ }
+
+ if (app_id)
+ free(app_id);
+
+ return ret;
+}
+
+EXPORT_API int notification_set_text_input(notification_h noti, int text_input_max_length)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->text_input_max_length = text_input_max_length;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_extension_image_size(notification_h noti, int height)
+{
+ if (noti == NULL || height <= 0)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->extension_image_size = height;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_extension_image_size(notification_h noti, int *height)
+{
+ if (noti == NULL || height == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *height = noti->extension_image_size;
+
+ return NOTIFICATION_ERROR_NONE;
+}
diff --git a/notification/src/notification_db.c b/notification/src/notification_db.c
new file mode 100644
index 0000000..485a207
--- /dev/null
+++ b/notification/src/notification_db.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2000 - 2017 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.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sqlite3.h>
+#include <tizen.h>
+
+#include <notification_error.h>
+#include <notification_debug.h>
+#include <notification_db.h>
+#include "notification_db_query.h"
+
+static bool is_db_corrupted = false;
+
+/* LCOV_EXCL_START */
+static int __check_integrity_cb(void *pid, int argc, char **argv, char **notUsed)
+{
+ char *check_str = "ok";
+
+ if (strncmp(argv[0], check_str, strlen(check_str))) {
+ ERR("db integrity result : %s", argv[0]);
+ is_db_corrupted = true;
+ return -1;
+ }
+
+ INFO("db integrity result : %s", argv[0]);
+ return 0;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static int __recover_corrupted_db(sqlite3 *db)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ char *errmsg = NULL;
+
+ INFO("DB is corrupted, start to recover corrupted db");
+ if (db)
+ sqlite3_close(db);
+ unlink(DBPATH);
+
+ sql_ret = sqlite3_open_v2(DBPATH, &db,
+ SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE,
+ NULL);
+ if (sql_ret != SQLITE_OK) {
+ ERR("Failed to open db[%d]", sql_ret);
+ unlink(DBPATH);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ sql_ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, NULL, NULL, &errmsg);
+ if (sql_ret != SQLITE_OK) {
+ ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ }
+
+out:
+ if (errmsg)
+ sqlite3_free(errmsg);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_db_init(void)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ sqlite3 *db = NULL;
+ char *errmsg = NULL;
+
+ sql_ret = sqlite3_open_v2(DBPATH, &db,
+ SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
+ if (sql_ret != SQLITE_OK) {
+ ERR("Failed to open db[%d]", ret);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ sql_ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, NULL, NULL, &errmsg);
+ if (sql_ret != SQLITE_OK) {
+ ERR("Failed to exec sqlite[%d][%s]", ret, errmsg);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ sql_ret = sqlite3_exec(db, "PRAGMA integrity_check",
+ __check_integrity_cb, NULL, &errmsg);
+ if (sql_ret != SQLITE_OK || is_db_corrupted) {
+ ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ }
+
+out:
+ if (sql_ret == SQLITE_CORRUPT || sql_ret == SQLITE_NOTADB || is_db_corrupted)
+ ret = __recover_corrupted_db(db);
+ if (errmsg)
+ sqlite3_free(errmsg);
+ if (db)
+ sqlite3_close(db);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+sqlite3 *notification_db_open()
+{
+ int ret = 0;
+ sqlite3 *db = 0;
+
+ ret = access(DBPATH, R_OK | W_OK);
+ if (ret != 0) {
+ /* LCOV_EXCL_START */
+ set_last_result(NOTIFICATION_ERROR_FROM_DB);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_open_v2(DBPATH, &db, SQLITE_OPEN_READWRITE, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ if (ret == SQLITE_PERM)
+ set_last_result(NOTIFICATION_ERROR_PERMISSION_DENIED);
+ else
+ set_last_result(NOTIFICATION_ERROR_FROM_DB);
+
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ return db;
+}
+
+int notification_db_close(sqlite3 **db)
+{
+ int ret = 0;
+
+ if (db == NULL || *db == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = sqlite3_close(*db);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to close db[%d]", ret);
+ return NOTIFICATION_ERROR_FROM_DB;
+ /* LCOV_EXCL_STOP */
+ }
+
+ *db = NULL;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_db_exec(sqlite3 *db, const char *query, int *num_changes)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ sqlite3_stmt *stmt = NULL;
+
+ if (db == NULL || query == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Sqlite3 err[%d][%s]", ret, sqlite3_errmsg(db));
+ return NOTIFICATION_ERROR_FROM_DB;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_OK || ret == SQLITE_DONE) {
+ if (num_changes != NULL)
+ *num_changes = sqlite3_changes(db);
+
+ ret = NOTIFICATION_ERROR_NONE;
+ } else {
+ /* LCOV_EXCL_START */
+ ERR("Sqlite err[%d][%s]", ret, sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sqlite3_finalize(stmt);
+
+ return ret;
+}
+
+char *notification_db_column_text(sqlite3_stmt *stmt, int col)
+{
+ const unsigned char *col_text = NULL;
+
+ col_text = sqlite3_column_text(stmt, col);
+ if (col_text == NULL || col_text[0] == '\0')
+ return NULL;
+
+ return strdup((char *)col_text);
+}
+
+bundle *notification_db_column_bundle(sqlite3_stmt *stmt, int col)
+{
+ const unsigned char *col_bundle = NULL;
+
+ col_bundle = sqlite3_column_text(stmt, col);
+ if (col_bundle == NULL || col_bundle[0] == '\0')
+ return NULL;
+
+ return bundle_decode(col_bundle, strlen((char *)col_bundle));
+}
+
diff --git a/notification/src/notification_db_query.h b/notification/src/notification_db_query.h
new file mode 100644
index 0000000..dd6a65a
--- /dev/null
+++ b/notification/src/notification_db_query.h
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2017 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.
+ */
+
+#define NOTIFICATION_DB_TABLE "noti_list"
+#define NOTIFICATION_SETTING_DB_TABLE "notification_setting"
+#define NOTIFICATION_SYSTEM_SETTING_DB_TABLE "notification_system_setting"
+#define NOTIFICATION_DND_ALLOW_EXCEPTION "dnd_allow_exception"
+
+#define CREATE_NOTIFICATION_TABLE \
+ "PRAGMA journal_mode = PERSIST;\n" \
+ "PRAGMA synchronous = FULL;\n" \
+ "CREATE TABLE IF NOT EXISTS noti_list (\n" \
+ " type INTEGER NOT NULL,\n" \
+ " layout INTEGER NOT NULL DEFAULT 0,\n" \
+ " pkg_id TEXT NOT NULL,\n" \
+ " caller_app_id TEXT NOT NULL,\n" \
+ " launch_app_id TEXT,\n" \
+ " app_label TEXT,\n" \
+ " image_path TEXT,\n" \
+ " priv_image_path TEXT,\n" \
+ " group_id INTEGER DEFAULT 0,\n" \
+ " internal_group_id INTEGER DEFAULT 0,\n" \
+ " priv_id INTEGER PRIMARY KEY AUTOINCREMENT,\n" \
+ " title_key TEXT,\n" \
+ " b_text TEXT,\n" \
+ " b_key TEXT,\n" \
+ " tag TEXT,\n" \
+ " b_format_args TEXT,\n" \
+ " num_format_args INTEGER DEFAULT 0,\n" \
+ " text_domain TEXT,\n" \
+ " text_dir TEXT,\n" \
+ " time INTEGER DEFAULT 0,\n" \
+ " insert_time INTEGER DEFAULT 0,\n" \
+ " args TEXT,\n" \
+ " group_args TEXT,\n" \
+ " b_execute_option TEXT,\n" \
+ " b_service_responding TEXT,\n" \
+ " b_service_single_launch TEXT,\n" \
+ " b_service_multi_launch TEXT,\n" \
+ " b_event_handler_click_on_button_1 TEXT,\n" \
+ " b_event_handler_click_on_button_2 TEXT,\n" \
+ " b_event_handler_click_on_button_3 TEXT,\n" \
+ " b_event_handler_click_on_button_4 TEXT,\n" \
+ " b_event_handler_click_on_button_5 TEXT,\n" \
+ " b_event_handler_click_on_button_6 TEXT,\n" \
+ " b_event_handler_click_on_icon TEXT,\n" \
+ " b_event_handler_click_on_thumbnail TEXT,\n" \
+ " b_event_handler_click_on_text_input_button TEXT,\n" \
+ " b_event_handler_click_on_button_7 TEXT,\n" \
+ " b_event_handler_click_on_button_8 TEXT,\n" \
+ " b_event_handler_click_on_button_9 TEXT,\n" \
+ " b_event_handler_click_on_button_10 TEXT,\n" \
+ " sound_type INTEGER DEFAULT 0,\n" \
+ " sound_path TEXT,\n" \
+ " priv_sound_path TEXT,\n" \
+ " vibration_type INTEGER DEFAULT 0,\n" \
+ " vibration_path TEXT,\n" \
+ " priv_vibration_path TEXT,\n" \
+ " led_operation INTEGER DEFAULT 0,\n" \
+ " led_argb INTEGER DEFAULT 0,\n" \
+ " led_on_ms INTEGER DEFAULT -1,\n" \
+ " led_off_ms INTEGER DEFAULT -1,\n" \
+ " flags_for_property INTEGER DEFAULT 0,\n" \
+ " flag_simmode INTEGER DEFAULT 0,\n" \
+ " display_applist INTEGER,\n" \
+ " progress_size DOUBLE DEFAULT 0,\n" \
+ " progress_percentage DOUBLE DEFAULT 0,\n" \
+ " ongoing_flag INTEGER DEFAULT 0,\n" \
+ " ongoing_value_type INTEGER DEFAULT 0,\n" \
+ " ongoing_current INTEGER DEFAULT 0,\n" \
+ " ongoing_duration INTEGER DEFAULT 0,\n" \
+ " auto_remove INTEGER DEFAULT 1,\n" \
+ " default_button_index INTEGER DEFAULT 0,\n" \
+ " hide_timeout INTEGER DEFAULT 0,\n" \
+ " delete_timeout INTEGER DEFAULT 0,\n" \
+ " text_input_max_length INTEGER DEFAULT 0,\n" \
+ " event_flag INTEGER DEFAULT 0,\n" \
+ " extension_image_size INTEGER DEFAULT 0,\n" \
+ " uid INTEGER );\n" \
+ "CREATE TABLE IF NOT EXISTS noti_group_data (\n" \
+ " caller_app_id TEXT NOT NULL,\n" \
+ " group_id INTEGER DEFAULT 0,\n" \
+ " badge INTEGER DEFAULT 0,\n" \
+ " title TEXT,\n" \
+ " content TEXT,\n" \
+ " loc_title TEXT,\n" \
+ " loc_content TEXT,\n" \
+ " count_display_title INTEGER,\n" \
+ " count_display_content INTEGER,\n" \
+ " rowid INTEGER PRIMARY KEY AUTOINCREMENT,\n" \
+ " UNIQUE (caller_app_id, group_id));\n" \
+ "CREATE TABLE IF NOT EXISTS ongoing_list (\n" \
+ " caller_app_id TEXT NOT NULL,\n" \
+ " launch_app_id TEXT,\n" \
+ " icon_path TEXT,\n" \
+ " group_id INTEGER DEFAULT 0,\n" \
+ " internal_group_id INTEGER DEFAULT 0,\n" \
+ " priv_id INTERGER NOT NULL,\n" \
+ " title TEXT,\n" \
+ " content TEXT,\n" \
+ " default_content TEXT,\n" \
+ " loc_title TEXT,\n" \
+ " loc_content TEXT,\n" \
+ " loc_default_content TEXT,\n" \
+ " text_domain TEXT,\n" \
+ " text_dir TEXT,\n" \
+ " args TEXT,\n" \
+ " group_args TEXT,\n" \
+ " flag INTEGER DEFAULT 0,\n" \
+ " progress_size DOUBLE DEFAULT 0,\n" \
+ " progress_percentage DOUBLE DEFAULT 0,\n" \
+ " rowid INTEGER PRIMARY KEY AUTOINCREMENT,\n" \
+ " UNIQUE (caller_app_id, priv_id));\n" \
+ "CREATE TABLE IF NOT EXISTS notification_setting (\n" \
+ " uid INTEGER,\n" \
+ " package_name TEXT NOT NULL,\n" \
+ " app_id TEXT NOT NULL,\n" \
+ " allow_to_notify INTEGER DEFAULT 1,\n" \
+ " do_not_disturb_except INTEGER DEFAULT 0,\n" \
+ " visibility_class INTEGER DEFAULT 0,\n" \
+ " pop_up_notification INTEGER DEFAULT 1,\n" \
+ " lock_screen_content_level INTEGER DEFAULT 0,\n" \
+ " app_disabled INTEGER DEFAULT 0,\n" \
+ " UNIQUE (uid, package_name, app_id));\n" \
+ "CREATE TABLE IF NOT EXISTS notification_system_setting (\n" \
+ " uid INTEGER,\n" \
+ " do_not_disturb INTEGER DEFAULT 0,\n" \
+ " visibility_class INTEGER DEFAULT 0,\n" \
+ " dnd_schedule_enabled INTEGER DEFAULT 0,\n" \
+ " dnd_schedule_day INTEGER DEFAULT 62,\n" \
+ " dnd_start_hour INTEGER DEFAULT 22,\n" \
+ " dnd_start_min INTEGER DEFAULT 0,\n" \
+ " dnd_end_hour INTEGER DEFAULT 8,\n" \
+ " dnd_end_min INTEGER DEFAULT 0,\n" \
+ " lock_screen_content_level INTEGER DEFAULT 0,\n" \
+ " UNIQUE (uid));\n"\
+ "CREATE TABLE IF NOT EXISTS dnd_allow_exception (\n" \
+ " uid INTEGER,\n" \
+ " type INTEGER DEFAULT 0,\n" \
+ " value INTEGER DEFAULT 0,\n" \
+ " UNIQUE (uid, type));\n" \
+ "CREATE TABLE IF NOT EXISTS noti_template (\n" \
+ " type INTEGER NOT NULL,\n" \
+ " layout INTEGER NOT NULL DEFAULT 0,\n" \
+ " pkg_id TEXT NOT NULL,\n" \
+ " caller_app_id TEXT NOT NULL,\n" \
+ " launch_app_id TEXT,\n" \
+ " app_label TEXT,\n" \
+ " image_path TEXT,\n" \
+ " priv_image_path TEXT,\n" \
+ " group_id INTEGER DEFAULT 0,\n" \
+ " internal_group_id INTEGER DEFAULT 0,\n" \
+ " priv_id INTEGER PRIMARY KEY AUTOINCREMENT,\n" \
+ " title_key TEXT,\n" \
+ " b_text TEXT,\n" \
+ " b_key TEXT,\n" \
+ " tag TEXT,\n" \
+ " b_format_args TEXT,\n" \
+ " num_format_args INTEGER DEFAULT 0,\n" \
+ " text_domain TEXT,\n" \
+ " text_dir TEXT,\n" \
+ " time INTEGER DEFAULT 0,\n" \
+ " insert_time INTEGER DEFAULT 0,\n" \
+ " args TEXT,\n" \
+ " group_args TEXT,\n" \
+ " b_execute_option TEXT,\n" \
+ " b_service_responding TEXT,\n" \
+ " b_service_single_launch TEXT,\n" \
+ " b_service_multi_launch TEXT,\n" \
+ " b_event_handler_click_on_button_1 TEXT,\n" \
+ " b_event_handler_click_on_button_2 TEXT,\n" \
+ " b_event_handler_click_on_button_3 TEXT,\n" \
+ " b_event_handler_click_on_button_4 TEXT,\n" \
+ " b_event_handler_click_on_button_5 TEXT,\n" \
+ " b_event_handler_click_on_button_6 TEXT,\n" \
+ " b_event_handler_click_on_icon TEXT,\n" \
+ " b_event_handler_click_on_thumbnail TEXT,\n" \
+ " b_event_handler_click_on_text_input_button TEXT,\n" \
+ " b_event_handler_click_on_button_7 TEXT,\n" \
+ " b_event_handler_click_on_button_8 TEXT,\n" \
+ " b_event_handler_click_on_button_9 TEXT,\n" \
+ " b_event_handler_click_on_button_10 TEXT,\n" \
+ " sound_type INTEGER DEFAULT 0,\n" \
+ " sound_path TEXT,\n" \
+ " priv_sound_path TEXT,\n" \
+ " vibration_type INTEGER DEFAULT 0,\n" \
+ " vibration_path TEXT,\n" \
+ " priv_vibration_path TEXT,\n" \
+ " led_operation INTEGER DEFAULT 0,\n" \
+ " led_argb INTEGER DEFAULT 0,\n" \
+ " led_on_ms INTEGER DEFAULT -1,\n" \
+ " led_off_ms INTEGER DEFAULT -1,\n" \
+ " flags_for_property INTEGER DEFAULT 0,\n" \
+ " flag_simmode INTEGER DEFAULT 0,\n" \
+ " display_applist INTEGER,\n" \
+ " progress_size DOUBLE DEFAULT 0,\n" \
+ " progress_percentage DOUBLE DEFAULT 0,\n" \
+ " ongoing_flag INTEGER DEFAULT 0,\n" \
+ " ongoing_value_type INTEGER DEFAULT 0,\n" \
+ " ongoing_current INTEGER DEFAULT 0,\n" \
+ " ongoing_duration INTEGER DEFAULT 0,\n" \
+ " auto_remove INTEGER DEFAULT 1,\n" \
+ " default_button_index INTEGER DEFAULT 0,\n" \
+ " hide_timeout INTEGER DEFAULT 0,\n" \
+ " delete_timeout INTEGER DEFAULT 0,\n" \
+ " text_input_max_length INTEGER DEFAULT 0,\n" \
+ " event_flag INTEGER DEFAULT 0,\n" \
+ " extension_image_size INTEGER DEFAULT 0,\n" \
+ " uid INTEGER,\n" \
+ " template_name TEXT,\n" \
+ " UNIQUE (caller_app_id, template_name));\n"
+
+#define NOTI_LIST_DB_ATTRIBUTES_SELECT \
+ "type, layout, pkg_id, caller_app_id, launch_app_id, app_label, "\
+ "image_path, priv_image_path, group_id, priv_id, b_text, b_key, " \
+ "tag, b_format_args, num_format_args, text_domain, text_dir, " \
+ "time, insert_time, args, group_args, b_execute_option, " \
+ "b_service_responding, b_service_single_launch, b_service_multi_launch, " \
+ "b_event_handler_click_on_button_1, b_event_handler_click_on_button_2, " \
+ "b_event_handler_click_on_button_3, b_event_handler_click_on_button_4, " \
+ "b_event_handler_click_on_button_5, b_event_handler_click_on_button_6, " \
+ "b_event_handler_click_on_icon, b_event_handler_click_on_thumbnail, " \
+ "b_event_handler_click_on_text_input_button, " \
+ "b_event_handler_click_on_button_7, b_event_handler_click_on_button_8, " \
+ "b_event_handler_click_on_button_9, b_event_handler_click_on_button_10, " \
+ "sound_type, sound_path, priv_sound_path, " \
+ "vibration_type, vibration_path, priv_vibration_path, " \
+ "led_operation, led_argb, led_on_ms, led_off_ms, " \
+ "flags_for_property, display_applist, " \
+ "progress_size, progress_percentage, ongoing_flag, ongoing_value_type, " \
+ "ongoing_current, ongoing_duration, auto_remove, default_button_index, " \
+ "hide_timeout, delete_timeout, text_input_max_length, event_flag, "\
+ "extension_image_size, uid"
+
+#define NOTI_LIST_DB_ATTRIBUTES_INSERT \
+ "type, layout, pkg_id, caller_app_id, launch_app_id, app_label, " \
+ "image_path, priv_image_path, group_id, internal_group_id, title_key, " \
+ "b_text, b_key, tag, b_format_args, num_format_args, text_domain, " \
+ "text_dir, time, insert_time, args, group_args, b_execute_option, " \
+ "b_service_responding, b_service_single_launch, b_service_multi_launch, " \
+ "b_event_handler_click_on_button_1, b_event_handler_click_on_button_2, " \
+ "b_event_handler_click_on_button_3, b_event_handler_click_on_button_4, " \
+ "b_event_handler_click_on_button_5, b_event_handler_click_on_button_6, " \
+ "b_event_handler_click_on_icon, b_event_handler_click_on_thumbnail, " \
+ "b_event_handler_click_on_text_input_button, " \
+ "b_event_handler_click_on_button_7, b_event_handler_click_on_button_8, " \
+ "b_event_handler_click_on_button_9, b_event_handler_click_on_button_10, " \
+ "sound_type, sound_path, priv_sound_path, " \
+ "vibration_type, vibration_path, priv_vibration_path, " \
+ "led_operation, led_argb, led_on_ms, led_off_ms, " \
+ "flags_for_property, flag_simmode, display_applist, " \
+ "progress_size, progress_percentage, ongoing_flag, ongoing_value_type, " \
+ "ongoing_current, ongoing_duration, auto_remove, default_button_index, " \
+ "hide_timeout, delete_timeout, text_input_max_length, event_flag, " \
+ "extension_image_size, uid"
+
+#define NOTI_LIST_INSERT_VALUES \
+ "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " \
+ "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " \
+ "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " \
+ "?, ?, ?, ?, ?, ? "
+
+#define NOTI_LIST_DB_ATTRIBUTES_UPDATE \
+ "type = ?, layout = ?, launch_app_id = ?, app_label = ?, " \
+ "image_path = ?, priv_image_path = ?, b_text = ?, b_key = ?, tag = ?, " \
+ "b_format_args = ?, num_format_args = ?, text_domain = ?, text_dir = ?, " \
+ "time = ?, insert_time = ?, args = ?, group_args = ?, " \
+ "b_execute_option = ?, b_service_responding = ?, " \
+ "b_service_single_launch = ?, b_service_multi_launch = ?, " \
+ "b_event_handler_click_on_button_1 = ?, " \
+ "b_event_handler_click_on_button_2 = ?, " \
+ "b_event_handler_click_on_button_3 = ?, " \
+ "b_event_handler_click_on_button_4 = ?, " \
+ "b_event_handler_click_on_button_5 = ?, " \
+ "b_event_handler_click_on_button_6 = ?, " \
+ "b_event_handler_click_on_icon = ?, " \
+ "b_event_handler_click_on_thumbnail = ?, " \
+ "b_event_handler_click_on_text_input_button = ?, " \
+ "b_event_handler_click_on_button_7 = ?, " \
+ "b_event_handler_click_on_button_8 = ?, " \
+ "b_event_handler_click_on_button_9 = ?, " \
+ "b_event_handler_click_on_button_10 = ?, " \
+ "sound_type = ?, sound_path = ?, priv_sound_path = ?, " \
+ "vibration_type = ?, vibration_path = ?, priv_vibration_path = ?, " \
+ "led_operation = ?, led_argb = ?, led_on_ms = ?, led_off_ms = ?, " \
+ "flags_for_property = ?, flag_simmode = ?, display_applist = ?, " \
+ "progress_size = ?, progress_percentage = ?, " \
+ "ongoing_flag = ?, ongoing_value_type = ?, " \
+ "ongoing_current = ?, ongoing_duration = ?, " \
+ "auto_remove = ?, default_button_index = ?, " \
+ "hide_timeout = ?, delete_timeout = ?, " \
+ "text_input_max_length = ?, event_flag = ?, extension_image_size = ? "
+
+#define NOTIFICATION_SETTING_DB_ATTRIBUTES \
+ "package_name, app_id, allow_to_notify, do_not_disturb_except, "\
+ "visibility_class, pop_up_notification, lock_screen_content_level, "\
+ "app_disabled"
+
+#define NOTIFICATION_SYSTEM_SETTING_DB_ATTRIBUTES \
+ "do_not_disturb, visibility_class, dnd_schedule_enabled, " \
+ "dnd_schedule_day, dnd_start_hour, dnd_start_min, dnd_end_hour, " \
+ "dnd_end_min, lock_screen_content_level"
+
+#define __BIND_TEXT(db, stmt, i, text, ret, label) \
+do { \
+ ret = sqlite3_bind_text(stmt, i, text, -1, SQLITE_TRANSIENT); \
+ if (ret != SQLITE_OK) { \
+ ERR("bind error(index %d): [%d][%s]", i, ret, \
+ sqlite3_errmsg(db)); \
+ ret = NOTIFICATION_ERROR_FROM_DB; \
+ goto label; \
+ } \
+} while (0)
+
+#define __BIND_TEXT_STATIC(db, stmt, i, text, ret, label) \
+do { \
+ ret = sqlite3_bind_text(stmt, i, text, -1, SQLITE_STATIC); \
+ if (ret != SQLITE_OK) { \
+ ERR("bind error(index %d): [%d][%s]", i, ret, \
+ sqlite3_errmsg(db)); \
+ ret = NOTIFICATION_ERROR_FROM_DB; \
+ goto label; \
+ } \
+} while (0)
+
+#define __BIND_INT(db, stmt, i, int, ret, label) \
+do { \
+ ret = sqlite3_bind_int(stmt, i, int); \
+ if (ret != SQLITE_OK) { \
+ ERR("bind error(index %d): [%d][%s]", i, ret, \
+ sqlite3_errmsg(db)); \
+ ret = NOTIFICATION_ERROR_FROM_DB; \
+ goto label; \
+ } \
+} while (0)
+
+#define __BIND_DOUBLE(db, stmt, i, double, ret, label) \
+do { \
+ ret = sqlite3_bind_double(stmt, i, double); \
+ if (ret != SQLITE_OK) { \
+ ERR("bind error(index %d): [%d][%s]", i, ret, \
+ sqlite3_errmsg(db)); \
+ ret = NOTIFICATION_ERROR_FROM_DB; \
+ goto label; \
+ } \
+} while (0)
diff --git a/notification/src/notification_error.c b/notification/src/notification_error.c
new file mode 100644
index 0000000..4e4c98b
--- /dev/null
+++ b/notification/src/notification_error.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2000 - 2017 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.
+ */
+
+#include <string.h>
+#include <gio/gio.h>
+#include "notification_error.h"
+
+static const GDBusErrorEntry dbus_error_entries[] = {
+ {NOTIFICATION_ERROR_INVALID_PARAMETER, "org.freedesktop.Notification.Error.INVALID_PARAMETER"},
+ {NOTIFICATION_ERROR_OUT_OF_MEMORY, "org.freedesktop.Notification.Error.OUT_OF_MEMORY"},
+ {NOTIFICATION_ERROR_IO_ERROR, "org.freedesktop.Notification.Error.IO_ERROR"},
+ {NOTIFICATION_ERROR_PERMISSION_DENIED, "org.freedesktop.Notification.Error.PERMISSION_DENIED"},
+ {NOTIFICATION_ERROR_FROM_DB, "org.freedesktop.Notification.Error.FROM_DB"},
+ {NOTIFICATION_ERROR_ALREADY_EXIST_ID, "org.freedesktop.Notification.Error.ALREADY_EXIST_ID"},
+ {NOTIFICATION_ERROR_FROM_DBUS, "org.freedesktop.Notification.Error.FROM_DBUS"},
+ {NOTIFICATION_ERROR_NOT_EXIST_ID, "org.freedesktop.Notification.Error.NOT_EXIST_ID"},
+ {NOTIFICATION_ERROR_SERVICE_NOT_READY, "org.freedesktop.Notification.Error.SERVICE_NOT_READY"},
+ {NOTIFICATION_ERROR_INVALID_OPERATION, "org.freedesktop.Notification.Error.INVALID_OPERATION"},
+ {NOTIFICATION_ERROR_MAX_EXCEEDED, "org.freedesktop.Notification.Error.MAX_EXCEEDED"},
+};
+
+#define NOTIFICATION_ERROR_QUARK "notification-error-quark"
+
+EXPORT_API GQuark notification_error_quark(void)
+{
+ static volatile gsize quark_volatile = 0;
+ static const char *domain_name = NULL;
+
+ /* This is for preventing crash when notification api is used in ui-gadget */
+ /* ui-gadget libraries can be unloaded when it is needed and the static string */
+ /* parameter to g_dbus_error_register_error_domain may cause crash. */
+ GQuark quark = g_quark_try_string(NOTIFICATION_ERROR_QUARK);
+
+ if (quark == 0) {
+ if (domain_name == NULL)
+ domain_name = strdup(NOTIFICATION_ERROR_QUARK);
+ } else {
+ domain_name = NOTIFICATION_ERROR_QUARK;
+ }
+
+ g_dbus_error_register_error_domain(domain_name,
+ &quark_volatile,
+ dbus_error_entries,
+ G_N_ELEMENTS(dbus_error_entries));
+ return (GQuark)quark_volatile;
+}
+
diff --git a/notification/src/notification_group.c b/notification/src/notification_group.c
new file mode 100644
index 0000000..b03496a
--- /dev/null
+++ b/notification/src/notification_group.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2000 - 2017 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <notification_debug.h>
+#include <notification_group.h>
+#include <notification_db.h>
+
+/* LCOV_EXCL_START */
+static int _notification_group_check_data_inserted(const char *app_id,
+ int group_id, sqlite3 *db)
+{
+ sqlite3_stmt *stmt = NULL;
+ char query[NOTIFICATION_QUERY_MAX] = { 0, };
+ int ret;
+ int result;
+
+ snprintf(query, sizeof(query),
+ "select count(*) from noti_group_data where caller_app_id = '%s' and group_id = %d",
+ app_id, group_id);
+
+ ret = sqlite3_prepare(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ERR("Get count DB err(%d) : %s", ret, sqlite3_errmsg(db));
+ return NOTIFICATION_ERROR_FROM_DB;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ result = sqlite3_column_int(stmt, 0);
+ else
+ result = 0;
+
+
+ sqlite3_finalize(stmt);
+
+ if (result > 0)
+ return NOTIFICATION_ERROR_ALREADY_EXIST_ID;
+
+ INFO("Check Data Inserted appid[%s] group_id[%d] result[%d]",
+ app_id, group_id, result);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+int notification_group_set_badge(const char *app_id,
+ int group_id, int count)
+{
+ sqlite3 *db;
+ sqlite3_stmt *stmt = NULL;
+ char query[NOTIFICATION_QUERY_MAX] = { 0, };
+ int ret;
+ int result;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ ret = _notification_group_check_data_inserted(app_id, group_id, db);
+
+ if (ret == NOTIFICATION_ERROR_NONE) {
+ /* Insert if does not exist */
+ snprintf(query, sizeof(query), "insert into noti_group_data ("
+ "caller_app_id, group_id, badge, content, loc_content) values ("
+ "'%s', %d, %d, '', '')", app_id, group_id, count);
+
+ } else {
+ /* Update if exist */
+ snprintf(query, sizeof(query), "update noti_group_data "
+ "set badge = %d "
+ "where caller_app_id = '%s' and group_id = %d",
+ count, app_id, group_id);
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ERR("Failed to insert data app_id[%s] err[%d][%s]",
+ app_id, ret, sqlite3_errmsg(db));
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (db)
+ notification_db_close(&db);
+
+ return NOTIFICATION_ERROR_FROM_DB;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_OK || ret == SQLITE_DONE)
+ result = NOTIFICATION_ERROR_NONE;
+ else
+ result = NOTIFICATION_ERROR_FROM_DB;
+
+ sqlite3_finalize(stmt);
+
+ if (db)
+ notification_db_close(&db);
+
+ return result;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+int notification_group_get_badge(const char *app_id,
+ int group_id, int *count)
+{
+ sqlite3 *db;
+ sqlite3_stmt *stmt = NULL;
+ char query[NOTIFICATION_QUERY_MAX] = { 0, };
+ int ret;
+ int col = 0;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ if (group_id == NOTIFICATION_GROUP_ID_NONE) {
+ ret = _notification_group_check_data_inserted(app_id, group_id, db);
+ if (ret == NOTIFICATION_ERROR_NONE)
+ /* Get all of app_id count if none group id is not exist */
+ snprintf(query, sizeof(query),
+ "select sum(badge) "
+ "from noti_group_data "
+ "where caller_app_id = '%s'", app_id);
+ else
+ /* Get none group id count */
+ snprintf(query, sizeof(query),
+ "select badge "
+ "from noti_group_data "
+ "where caller_app_id = '%s' and group_id = %d",
+ app_id, group_id);
+ } else {
+ snprintf(query, sizeof(query),
+ "select badge "
+ "from noti_group_data "
+ "where caller_app_id = '%s' and group_id = %d",
+ app_id, group_id);
+ }
+
+ INFO("Get badge : query[%s]", query);
+
+ ret = sqlite3_prepare(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ERR("Failed to insert data app_id[%s] err[%d][%s]",
+ app_id, ret, sqlite3_errmsg(db));
+ if (db)
+ notification_db_close(&db);
+
+ return NOTIFICATION_ERROR_FROM_DB;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ *count = sqlite3_column_int(stmt, col++);
+
+ sqlite3_finalize(stmt);
+
+ if (db)
+ notification_db_close(&db);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
diff --git a/notification/src/notification_init.c b/notification/src/notification_init.c
new file mode 100644
index 0000000..72d6cdc
--- /dev/null
+++ b/notification/src/notification_init.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2016 - 2017 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.
+ *
+ */
+
+#define _GNU_SOURCE
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+#include <notification_setting.h>
+
+/* For multi-user support */
+#include <tzplatform_config.h>
+
+#define OWNER_ROOT 0
+
+#ifdef _E
+#undef _E
+#endif
+#define _E(fmt, arg...) fprintf(stderr, "[NOTIFICATION_INIT][E][%s,%d] "fmt"\n", \
+ __func__, __LINE__, ##arg)
+
+/* LCOV_EXCL_START */
+static int _is_authorized(void)
+{
+ /* pkg_init db should be called by as root privilege. */
+ uid_t uid = getuid();
+
+ if ((uid_t) OWNER_ROOT == uid)
+ return 1;
+ else
+ return 0;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+int main(int argc, char *argv[])
+{
+ int ret;
+ uid_t uid = 0;
+
+ if (!_is_authorized()) {
+ _E("Not an authorized user");
+ return -1;
+ }
+
+ if (argc > 2)
+ uid = (uid_t)atoi(argv[2]);
+
+ ret = notification_setting_refresh_setting_table(uid);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ _E("Failed to refresh setting table");
+ return ret;
+ }
+
+ ret = notification_system_setting_init_system_setting_table(uid);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ _E("Failed to init system setting table");
+ return ret;
+ }
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
diff --git a/notification/src/notification_internal.c b/notification/src/notification_internal.c
new file mode 100644
index 0000000..bee6eb3
--- /dev/null
+++ b/notification/src/notification_internal.c
@@ -0,0 +1,2133 @@
+/*
+ * Copyright (c) 2000 - 2017 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libintl.h>
+#include <dbus/dbus.h>
+#include <gio/gio.h>
+
+#include <aul.h>
+#include <tizen.h>
+#include <bundle.h>
+#include <bundle_internal.h>
+#include <app_control.h>
+#include <app_control_internal.h>
+#include <pkgmgr-info.h>
+
+#include <notification.h>
+#include <notification_list.h>
+#include <notification_debug.h>
+#include <notification_private.h>
+#include <notification_noti.h>
+#include <notification_ongoing.h>
+#include <notification_group.h>
+#include <notification_ipc.h>
+#include <notification_internal.h>
+#include <notification_shared_file.h>
+
+#define REGULAR_UID_MIN 5000
+
+typedef struct _notification_cb_info notification_cb_info_s;
+typedef struct _notification_event_cb_info notification_event_cb_info_s;
+
+typedef enum __notification_cb_type {
+ NOTIFICATION_CB_NORMAL = 1,
+ NOTIFICATION_CB_DETAILED,
+} _notification_cb_type_e;
+
+struct _notification_cb_info {
+ _notification_cb_type_e cb_type;
+ void (*changed_cb)(void *data, notification_type_e type);
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op);
+ void *data;
+};
+
+struct _notification_event_cb_info {
+ int priv_id;
+ event_handler_cb cb;
+ void *userdata;
+};
+
+static GHashTable *_noti_cb_hash = NULL;
+static GList *__noti_event_cb_list = NULL;
+
+void notification_reset_event_handler_list(void)
+{
+ GList *iter;
+ notification_event_cb_info_s *info;
+
+ if (!__noti_event_cb_list)
+ return;
+
+ iter = g_list_first(__noti_event_cb_list);
+ while (iter) {
+ info = g_list_nth_data(iter, 0);
+ if (info)
+ notification_ipc_reset_event_handler(info->priv_id);
+ iter = g_list_next(iter);
+ }
+}
+
+/* LCOV_EXCL_START */
+static void __free_changed_cb_info(gpointer data)
+{
+ notification_cb_info_s *noti_cb_info = (notification_cb_info_s *)data;
+
+ if (noti_cb_info)
+ free(noti_cb_info);
+}
+/* LCOV_EXCL_STOP */
+
+void notification_call_changed_cb_for_uid(notification_op *op_list, int op_num, uid_t uid)
+{
+ notification_type_e type = NOTIFICATION_TYPE_NOTI;
+ GList *noti_cb_list;
+ notification_cb_info_s *noti_cb_info;
+
+ if (_noti_cb_hash == NULL)
+ return;
+
+ noti_cb_list = (GList *)g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
+ if (noti_cb_list == NULL)
+ return;
+
+ if (op_list == NULL) {
+ ERR("Invalid parameter");
+ return;
+ }
+
+ noti_cb_list = g_list_first(noti_cb_list);
+ notification_get_type(op_list->noti, &type);
+
+ for (; noti_cb_list != NULL; noti_cb_list = noti_cb_list->next) {
+ noti_cb_info = noti_cb_list->data;
+
+ if (noti_cb_info->cb_type == NOTIFICATION_CB_NORMAL && noti_cb_info->changed_cb)
+ noti_cb_info->changed_cb(noti_cb_info->data, type);
+
+ if (noti_cb_info->cb_type == NOTIFICATION_CB_DETAILED && noti_cb_info->detailed_changed_cb) {
+ noti_cb_info->detailed_changed_cb(noti_cb_info->data,
+ type, op_list, op_num);
+ }
+ }
+}
+
+static gint __priv_id_compare(gconstpointer a, gconstpointer b)
+{
+ const notification_event_cb_info_s *info = NULL;
+
+ if (!a)
+ return -1;
+
+ info = (notification_event_cb_info_s *)a;
+
+ if (info->priv_id == GPOINTER_TO_INT(b))
+ return 0;
+
+ return 1;
+}
+
+void notification_call_event_handler_cb(notification_h noti, int event_type)
+{
+ int ret;
+ int priv_id;
+ GList *find_list;
+ notification_event_cb_info_s *info;
+
+ if (__noti_event_cb_list == NULL)
+ return;
+
+ ret = notification_get_id(noti, NULL, &priv_id);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return;
+
+ __noti_event_cb_list = g_list_first(__noti_event_cb_list);
+ find_list = g_list_find_custom(__noti_event_cb_list, GINT_TO_POINTER(priv_id),
+ (GCompareFunc)__priv_id_compare);
+ if (find_list == NULL)
+ return;
+
+ info = g_list_nth_data(find_list, 0);
+ info->cb(noti, event_type, info->userdata);
+}
+
+/* LCOV_EXCL_START */
+void notification_delete_event_handler_cb(int priv_id)
+{
+ GList *delete_list;
+ notification_event_cb_info_s *info;
+
+ if (__noti_event_cb_list == NULL)
+ return;
+
+ __noti_event_cb_list = g_list_first(__noti_event_cb_list);
+ delete_list = g_list_find_custom(__noti_event_cb_list, GINT_TO_POINTER(priv_id),
+ (GCompareFunc)__priv_id_compare);
+
+ if (delete_list == NULL)
+ return;
+
+ info = g_list_nth_data(delete_list, 0);
+ __noti_event_cb_list = g_list_remove(g_list_first(__noti_event_cb_list), info);
+
+ if (info)
+ free(info);
+
+ if (__noti_event_cb_list == NULL)
+ notification_ipc_event_monitor_fini();
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_add_deferred_task(
+ void (*deferred_task_cb)(void *data), void *user_data)
+{
+ if (deferred_task_cb == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ return notification_ipc_add_deffered_task(deferred_task_cb, user_data);
+}
+
+EXPORT_API int notification_del_deferred_task(
+ void (*deferred_task_cb)(void *data))
+{
+ if (deferred_task_cb == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ return notification_ipc_del_deffered_task(deferred_task_cb);
+}
+
+EXPORT_API int notification_resister_changed_cb_for_uid(
+ void (*changed_cb)(void *data, notification_type_e type),
+ void *user_data, uid_t uid)
+{
+ GList *noti_cb_list;
+ notification_cb_info_s *noti_cb_info_new;
+
+ if (changed_cb == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (_noti_cb_hash == NULL)
+ _noti_cb_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+ noti_cb_info_new = (notification_cb_info_s *)malloc(sizeof(notification_cb_info_s));
+ if (noti_cb_info_new == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ noti_cb_info_new->cb_type = NOTIFICATION_CB_NORMAL;
+ noti_cb_info_new->changed_cb = changed_cb;
+ noti_cb_info_new->detailed_changed_cb = NULL;
+ noti_cb_info_new->data = user_data;
+
+ noti_cb_list = g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
+
+ if (noti_cb_list == NULL) {
+ noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
+ g_hash_table_insert(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
+ } else {
+ noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
+ }
+
+ if (notification_ipc_monitor_init(uid) != NOTIFICATION_ERROR_NONE) {
+ notification_unresister_changed_cb_for_uid(changed_cb, uid);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_resister_changed_cb(
+ void (*changed_cb)(void *data, notification_type_e type),
+ void *user_data)
+{
+ return notification_resister_changed_cb_for_uid(changed_cb, user_data, getuid());
+}
+
+static gint _noti_changed_compare(gconstpointer a, gconstpointer b)
+{
+ const struct _notification_cb_info *info = NULL;
+
+ if (!a)
+ return -1;
+ info = (notification_cb_info_s *)a;
+
+ if (info->changed_cb == b)
+ return 0;
+
+ return 1;
+}
+
+EXPORT_API int notification_unresister_changed_cb_for_uid(
+ void (*changed_cb)(void *data, notification_type_e type), uid_t uid)
+{
+ notification_cb_info_s *noti_cb_info;
+ GList *noti_cb_list;
+ GList *delete_cb_list;
+
+ if (changed_cb == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (_noti_cb_hash == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti_cb_list = (GList *)g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
+ if (noti_cb_list == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti_cb_list = g_list_first(noti_cb_list);
+ delete_cb_list = g_list_find_custom(noti_cb_list, (gconstpointer)changed_cb,
+ (GCompareFunc)_noti_changed_compare);
+ if (delete_cb_list) {
+ noti_cb_info = g_list_nth_data(delete_cb_list, 0);
+ noti_cb_list = g_list_delete_link(noti_cb_list, delete_cb_list);
+ __free_changed_cb_info(noti_cb_info);
+
+ if (noti_cb_list == NULL) {
+ g_hash_table_steal(_noti_cb_hash, GUINT_TO_POINTER(uid));
+ } else {
+ noti_cb_list = g_list_first(noti_cb_list);
+ g_hash_table_replace(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
+ }
+
+ } else {
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (g_hash_table_size(_noti_cb_hash) == 0)
+ notification_ipc_monitor_fini();
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_unresister_changed_cb(
+ void (*changed_cb)(void *data, notification_type_e type))
+{
+ return notification_unresister_changed_cb_for_uid(changed_cb, getuid());
+}
+
+EXPORT_API int notification_update_progress(notification_h noti,
+ int priv_id,
+ double progress)
+{
+ int ret;
+ int input_priv_id;
+ char *caller_app_id;
+ double input_progress;
+
+ if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ input_priv_id = noti->priv_id;
+ } else {
+ input_priv_id = priv_id;
+ }
+
+ if (noti == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(noti->caller_app_id);
+
+ if (progress < 0.0)
+ input_progress = 0.0;
+ else if (progress > 1.0)
+ input_progress = 1.0;
+ else
+ input_progress = progress;
+
+ ret = notification_ongoing_update_progress(caller_app_id, input_priv_id,
+ input_progress);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+
+EXPORT_API int notification_update_size(notification_h noti,
+ int priv_id,
+ double size)
+{
+ int ret;
+ int input_priv_id;
+ char *caller_app_id;
+ double input_size;
+
+ if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ input_priv_id = noti->priv_id;
+ } else {
+ input_priv_id = priv_id;
+ }
+
+ if (noti == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(noti->caller_app_id);
+
+ if (size < 0.0)
+ input_size = 0.0;
+ else
+ input_size = size;
+
+ ret = notification_ongoing_update_size(caller_app_id, input_priv_id,
+ input_size);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+
+EXPORT_API int notification_update_content(notification_h noti,
+ int priv_id,
+ const char *content)
+{
+ char *caller_app_id;
+ int input_priv_id;
+ int ret;
+
+ if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ input_priv_id = noti->priv_id;
+ } else {
+ input_priv_id = priv_id;
+ }
+
+ if (noti == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(noti->caller_app_id);
+
+ ret = notification_ongoing_update_content(caller_app_id, input_priv_id,
+ content);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+
+/* notification_set_icon will be removed */
+/* LCOV_EXCL_START */
+EXPORT_API int notification_set_icon(notification_h noti,
+ const char *icon_path)
+{
+ return notification_set_image(noti, NOTIFICATION_IMAGE_TYPE_ICON, icon_path);
+}
+/* LCOV_EXCL_STOP */
+
+/* notification_get_icon will be removed */
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_icon(notification_h noti,
+ char **icon_path)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *ret_image_path = NULL;
+
+ ret = notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_ICON,
+ &ret_image_path);
+
+ if (ret == NOTIFICATION_ERROR_NONE && icon_path != NULL)
+ *icon_path = ret_image_path;
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_translate_localized_text(notification_h noti)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *ret_text = NULL;
+ char buf_key[32];
+ char *bundle_val = NULL;
+ char *new_text;
+ bundle *b;
+ notification_text_type_e type = NOTIFICATION_TEXT_TYPE_TITLE;
+
+ noti->is_translation = false;
+
+ for (; type <= NOTIFICATION_TEXT_TYPE_MAX; type++) {
+ ret = notification_get_text(noti, type, &ret_text);
+ if (ret == NOTIFICATION_ERROR_NONE && ret_text) {
+ if (noti->b_text == NULL) {
+ noti->b_text = bundle_create();
+ if (noti->b_text == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ b = noti->b_text;
+
+ new_text = strdup(ret_text);
+
+ snprintf(buf_key, sizeof(buf_key), "%d", type);
+ bundle_get_str(b, buf_key, &bundle_val);
+ if (bundle_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, new_text);
+ free(new_text);
+ new_text = NULL;
+
+ noti->num_format_args = 0;
+ bundle_val = NULL;
+ }
+ }
+
+ noti->is_translation = true;
+
+ return ret;
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_set_title(notification_h noti,
+ const char *title,
+ const char *loc_title)
+{
+ return notification_set_text(noti, NOTIFICATION_TEXT_TYPE_TITLE,
+ title, loc_title,
+ NOTIFICATION_VARIABLE_TYPE_NONE);
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_title(notification_h noti,
+ char **title,
+ char **loc_title)
+{
+ int ret;
+ char *ret_text = NULL;
+
+ ret = notification_get_text(noti, NOTIFICATION_TEXT_TYPE_TITLE,
+ &ret_text);
+
+ if (title != NULL)
+ *title = ret_text;
+
+ if (loc_title != NULL)
+ *loc_title = NULL;
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_set_content(notification_h noti,
+ const char *content,
+ const char *loc_content)
+{
+ return notification_set_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT,
+ content, loc_content,
+ NOTIFICATION_VARIABLE_TYPE_NONE);
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_content(notification_h noti,
+ char **content,
+ char **loc_content)
+{
+ int ret;
+ char *ret_text = NULL;
+
+ ret = notification_get_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT,
+ &ret_text);
+
+ if (content != NULL)
+ *content = ret_text;
+
+ if (loc_content != NULL)
+ *loc_content = NULL;
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_set_application(notification_h noti,
+ const char *app_id)
+{
+ if (noti == NULL || app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->launch_app_id)
+ free(noti->launch_app_id);
+
+ noti->launch_app_id = strdup(app_id);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_application(notification_h noti,
+ char **app_id)
+{
+ if (noti == NULL || app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->launch_app_id)
+ *app_id = noti->launch_app_id;
+ else
+ *app_id = noti->caller_app_id;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_set_args(notification_h noti, bundle *args,
+ bundle *group_args)
+{
+ if (noti == NULL || args == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->args)
+ bundle_free(noti->args);
+
+ noti->args = bundle_dup(args);
+
+ if (noti->group_args) {
+ bundle_free(noti->group_args);
+ noti->group_args = NULL;
+ }
+
+ if (group_args != NULL)
+ noti->group_args = bundle_dup(group_args);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_args(notification_h noti,
+ bundle **args,
+ bundle **group_args)
+{
+ if (noti == NULL || args == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->args)
+ *args = noti->args;
+ else
+ *args = NULL;
+
+ if (group_args != NULL && noti->group_args)
+ *group_args = noti->group_args;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+int notification_get_grouping_list_for_uid(notification_type_e type, int count,
+ notification_list_h *list, uid_t uid)
+{
+ notification_list_h get_list = NULL;
+ int ret = 0;
+
+ if (list == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_noti_get_grouping_list(type, 1, count, &get_list, NULL, uid);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ *list = get_list;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_grouping_list(notification_type_e type, int count,
+ notification_list_h *list)
+{
+ return notification_get_grouping_list_for_uid(type, count, list, getuid());
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_delete_group_by_group_id(const char *app_id,
+ notification_type_e type,
+ int group_id)
+{
+ int ret;
+ char *caller_app_id;
+
+ if (app_id == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(app_id);
+
+ ret = notification_ipc_request_delete_multiple(type, caller_app_id, getuid());
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+int notification_delete_group_by_priv_id_for_uid(const char *app_id,
+ notification_type_e type,
+ int priv_id, uid_t uid)
+{
+ int ret;
+ char *caller_app_id;
+
+ if (app_id == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(app_id);
+
+ ret = notification_ipc_request_delete_single(type, caller_app_id, priv_id, uid);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_delete_group_by_priv_id(const char *app_id,
+ notification_type_e type,
+ int priv_id)
+{
+ return notification_delete_group_by_priv_id_for_uid(app_id, type, priv_id, getuid());
+}
+
+int notification_get_count_for_uid(notification_type_e type,
+ const char *app_id,
+ int group_id,
+ int priv_id, int *count,
+ uid_t uid)
+{
+ int ret;
+ char *caller_app_id;
+
+ if (count == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (app_id == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(app_id);
+
+ ret = notification_ipc_request_get_count(
+ type,
+ caller_app_id,
+ group_id,
+ priv_id,
+ count,
+ uid);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_count(notification_type_e type,
+ const char *app_id,
+ int group_id,
+ int priv_id, int *count)
+{
+ return notification_get_count_for_uid(type, app_id, group_id, priv_id, count, getuid());
+}
+
+int notification_clear_for_uid(notification_type_e type, uid_t uid)
+{
+ if (type <= NOTIFICATION_TYPE_NONE || type > NOTIFICATION_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ return notification_ipc_request_delete_multiple(type, NULL, uid);
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_clear(notification_type_e type)
+{
+ return notification_clear_for_uid(type, getuid());
+}
+
+EXPORT_API int notification_op_get_data(notification_op *noti_op, notification_op_data_type_e type,
+ void *data)
+{
+ if (noti_op == NULL || data == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ switch (type) {
+ case NOTIFICATION_OP_DATA_TYPE:
+ *((int *)data) = noti_op->type;
+ break;
+ case NOTIFICATION_OP_DATA_PRIV_ID:
+ *((int *)data) = noti_op->priv_id;
+ break;
+ case NOTIFICATION_OP_DATA_NOTI:
+ *((notification_h *)data) = noti_op->noti;
+ break;
+ case NOTIFICATION_OP_DATA_EXTRA_INFO_1:
+ *((int *)data) = noti_op->extra_info_1;
+ break;
+ case NOTIFICATION_OP_DATA_EXTRA_INFO_2:
+ *((int *)data) = noti_op->extra_info_2;
+ break;
+ default:
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_set_pkgname(notification_h noti,
+ const char *pkgname)
+{
+ return notification_set_app_id(noti, pkgname);
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_set_app_id(notification_h noti,
+ const char *app_id)
+{
+ if (noti == NULL || app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ /* Remove previous caller app_id */
+ if (noti->caller_app_id) {
+ free(noti->caller_app_id);
+ noti->caller_app_id = NULL;
+ }
+
+ noti->caller_app_id = strdup(app_id);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+/* LCOV_EXCL_START */
+int notification_delete_all_by_type_for_uid(const char *app_id,
+ notification_type_e type, uid_t uid)
+{
+ int ret;
+ char *caller_app_id;
+
+ if (type <= NOTIFICATION_TYPE_NONE || type > NOTIFICATION_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (app_id == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(app_id);
+
+ ret = notification_ipc_request_delete_multiple(type, caller_app_id, uid);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_delete_all_by_type(const char *app_id,
+ notification_type_e type)
+{
+ return notification_delete_all_by_type_for_uid(app_id, type, getuid());
+}
+
+int notification_delete_by_priv_id_for_uid(const char *app_id,
+ notification_type_e type,
+ int priv_id,
+ uid_t uid)
+{
+ int ret;
+ char *caller_app_id;
+
+ if (priv_id <= NOTIFICATION_PRIV_ID_NONE)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (app_id == NULL)
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ else
+ caller_app_id = strdup(app_id);
+
+ ret = notification_ipc_request_delete_single(type, caller_app_id, priv_id, uid);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_delete_by_priv_id(const char *app_id,
+ notification_type_e type,
+ int priv_id)
+{
+ return notification_delete_by_priv_id_for_uid(app_id, type, priv_id, getuid());
+}
+
+EXPORT_API int notification_set_execute_option(notification_h noti,
+ notification_execute_type_e type,
+ const char *text,
+ const char *key,
+ bundle *service_handle)
+{
+ char buf_key[32] = { 0, };
+ char *ret_val = NULL;
+ bundle *b = NULL;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_EXECUTE_TYPE_NONE
+ || type > NOTIFICATION_EXECUTE_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->b_execute_option == NULL)
+ noti->b_execute_option = bundle_create();
+
+ b = noti->b_execute_option;
+
+ if (text != NULL) {
+ snprintf(buf_key, sizeof(buf_key), "text%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, text);
+ }
+
+ if (key != NULL) {
+ snprintf(buf_key, sizeof(buf_key), "key%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL)
+ bundle_del(b, buf_key);
+
+ bundle_add_str(b, buf_key, key);
+ }
+
+ switch ((int)type) {
+ case NOTIFICATION_EXECUTE_TYPE_RESPONDING:
+ if (noti->b_service_responding != NULL) {
+ bundle_free(noti->b_service_responding);
+ noti->b_service_responding = NULL;
+ }
+
+ if (service_handle != NULL)
+ noti->b_service_responding = bundle_dup(service_handle);
+
+ break;
+ case NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH:
+ if (noti->b_service_single_launch != NULL) {
+ bundle_free(noti->b_service_single_launch);
+ noti->b_service_single_launch = NULL;
+ }
+
+ if (service_handle != NULL)
+ noti->b_service_single_launch =
+ bundle_dup(service_handle);
+
+ break;
+ case NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH:
+ if (noti->b_service_multi_launch != NULL) {
+ bundle_free(noti->b_service_multi_launch);
+ noti->b_service_multi_launch = NULL;
+ }
+
+ if (service_handle != NULL)
+ noti->b_service_multi_launch =
+ bundle_dup(service_handle);
+
+ break;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_id(notification_h noti,
+ int *group_id, int *priv_id)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (group_id) {
+ if (noti->group_id < NOTIFICATION_GROUP_ID_NONE)
+ *group_id = NOTIFICATION_GROUP_ID_NONE;
+ else
+ *group_id = noti->group_id;
+ }
+
+ if (priv_id)
+ *priv_id = noti->priv_id;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_set_priv_id(notification_h noti, int priv_id)
+{
+ if (noti == NULL || priv_id <= 0)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->priv_id = priv_id;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+/* LCOV_EXCL_START */
+notification_h notification_load_for_uid(char *app_id,
+ int priv_id, uid_t uid)
+{
+ int ret;
+ notification_h noti;
+
+ noti = (notification_h)calloc(1, sizeof(struct _notification));
+ if (noti == NULL) {
+ ERR("Failed to alloc memory");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+
+ ret = notification_ipc_request_load_noti_by_priv_id(noti, app_id, priv_id, uid);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ set_last_result(ret);
+ return NULL;
+ }
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+
+ return noti;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API notification_h notification_load(char *app_id,
+ int priv_id)
+{
+ return notification_load_for_uid(app_id, priv_id, getuid());
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API notification_h notification_new(notification_type_e type,
+ int group_id, int priv_id)
+{
+ return notification_create(type);
+}
+
+static void _notification_get_text_domain(notification_h noti)
+{
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_execute_option(notification_h noti,
+ notification_execute_type_e type,
+ const char **text,
+ bundle **service_handle)
+{
+ char buf_key[32] = { 0, };
+ char *ret_val = NULL;
+ char *get_str = NULL;
+ bundle *b = NULL;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type <= NOTIFICATION_EXECUTE_TYPE_NONE
+ || type > NOTIFICATION_EXECUTE_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ switch (type) {
+ case NOTIFICATION_EXECUTE_TYPE_RESPONDING:
+ b = noti->b_service_responding;
+ break;
+ case NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH:
+ b = noti->b_service_single_launch;
+ break;
+ case NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH:
+ b = noti->b_service_multi_launch;
+ break;
+ default:
+ break;
+ }
+
+ if (b != NULL) {
+ if (text != NULL) {
+ if (noti->domain == NULL || noti->dir == NULL)
+ _notification_get_text_domain(noti);
+
+ snprintf(buf_key, sizeof(buf_key), "key%d", type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+ if (ret_val != NULL && noti->domain != NULL
+ && noti->dir != NULL) {
+ bindtextdomain(noti->domain, noti->dir);
+
+ get_str = dgettext(noti->domain, ret_val);
+
+ *text = get_str;
+ } else if (ret_val != NULL) {
+ get_str = dgettext("sys_string", ret_val);
+
+ *text = get_str;
+ } else {
+ snprintf(buf_key, sizeof(buf_key), "text%d",
+ type);
+
+ bundle_get_str(b, buf_key, &ret_val);
+
+ *text = ret_val;
+ }
+ }
+ }
+
+ if (service_handle != NULL)
+ *service_handle = b;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_insert_for_uid(notification_h noti,
+ int *priv_id, uid_t uid)
+{
+ int ret;
+ int id;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->type <= NOTIFICATION_TYPE_NONE
+ || noti->type > NOTIFICATION_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->uid = uid;
+ noti->insert_time = time(NULL);
+
+ ret = notification_ipc_request_insert(noti, &id);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ noti->priv_id = id;
+
+ /* If priv_id is valid data, set priv_id */
+ if (priv_id != NULL)
+ *priv_id = noti->priv_id;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_insert(notification_h noti,
+ int *priv_id)
+{
+ return notification_insert_for_uid(noti, priv_id, getuid());
+}
+
+EXPORT_API int notification_update_async_for_uid(notification_h noti,
+ void (*result_cb)(int priv_id, int result, void *data), void *user_data, uid_t uid)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->uid = uid;
+ /* Update insert time ? */
+ noti->insert_time = time(NULL);
+
+ return notification_ipc_request_update_async(noti, result_cb, user_data);
+}
+
+EXPORT_API int notification_update_async(notification_h noti,
+ void (*result_cb)(int priv_id, int result, void *data), void *user_data)
+{
+ return notification_update_async_for_uid(noti, result_cb, user_data, getuid());
+}
+
+EXPORT_API int notification_register_detailed_changed_cb_for_uid(
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
+ void *user_data, uid_t uid)
+{
+ GList *noti_cb_list = NULL;
+ notification_cb_info_s *noti_cb_info_new = NULL;
+
+ if (detailed_changed_cb == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (_noti_cb_hash == NULL)
+ _noti_cb_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+ noti_cb_info_new = (notification_cb_info_s *)malloc(sizeof(notification_cb_info_s));
+ if (noti_cb_info_new == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ noti_cb_info_new->cb_type = NOTIFICATION_CB_DETAILED;
+ noti_cb_info_new->changed_cb = NULL;
+ noti_cb_info_new->detailed_changed_cb = detailed_changed_cb;
+ noti_cb_info_new->data = user_data;
+
+ noti_cb_list = g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
+
+ if (noti_cb_list == NULL) {
+ noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
+ g_hash_table_insert(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
+ } else {
+ noti_cb_list = g_list_append(noti_cb_list, noti_cb_info_new);
+ }
+
+ if (notification_ipc_monitor_init(uid) != NOTIFICATION_ERROR_NONE) {
+ notification_unregister_detailed_changed_cb_for_uid(detailed_changed_cb, user_data, uid);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_register_detailed_changed_cb(
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
+ void *user_data)
+{
+ return notification_register_detailed_changed_cb_for_uid(detailed_changed_cb, user_data, getuid());
+}
+
+static gint _noti_detailed_changed_compare(gconstpointer a, gconstpointer b)
+{
+ const struct _notification_cb_info *info = NULL;
+
+ if (!a)
+ return -1;
+ info = (notification_cb_info_s *)a;
+
+ if (info->detailed_changed_cb == b)
+ return 0;
+
+ return 1;
+}
+
+EXPORT_API int notification_unregister_detailed_changed_cb_for_uid(
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
+ void *user_data, uid_t uid)
+{
+ notification_cb_info_s *noti_cb_info;
+ GList *noti_cb_list;
+ GList *delete_cb_list;
+
+ if (detailed_changed_cb == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (_noti_cb_hash == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti_cb_list = (GList *)g_hash_table_lookup(_noti_cb_hash, GUINT_TO_POINTER(uid));
+
+ if (noti_cb_list == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti_cb_list = g_list_first(noti_cb_list);
+ delete_cb_list = g_list_find_custom(noti_cb_list, (gconstpointer)detailed_changed_cb,
+ (GCompareFunc)_noti_detailed_changed_compare);
+
+ if (delete_cb_list) {
+ noti_cb_info = (notification_cb_info_s *)g_list_nth_data(delete_cb_list, 0);
+ noti_cb_list = g_list_delete_link(noti_cb_list, delete_cb_list);
+ __free_changed_cb_info(noti_cb_info);
+ if (noti_cb_list == NULL) {
+ g_hash_table_steal(_noti_cb_hash, GUINT_TO_POINTER(uid));
+ } else {
+ noti_cb_list = g_list_first(noti_cb_list);
+ g_hash_table_replace(_noti_cb_hash, GUINT_TO_POINTER(uid), noti_cb_list);
+ }
+
+ } else {
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (g_hash_table_size(_noti_cb_hash) == 0)
+ notification_ipc_monitor_fini();
+
+ return NOTIFICATION_ERROR_NONE;
+
+}
+
+EXPORT_API int notification_unregister_detailed_changed_cb(
+ void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
+ void *user_data)
+{
+ return notification_unregister_detailed_changed_cb_for_uid(detailed_changed_cb, user_data, getuid());
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_is_service_ready(void)
+{
+ return notification_ipc_is_master_ready();
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_set_uid(notification_h noti,
+ uid_t uid)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->uid = uid;
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_uid(notification_h noti,
+ uid_t *uid)
+{
+ if (noti == NULL || uid == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *uid = noti->uid;
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static GList *__copy_private_file(notification_h noti)
+{
+ bundle *dst_b;
+ bundle *src_b;
+ char buf_key[32];
+ char *src_path;
+ char *dst_path;
+ int i;
+ GList *file_list = NULL;
+ int ret;
+
+ if (noti->b_priv_image_path && noti->b_image_path) {
+ dst_b = noti->b_priv_image_path;
+ src_b = noti->b_image_path;
+ for (i = NOTIFICATION_IMAGE_TYPE_ICON; i <= NOTIFICATION_IMAGE_TYPE_MAX; i++) {
+ src_path = NULL;
+ dst_path = NULL;
+
+ snprintf(buf_key, sizeof(buf_key), "%d", i);
+
+ bundle_get_str(dst_b, buf_key, &dst_path);
+ if (dst_path == NULL)
+ continue;
+
+ bundle_get_str(src_b, buf_key, &src_path);
+ if (src_path == NULL)
+ continue;
+
+ ret = notification_copy_private_file(src_path, dst_path);
+ if (ret == NOTIFICATION_ERROR_NONE)
+ file_list = g_list_append(file_list, strdup(dst_path));
+ }
+ }
+ if (noti->sound_path && noti->priv_sound_path) {
+ ret = notification_copy_private_file(noti->sound_path,
+ noti->priv_sound_path);
+ if (ret == NOTIFICATION_ERROR_NONE)
+ file_list = g_list_append(file_list,
+ strdup(noti->priv_sound_path));
+ }
+
+ if (noti->vibration_path && noti->priv_vibration_path) {
+ ret = notification_copy_private_file(noti->vibration_path,
+ noti->priv_vibration_path);
+ if (ret == NOTIFICATION_ERROR_NONE)
+ file_list = g_list_append(file_list,
+ strdup(noti->priv_vibration_path));
+ }
+
+ return file_list;
+}
+
+/* LCOV_EXCL_START */
+static void __remove_private_file(gpointer data, gpointer user_data)
+{
+ GFile *src = NULL;
+ char *path = (char *)data;
+
+ src = g_file_new_for_path(path);
+ if (src) {
+ g_file_delete(src, NULL, NULL);
+ g_object_unref(src);
+ }
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_post_for_uid(notification_h noti, uid_t uid)
+{
+ int ret = 0;
+ int id = 0;
+ GList *file_list;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->type <= NOTIFICATION_TYPE_NONE
+ || noti->type > NOTIFICATION_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ /* Save insert time */
+ noti->insert_time = time(NULL);
+ noti->uid = uid;
+
+ file_list = __copy_private_file(noti);
+ ret = notification_ipc_request_insert(noti, &id);
+ if (ret == NOTIFICATION_ERROR_NONE) {
+ noti->priv_id = id;
+ INFO("Posted notification id[%d]", id);
+ } else {
+ g_list_foreach(file_list, __remove_private_file, NULL);
+ }
+
+ if (file_list)
+ g_list_free_full(file_list, free);
+
+ return ret;
+}
+
+EXPORT_API int notification_update_for_uid(notification_h noti, uid_t uid)
+{
+ if (noti == NULL) {
+ notification_ipc_request_refresh(uid);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ noti->uid = uid;
+ /* Update insert time ? */
+ noti->insert_time = time(NULL);
+
+ return notification_ipc_request_update(noti);
+}
+
+EXPORT_API int notification_delete_for_uid(notification_h noti, uid_t uid)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ return notification_ipc_request_delete_single(NOTIFICATION_TYPE_NONE,
+ noti->caller_app_id, noti->priv_id, uid);
+}
+
+EXPORT_API int notification_delete_all_for_uid(notification_type_e type, uid_t uid)
+{
+ int ret = 0;
+ char *caller_app_id = NULL;
+
+ if (type <= NOTIFICATION_TYPE_NONE || type > NOTIFICATION_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+
+ ret = notification_ipc_request_delete_multiple(type, caller_app_id, uid);
+
+ if (caller_app_id)
+ free(caller_app_id);
+
+ return ret;
+}
+
+EXPORT_API notification_h notification_load_by_tag_for_uid(const char *tag, uid_t uid)
+{
+ int ret;
+ notification_h noti;
+ char *caller_app_id;
+
+ if (tag == NULL) {
+ ERR("Invalid tag");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ caller_app_id = notification_get_app_id_by_pid(getpid());
+ if (!caller_app_id) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get a package name");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ noti = (notification_h)calloc(1, sizeof(struct _notification));
+ if (noti == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc a new notification");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ free(caller_app_id);
+
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_ipc_request_load_noti_by_tag(noti, caller_app_id, (char *)tag, uid);
+ free(caller_app_id);
+
+ set_last_result(ret);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return NULL;
+ }
+
+ return noti;
+}
+
+EXPORT_API notification_h notification_create_from_package_template(const char *app_id, const char *template_name)
+{
+ int ret;
+ notification_h noti;
+
+ if (app_id == NULL || template_name == NULL) {
+ ERR("Invalid parameter");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ noti = (notification_h)calloc(1, sizeof(struct _notification));
+ if (noti == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_ipc_request_create_from_package_template(noti, app_id, template_name);
+ set_last_result(ret);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ notification_free(noti);
+ return NULL;
+ }
+
+ return noti;
+}
+
+EXPORT_API int notification_set_default_button(notification_h noti, notification_button_index_e index)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (index < 0 || index > NOTIFICATION_BUTTON_6)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->default_button_index = index;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_default_button(notification_h noti, notification_button_index_e *index)
+{
+ if (noti == NULL || index == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *index = noti->default_button_index;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_ongoing_value_type(notification_h noti, notification_ongoing_value_type_e *type)
+{
+ if (noti == NULL || type == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *type = noti->ongoing_value_type;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_ongoing_value_type(notification_h noti, notification_ongoing_value_type_e type)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (type < NOTIFICATION_ONGOING_VALUE_TYPE_PERCENT || type > NOTIFICATION_ONGOING_VALUE_TYPE_TIME)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->ongoing_value_type = type;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_ongoing_time(notification_h noti, int *current, int *duration)
+{
+ if (noti == NULL || current == NULL || duration == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *current = noti->ongoing_current;
+ *duration = noti->ongoing_duration;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_ongoing_time(notification_h noti, int current, int duration)
+{
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (current < 0 || duration < 0 || current > duration)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->ongoing_current = current;
+ noti->ongoing_duration = duration;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_hide_timeout(notification_h noti, int *timeout)
+{
+ if (noti == NULL || timeout == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *timeout = noti->hide_timeout;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_hide_timeout(notification_h noti, int timeout)
+{
+ if (noti == NULL || timeout < 0)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->hide_timeout = timeout;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_delete_timeout(notification_h noti, int *timeout)
+{
+ if (noti == NULL || timeout == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *timeout = noti->delete_timeout;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_set_delete_timeout(notification_h noti, int timeout)
+{
+ if (noti == NULL || timeout < 0)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->delete_timeout = timeout;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_text_input_max_length(notification_h noti, int *text_input_max_length)
+{
+ if (noti == NULL || text_input_max_length == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *text_input_max_length = noti->text_input_max_length;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_post_with_event_cb_for_uid(notification_h noti, event_handler_cb cb,
+ void *userdata, uid_t uid)
+{
+ int ret;
+ int priv_id;
+ notification_event_cb_info_s *info = NULL;
+ GList *find_list;
+
+ if (noti == NULL || cb == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->type <= NOTIFICATION_TYPE_NONE || noti->type > NOTIFICATION_TYPE_MAX)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti->insert_time = time(NULL);
+ noti->event_flag = true;
+ noti->uid = uid;
+
+ ret = notification_ipc_request_insert(noti, &priv_id);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ noti->priv_id = priv_id;
+
+ __noti_event_cb_list = g_list_first(__noti_event_cb_list);
+ find_list = g_list_find_custom(__noti_event_cb_list, GINT_TO_POINTER(priv_id),
+ (GCompareFunc)__priv_id_compare);
+
+ if (find_list) {
+ info = g_list_nth_data(find_list, 0);
+ info->cb = cb;
+ info->userdata = userdata;
+ } else {
+ info = (notification_event_cb_info_s *)malloc(sizeof(notification_event_cb_info_s));
+ if (info == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+ info->priv_id = priv_id;
+ info->cb = cb;
+ info->userdata = userdata;
+ __noti_event_cb_list = g_list_append(__noti_event_cb_list, info);
+ }
+
+ return ret;
+}
+
+EXPORT_API int notification_post_with_event_cb(notification_h noti, event_handler_cb cb, void *userdata)
+{
+ return notification_post_with_event_cb_for_uid(noti, cb, userdata, getuid());
+}
+
+EXPORT_API int notification_send_event(notification_h noti, int event_type)
+{
+ int ret;
+ bool event_flag;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (!((event_type >= NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1
+ && event_type <= NOTIFICATION_EVENT_TYPE_MAX) ||
+ (event_type >= NOTIFICATION_EVENT_TYPE_HIDDEN_BY_USER
+ && event_type <= NOTIFICATION_EVENT_TYPE_HIDDEN_BY_EXTERNAL) ||
+ (event_type >= NOTIFICATION_EVENT_TYPE_PRESSED
+ && event_type <= NOTIFICATION_EVENT_TYPE_DELETED)))
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_get_event_flag(noti, &event_flag);
+ if (ret != NOTIFICATION_ERROR_NONE || event_flag == false)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_ipc_send_event(noti, event_type, -1);
+
+ return ret;
+}
+
+EXPORT_API int notification_send_event_by_priv_id(int priv_id, int event_type)
+{
+ int ret;
+
+ if (priv_id <= 0)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (!((event_type >= NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1
+ && event_type <= NOTIFICATION_EVENT_TYPE_MAX) ||
+ (event_type >= NOTIFICATION_EVENT_TYPE_HIDDEN_BY_USER
+ && event_type <= NOTIFICATION_EVENT_TYPE_HIDDEN_BY_EXTERNAL) ||
+ (event_type >= NOTIFICATION_EVENT_TYPE_PRESSED
+ && event_type <= NOTIFICATION_EVENT_TYPE_DELETED)))
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_ipc_send_event(NULL, event_type, priv_id);
+ return ret;
+}
+
+EXPORT_API int notification_get_event_flag(notification_h noti, bool *flag)
+{
+ if (noti == NULL || flag == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *flag = noti->event_flag;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_check_event_receiver_available(notification_h noti, bool *available)
+{
+ int ret;
+ int priv_id;
+
+ if (noti == NULL || available == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_get_id(noti, NULL, &priv_id);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get priv id");
+ return ret;
+ }
+
+ ret = notification_ipc_check_event_receiver(priv_id, available);
+
+ return ret;
+}
+
+static bundle *_create_bundle_from_bundle_raw(bundle_raw *string)
+{
+ if (string == NULL || string[0] == '\0')
+ return NULL;
+
+ return bundle_decode(string, strlen((char *)string));
+}
+
+EXPORT_API int notification_set_extention_data(notification_h noti, const char *key, bundle *value)
+{
+ return notification_set_extension_data(noti, key, value);
+}
+
+EXPORT_API int notification_set_extension_data(notification_h noti, const char *key, bundle *value)
+{
+ int ret;
+ int len = 0;
+ char *del = NULL;
+ bundle_raw *raw = NULL;
+
+ if (noti == NULL || key == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->args == NULL)
+ noti->args = bundle_create();
+
+ if (value == NULL) {
+ ret = bundle_del(noti->args, key);
+ if (ret == BUNDLE_ERROR_NONE)
+ return NOTIFICATION_ERROR_NONE;
+ else
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ bundle_get_str(noti->args, key, &del);
+ if (del != NULL) {
+ bundle_del(noti->args, key);
+ del = NULL;
+ }
+
+ bundle_encode(value, &raw, &len);
+ bundle_add_str(noti->args, key, (const char *)raw);
+ bundle_free_encoded_rawdata(&raw);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_extention_data(notification_h noti, const char *key, bundle **value)
+{
+ return notification_get_extension_data(noti, key, value);
+}
+
+EXPORT_API int notification_get_extension_data(notification_h noti, const char *key, bundle **value)
+{
+ char *ret_str;
+ bundle *args;
+
+ if (noti == NULL || key == NULL || value == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->args == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ args = noti->args;
+
+ bundle_get_str(args, key, &ret_str);
+ if (ret_str == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ *value = _create_bundle_from_bundle_raw((bundle_raw *)ret_str);
+ if (*value == NULL)
+ return NOTIFICATION_ERROR_IO_ERROR;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+#define KEY_LEN 40
+#define EXTENSION_EVENT_KEY "_NOTIFICATION_EXTENSION_EVENT_"
+EXPORT_API int notification_set_extension_event_handler(notification_h noti,
+ notification_event_type_extension_e event,
+ app_control_h event_handler)
+{
+ int err;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int len;
+ bundle *app_control_bundle = NULL;
+ bundle_raw *b_raw = NULL;
+ char key[KEY_LEN];
+ char *del = NULL;
+
+ if (noti == NULL || event_handler == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (event < NOTIFICATION_EVENT_TYPE_HIDDEN_BY_USER ||
+ event > NOTIFICATION_EVENT_TYPE_HIDDEN_BY_EXTERNAL) {
+ ERR("Invalid event [%d]", event);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (noti->args == NULL)
+ noti->args = bundle_create();
+
+ snprintf(key, sizeof(key), "%s%d", EXTENSION_EVENT_KEY, event);
+ bundle_get_str(noti->args, key, &del);
+ if (del != NULL) {
+ bundle_del(noti->args, key);
+ del = NULL;
+ }
+
+ err = app_control_export_as_bundle(event_handler, &app_control_bundle);
+ if (err != APP_CONTROL_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to export app_control to bundle [%d]", err);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = bundle_encode(app_control_bundle, &b_raw, &len);
+ if (err != BUNDLE_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to encode bundle [%d]", err);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = bundle_add_str(noti->args, key, (const char *)b_raw);
+ if (err != BUNDLE_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to add str to bundle [%d]", err);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+out:
+ if (b_raw)
+ bundle_free_encoded_rawdata(&b_raw);
+ if (app_control_bundle)
+ bundle_free(app_control_bundle);
+
+ return ret;
+}
+
+EXPORT_API int notification_get_extension_event_handler(notification_h noti,
+ notification_event_type_extension_e event,
+ app_control_h *event_handler)
+{
+ int err;
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *ret_str = NULL;
+ char key[KEY_LEN];
+ bundle *app_control_bundle = NULL;
+ app_control_h ret_app_control = NULL;
+
+ if (noti == NULL || event_handler == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (event < NOTIFICATION_EVENT_TYPE_HIDDEN_BY_USER ||
+ event > NOTIFICATION_EVENT_TYPE_HIDDEN_BY_EXTERNAL) {
+ ERR("Invalid event [%d]", event);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ snprintf(key, sizeof(key), "%s%d", EXTENSION_EVENT_KEY, event);
+
+ bundle_get_str(noti->args, key, &ret_str);
+ if (ret_str == NULL) {
+ ERR("No handler, Invalid event[%d]", event);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ app_control_bundle = _create_bundle_from_bundle_raw((bundle_raw *)ret_str);
+ if (app_control_bundle == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to create bundle");
+ return NOTIFICATION_ERROR_IO_ERROR;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = app_control_create(&ret_app_control);
+ if (err != APP_CONTROL_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to create app control [%d]", err);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = app_control_import_from_bundle(ret_app_control, app_control_bundle);
+ if (err != APP_CONTROL_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to import app control from bundle [%d]", err);
+ app_control_destroy(ret_app_control);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ *event_handler = ret_app_control;
+
+out:
+ if (app_control_bundle)
+ bundle_free(app_control_bundle);
+
+ return ret;
+}
+
+EXPORT_API int notification_get_all_count_for_uid(notification_type_e type, int *count, uid_t uid)
+{
+ int ret;
+
+ if (count == NULL) {
+ ERR("Invalid parameter - count is null");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (type < NOTIFICATION_TYPE_NONE || type > NOTIFICATION_TYPE_MAX) {
+ ERR("Invalid parameter - wrong type");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ ret = notification_ipc_request_get_all_count(type, count, uid);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get count [%d]", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+EXPORT_API int notification_get_all_count(notification_type_e type, int *count)
+{
+ return notification_get_all_count_for_uid(type, count, getuid());
+}
+
+EXPORT_API int notification_set_app_label(notification_h noti, char *label)
+{
+ if (noti == NULL || label == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->app_label)
+ free(noti->app_label);
+
+ noti->app_label = strdup(label);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_app_label(notification_h noti, char **label)
+{
+ if (noti == NULL || label == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->app_label)
+ *label = noti->app_label;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static void __set_caller_info(bundle *b, const char *appid, uid_t uid)
+{
+ pkgmgrinfo_appinfo_h handle;
+ char buf[12];
+ char *pkgid = NULL;
+ int r;
+
+ snprintf(buf, sizeof(buf), "%u", uid);
+ bundle_del(b, AUL_K_ORG_CALLER_UID);
+ bundle_add(b, AUL_K_ORG_CALLER_UID, buf);
+
+ bundle_del(b, AUL_K_ORG_CALLER_APPID);
+ bundle_add(b, AUL_K_ORG_CALLER_APPID, appid);
+
+ r = pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid, &handle);
+ if (r != PMINFO_R_OK)
+ return;
+
+ pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
+ if (pkgid) {
+ bundle_del(b, AUL_K_ORG_CALLER_PKGID);
+ bundle_add(b, AUL_K_ORG_CALLER_PKGID, pkgid);
+ }
+ pkgmgrinfo_appinfo_destroy_appinfo(handle);
+}
+
+static void __set_indirect_request(bundle *b)
+{
+ bundle_del(b, AUL_K_REQUEST_TYPE);
+ bundle_add(b, AUL_K_REQUEST_TYPE, "indirect-request");
+}
+
+EXPORT_API int notification_set_indirect_request(notification_h noti,
+ pid_t pid, uid_t uid)
+{
+ char appid[256] = { 0, };
+ int r;
+ int i;
+
+ if (noti == NULL || pid <= 1 || uid < REGULAR_UID_MIN)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ r = aul_app_get_appid_bypid(pid, appid, sizeof(appid));
+ if (r != AUL_R_OK)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->b_service_responding) {
+ __set_caller_info(noti->b_service_responding, appid, uid);
+ __set_indirect_request(noti->b_service_responding);
+ }
+
+ if (noti->b_service_single_launch) {
+ __set_caller_info(noti->b_service_single_launch, appid, uid);
+ __set_indirect_request(noti->b_service_single_launch);
+ }
+
+ if (noti->b_service_multi_launch) {
+ __set_caller_info(noti->b_service_multi_launch, appid, uid);
+ __set_indirect_request(noti->b_service_multi_launch);
+ }
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++) {
+ if (noti->b_event_handler[i]) {
+ __set_caller_info(noti->b_event_handler[i], appid, uid);
+ __set_indirect_request(noti->b_event_handler[i]);
+ }
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+
+int notification_delete_by_display_applist_for_uid(int display_applist, uid_t uid)
+{
+ if (display_applist < NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ return notification_ipc_request_delete_by_display_applist(display_applist, uid);
+}
+
+EXPORT_API int notification_delete_by_display_applist(int display_applist)
+{
+ return notification_delete_by_display_applist_for_uid(display_applist, getuid());
+}
diff --git a/notification/src/notification_ipc.c b/notification/src/notification_ipc.c
new file mode 100644
index 0000000..c0446e9
--- /dev/null
+++ b/notification/src/notification_ipc.c
@@ -0,0 +1,2726 @@
+/*
+ * Copyright (c) 2000 - 2017 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.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <bundle_internal.h>
+
+#include <notification_ipc.h>
+#include <notification_db.h>
+#include <notification_type.h>
+#include <notification_private.h>
+#include <notification_debug.h>
+#include <notification_setting.h>
+#include <notification_setting_internal.h>
+#include <notification_internal.h>
+
+#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
+
+#define PROVIDER_BUS_NAME "org.tizen.data_provider_service"
+#define PROVIDER_OBJECT_PATH "/org/tizen/data_provider_service"
+#define PROVIDER_NOTI_INTERFACE_NAME "org.tizen.data_provider_noti_service"
+#define PROVIDER_NOTI_EVENT_INTERFACE_NAME "org.tizen.data_provider_noti_event_service"
+
+#define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
+#define DBUS_PATH_DBUS "/org/freedesktop/DBus"
+#define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
+#define ERR_BUFFER_SIZE 1024
+
+static const gchar *_bus_name = NULL;
+static GDBusConnection *_gdbus_conn = NULL;
+static guint provider_watcher_id = 0;
+static int monitor_id = 0;
+static int event_monitor_id = 0;
+static int provider_monitor_id = 0;
+static int is_master_started = 0;
+
+typedef struct _result_cb_item {
+ void (*result_cb)(int priv_id, int result, void *data);
+ void *data;
+} result_cb_item;
+
+typedef struct _task_list task_list;
+struct _task_list {
+ task_list *prev;
+ task_list *next;
+
+ void (*task_cb)(void *data);
+ void *data;
+};
+
+static task_list *g_task_list;
+
+static int _ipc_monitor_register(uid_t uid);
+static int _ipc_monitor_deregister(void);
+static void _do_deffered_task(void);
+
+static void _print_noti(notification_h noti)
+{
+ char *app_id = NULL;
+ char *text = NULL;
+ char *content = NULL;
+ const char *tag = NULL;
+
+ notification_get_pkgname(noti, &app_id);
+ notification_get_text(noti, NOTIFICATION_TEXT_TYPE_TITLE, &text);
+ notification_get_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT, &content);
+ notification_get_tag(noti, &tag);
+
+ DBG("Noti-info : app_id[%s] title[%s] content[%s] tag[%s] priv_id[%d]",
+ app_id, text, content, tag, noti->priv_id);
+}
+
+static void __provider_appeared_cb(GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ INFO("name [%s] name_owner[%s]", name, name_owner);
+ notification_reset_event_handler_list();
+}
+
+/* LCOV_EXCL_START */
+static void __provider_vanished_cb(GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ INFO("name [%s]", name);
+}
+/* LCOV_EXCL_STOP */
+
+static int _dbus_init(void)
+{
+ GError *error = NULL;
+
+ if (_gdbus_conn == NULL) {
+ _gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+
+ if (_gdbus_conn == NULL) {
+ /* LCOV_EXCL_START */
+ if (error != NULL) {
+ ERR("Failed to get dbus[%s]",
+ error->message);
+ g_error_free(error);
+ }
+ return NOTIFICATION_ERROR_IO_ERROR;
+ /* LCOV_EXCL_STOP */
+ }
+ _bus_name = g_dbus_connection_get_unique_name(_gdbus_conn);
+ INFO("Connected bus name[%s]", _bus_name);
+
+ notification_error_quark();
+ }
+
+ if (provider_watcher_id == 0) {
+ provider_watcher_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM,
+ PROVIDER_BUS_NAME,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ __provider_appeared_cb,
+ __provider_vanished_cb,
+ NULL,
+ NULL);
+ DBG("Watching data-provider-master is [%s] watcher_id [%d]",
+ provider_watcher_id ? "success" : "fail", provider_watcher_id);
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+/* LCOV_EXCL_START */
+int notification_ipc_is_master_ready(void)
+{
+ GVariant *result;
+ GError *err = NULL;
+ gboolean name_exist;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ ret = _dbus_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", ret);
+ is_master_started = 0;
+ return is_master_started;
+ }
+
+ result = g_dbus_connection_call_sync(
+ _gdbus_conn,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "NameHasOwner",
+ g_variant_new("(s)", PROVIDER_BUS_NAME),
+ G_VARIANT_TYPE("(b)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &err);
+
+ if (err || (result == NULL)) {
+ if (err) {
+ ERR("No reply[%s]", err->message);
+ g_error_free(err);
+ }
+ ERR("Failed to ready master");
+ is_master_started = 0;
+ } else {
+ g_variant_get(result, "(b)", &name_exist);
+
+ if (!name_exist) {
+ ERR("The master has been stopped, Not exsited name[%s]", PROVIDER_BUS_NAME);
+ is_master_started = 0;
+ } else {
+ DBG("The master has been started");
+ is_master_started = 1;
+ }
+ }
+
+ if (result)
+ g_variant_unref(result);
+
+ return is_master_started;
+}
+/* LCOV_EXCL_STOP */
+
+/* TODO: dbus activation isn't enough ? */
+/*
+ * store tasks when daemon stopped
+ */
+int notification_ipc_add_deffered_task(
+ void (*deferred_task_cb)(void *data),
+ void *user_data)
+{
+ task_list *list;
+ task_list *list_new;
+
+ list_new = (task_list *) malloc(sizeof(task_list));
+ if (list_new == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+
+ list_new->next = NULL;
+ list_new->prev = NULL;
+
+ list_new->task_cb = deferred_task_cb;
+ list_new->data = user_data;
+
+ if (g_task_list == NULL) {
+ g_task_list = list_new;
+ } else {
+ list = g_task_list;
+
+ while (list->next != NULL)
+ list = list->next;
+
+ list->next = list_new;
+ list_new->prev = list;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_ipc_del_deffered_task(
+ void (*deferred_task_cb)(void *data))
+{
+ task_list *list_del;
+ task_list *list_prev;
+ task_list *list_next;
+
+ list_del = g_task_list;
+
+ if (list_del == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ while (list_del->prev != NULL)
+ list_del = list_del->prev;
+
+ do {
+ if (list_del->task_cb == deferred_task_cb) {
+ list_prev = list_del->prev;
+ list_next = list_del->next;
+
+ if (list_prev == NULL)
+ g_task_list = list_next;
+ else
+ list_prev->next = list_next;
+
+ if (list_next == NULL) {
+ if (list_prev != NULL)
+ list_prev->next = NULL;
+ } else {
+ list_next->prev = list_prev;
+ }
+
+ free(list_del);
+ return NOTIFICATION_ERROR_NONE;
+ }
+ list_del = list_del->next;
+ } while (list_del != NULL);
+
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+}
+
+/* LCOV_EXCL_START */
+static void _do_deffered_task(void)
+{
+ task_list *list_do;
+ task_list *list_temp;
+
+ if (g_task_list == NULL)
+ return;
+
+ list_do = g_task_list;
+ g_task_list = NULL;
+
+ while (list_do->prev != NULL)
+ list_do = list_do->prev;
+
+ while (list_do != NULL) {
+ if (list_do->task_cb != NULL) {
+ list_do->task_cb(list_do->data);
+ DBG("called:%p", list_do->task_cb);
+ }
+ list_temp = list_do->next;
+ free(list_do);
+ list_do = list_temp;
+ }
+}
+/* LCOV_EXCL_STOP */
+
+/*!
+ * functions to create operation list
+ */
+static notification_op *_ipc_create_op(notification_op_type_e type,
+ int num_op, int *list_priv_id, int num_priv_id, notification_h *noti_list)
+{
+ int i;
+ notification_op *op_list;
+
+ if (num_op <= 0)
+ return NULL;
+
+ op_list = (notification_op *)malloc(sizeof(notification_op) * num_op);
+ if (op_list == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ memset(op_list, 0x0, sizeof(notification_op) * num_op);
+
+ for (i = 0; i < num_op; i++) {
+ (op_list + i)->type = type;
+ if (list_priv_id != NULL)
+ (op_list + i)->priv_id = *(list_priv_id + i);
+ if (noti_list != NULL)
+ (op_list + i)->noti = *(noti_list + i);
+ }
+
+ return op_list;
+}
+
+/*!
+ * utility functions creating notification packet
+ */
+static inline char *_dup_string(const char *string)
+{
+ char *ret;
+ char err_buf[ERR_BUFFER_SIZE];
+
+ if (string == NULL || string[0] == '\0')
+ return NULL;
+
+ ret = strdup(string);
+ if (!ret)
+ ERR("Failed to strdup[%s]",
+ strerror_r(errno, err_buf, sizeof(err_buf)));
+
+ return ret;
+}
+
+static inline bundle *_create_bundle_from_bundle_raw(bundle_raw *string)
+{
+ if (string == NULL || string[0] == '\0')
+ return NULL;
+
+ return bundle_decode(string, strlen((char *)string));
+}
+
+/* LCOV_EXCL_START */
+static void _add_noti_notify(GVariant *parameters)
+{
+ int ret;
+ notification_h noti;
+ notification_op *noti_op = NULL;
+ GVariant *body = NULL;
+ uid_t uid;
+
+ DBG("add noti notify");
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (!noti) {
+ ERR("Failed to create notification handle");
+ return;
+ }
+
+ g_variant_get(parameters, "(v)", &body);
+ notification_ipc_make_noti_from_gvariant(noti, body);
+ _print_noti(noti);
+ if (noti->flags_for_property & NOTIFICATION_PROP_DISABLE_UPDATE_ON_INSERT) {
+ ERR("Disable changed callback[%d]", noti->flags_for_property);
+ /* Disable changed cb */
+ } else {
+ /* Enable changed cb */
+ noti_op = _ipc_create_op(NOTIFICATION_OP_INSERT, 1, &(noti->priv_id), 1, &noti);
+ ret = notification_get_uid(noti, &uid);
+ if (noti_op != NULL && ret == NOTIFICATION_ERROR_NONE)
+ notification_call_changed_cb_for_uid(noti_op, 1, uid);
+ }
+ g_variant_unref(body);
+ notification_free(noti);
+ if (noti_op)
+ free(noti_op);
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static void _update_noti_notify(GVariant *parameters)
+{
+ int ret;
+ notification_h noti;
+ notification_op *noti_op = NULL;
+ GVariant *body = NULL;
+ uid_t uid;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (!noti) {
+ ERR("Failed to create notification handle");
+ return;
+ }
+
+ g_variant_get(parameters, "(v)", &body);
+ notification_ipc_make_noti_from_gvariant(noti, body);
+ _print_noti(noti);
+
+ noti_op = _ipc_create_op(NOTIFICATION_OP_UPDATE, 1, &(noti->priv_id), 1, &noti);
+ ret = notification_get_uid(noti, &uid);
+ if (noti_op != NULL && ret == NOTIFICATION_ERROR_NONE)
+ notification_call_changed_cb_for_uid(noti_op, 1, uid);
+
+ g_variant_unref(body);
+ notification_free(noti);
+ if (noti_op)
+ free(noti_op);
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static void _refresh_noti_notify(GVariant *parameters)
+{
+ uid_t uid;
+ notification_op *noti_op = _ipc_create_op(NOTIFICATION_OP_REFRESH, 1, NULL, 0, NULL);
+
+ g_variant_get(parameters, "(i)", &uid);
+
+ if (noti_op != NULL) {
+ notification_call_changed_cb_for_uid(noti_op, 1, uid);
+ free(noti_op);
+ }
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static void _delete_single_notify(GVariant *parameters)
+{
+ int num_deleted;
+ int priv_id;
+ notification_op *noti_op;
+ uid_t uid;
+
+ /* num_deleted ?? */
+ g_variant_get(parameters, "(iii)", &num_deleted, &priv_id, &uid);
+
+ noti_op = _ipc_create_op(NOTIFICATION_OP_DELETE, 1, &priv_id, 1, NULL);
+ if (noti_op != NULL) {
+ notification_call_changed_cb_for_uid(noti_op, 1, uid);
+ free(noti_op);
+ }
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static void _delete_multiple_notify(GVariant *parameters)
+{
+ int *buf;
+ int idx = 0;
+ int num;
+ notification_op *noti_op;
+ GVariantIter *iter;
+ uid_t uid;
+
+ g_variant_get(parameters, "(a(i)ii)", &iter, &num, &uid);
+ if (num <= 0) {
+ ERR("Invalid number to delete");
+ return;
+ }
+ DBG("Deleted count[%d]", num);
+
+ buf = (int *)malloc(sizeof(int) * num);
+ if (buf == NULL) {
+ ERR("Failed to alloc");
+ return;
+ }
+
+ while (idx < num && g_variant_iter_loop(iter, "(i)", &buf[idx])) {
+ DBG("priv id[%d]", buf[idx]);
+ idx++;
+ }
+ g_variant_iter_free(iter);
+
+ noti_op = _ipc_create_op(NOTIFICATION_OP_DELETE, idx, buf, idx, NULL);
+ if (noti_op == NULL) {
+ ERR("Failed to create op");
+ free(buf);
+ return;
+ }
+
+ notification_call_changed_cb_for_uid(noti_op, idx, uid);
+ free(noti_op);
+ free(buf);
+}
+/* LCOV_EXCL_STOP */
+
+static void _delete_by_display_applist_notify(GVariant *parameters)
+{
+ int *buf;
+ int idx = 0;
+ int num;
+ notification_op *noti_op;
+ GVariantIter *iter;
+ uid_t uid;
+
+ g_variant_get(parameters, "(a(i)ii)", &iter, &num, &uid);
+ if (num <= 0) {
+ ERR("Invalid number to delete");
+ return;
+ }
+
+ DBG("Deleted count[%d]", num);
+
+ buf = (int *)malloc(sizeof(int) * num);
+ if (buf == NULL) {
+ ERR("Failed to alloc");
+ return;
+ }
+
+ while (idx < num && g_variant_iter_loop(iter, "(i)", &buf[idx])) {
+ DBG("priv id[%d]", buf[idx]);
+ idx++;
+ }
+ g_variant_iter_free(iter);
+
+ noti_op = _ipc_create_op(NOTIFICATION_OP_DELETE, idx, buf, idx, NULL);
+ if (noti_op == NULL) {
+ ERR("Failed to create op");
+ free(buf);
+ return;
+ }
+
+ notification_call_changed_cb_for_uid(noti_op, idx, uid);
+ free(noti_op);
+ free(buf);
+}
+
+/* LCOV_EXCL_START */
+static void _change_dnd_notify(GVariant *parameters)
+{
+ int do_not_disturb;
+ uid_t uid;
+
+ g_variant_get(parameters, "(ii)", &do_not_disturb, &uid);
+ DBG("do_not_disturb[%d], uid[%d]", do_not_disturb, uid);
+
+ notification_call_dnd_changed_cb_for_uid(do_not_disturb, uid);
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static void _handle_noti_notify(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ DBG("own_name : %s signal_name: %s",
+ g_dbus_connection_get_unique_name(connection),
+ signal_name);
+
+ if (g_strcmp0(signal_name, "add_noti_notify") == 0)
+ _add_noti_notify(parameters);
+ else if (g_strcmp0(signal_name, "update_noti_notify") == 0)
+ _update_noti_notify(parameters);
+ else if (g_strcmp0(signal_name, "delete_single_notify") == 0)
+ _delete_single_notify(parameters);
+ else if (g_strcmp0(signal_name, "delete_multiple_notify") == 0)
+ _delete_multiple_notify(parameters);
+ else if (g_strcmp0(signal_name, "refresh_noti_notify") == 0)
+ _refresh_noti_notify(parameters);
+ else if (g_strcmp0(signal_name, "change_dnd_notify") == 0)
+ _change_dnd_notify(parameters);
+ else if (g_strcmp0(signal_name, "delete_by_display_applist_notify") == 0)
+ _delete_by_display_applist_notify(parameters);
+}
+/* LCOV_EXCL_STOP */
+
+static void _send_event(GVariant *parameters)
+{
+ int ret;
+ int event_type;
+ notification_h noti;
+ GVariant *coupled_body;
+ GVariant *body;
+
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (noti == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to create notification handle");
+ return;
+ /* LCOV_EXCL_STOP */
+ }
+
+ g_variant_get(parameters, "(vi)", &coupled_body, &event_type);
+ g_variant_get(coupled_body, "(v)", &body);
+
+ ret = notification_ipc_make_noti_from_gvariant(noti, body);
+ g_variant_unref(coupled_body);
+ g_variant_unref(body);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to make notification handle from gvariant");
+ notification_free(noti);
+ return;
+ /* LCOV_EXCL_STOP */
+ }
+
+ notification_call_event_handler_cb(noti, event_type);
+ notification_free(noti);
+}
+
+/* LCOV_EXCL_START */
+static void _delete_event(GVariant *parameters)
+{
+ int priv_id;
+
+ g_variant_get(parameters, "(i)", &priv_id);
+ notification_delete_event_handler_cb(priv_id);
+}
+/* LCOV_EXCL_STOP */
+
+static void _handle_noti_event_handler_notify(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ DBG("own_name : %s signal_name: %s",
+ g_dbus_connection_get_unique_name(connection), signal_name);
+
+ if (g_strcmp0(signal_name, "send_event") == 0)
+ _send_event(parameters);
+ else if (g_strcmp0(signal_name, "delete_noti") == 0)
+ _delete_event(parameters);
+}
+
+static int _dbus_event_handler_signal_init(void)
+{
+ int id;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (event_monitor_id == 0) {
+ id = g_dbus_connection_signal_subscribe(_gdbus_conn,
+ PROVIDER_BUS_NAME,
+ PROVIDER_NOTI_EVENT_INTERFACE_NAME, /* interface */
+ NULL, /* member */
+ PROVIDER_OBJECT_PATH, /* path */
+ NULL, /* arg0 */
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ _handle_noti_event_handler_notify,
+ NULL,
+ NULL);
+
+ DBG("subscribe id[%d]", id);
+ if (id == 0) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR("Failed to subscribe connection signal");
+ /* LCOV_EXCL_STOP */
+ } else {
+ event_monitor_id = id;
+ }
+ }
+
+ return ret;
+}
+
+static int _dbus_signal_init(void)
+{
+ int id;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (monitor_id == 0) {
+ id = g_dbus_connection_signal_subscribe(_gdbus_conn,
+ PROVIDER_BUS_NAME,
+ PROVIDER_NOTI_INTERFACE_NAME, /* interface */
+ NULL, /* member */
+ PROVIDER_OBJECT_PATH, /* path */
+ NULL, /* arg0 */
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ _handle_noti_notify,
+ NULL,
+ NULL);
+
+ DBG("subscribe id : %d", id);
+ if (id == 0) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR("Failed to register dbus_interface");
+ /* LCOV_EXCL_STOP */
+ } else {
+ monitor_id = id;
+ ret = NOTIFICATION_ERROR_NONE;
+ }
+ }
+
+ return ret;
+}
+
+static GDBusMessage *__get_new_msg(GVariant *body, const char *cmd)
+{
+ GDBusMessage *msg = NULL;
+
+ msg = g_dbus_message_new_method_call(
+ PROVIDER_BUS_NAME,
+ PROVIDER_OBJECT_PATH,
+ PROVIDER_NOTI_INTERFACE_NAME,
+ cmd);
+ if (!msg) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc new method call");
+ if (body)
+ g_variant_unref(body);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (body != NULL)
+ g_dbus_message_set_body(msg, body);
+
+ return msg;
+}
+
+static int __send_message(GDBusMessage *msg, GDBusMessage **reply, const char *cmd)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ GError *g_err = NULL;
+
+ *reply = g_dbus_connection_send_message_with_reply_sync(
+ _gdbus_conn,
+ msg,
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL,
+ &g_err);
+
+ if (!*reply) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_SERVICE_NOT_READY;
+ if (g_err != NULL) {
+ ERR("No reply. cmd[%s] err[%s]", cmd, g_err->message);
+ if (g_err->code == G_DBUS_ERROR_ACCESS_DENIED)
+ ret = NOTIFICATION_ERROR_PERMISSION_DENIED;
+ g_error_free(g_err);
+ }
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (g_dbus_message_to_gerror(*reply, &g_err)) {
+ if (g_err->code == G_DBUS_ERROR_ACCESS_DENIED)
+ ret = NOTIFICATION_ERROR_PERMISSION_DENIED;
+ else
+ ret = g_err->code;
+ g_error_free(g_err);
+ return ret;
+ }
+
+ INFO("Success to send message[%s]", cmd);
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static int _send_sync_noti_with_fd(int fd, GVariant *body, GDBusMessage **reply, char *cmd)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ GDBusMessage *msg = NULL;
+ GUnixFDList *fd_list = NULL;
+ GError *g_err = NULL;
+
+ fd_list = g_unix_fd_list_new();
+ g_unix_fd_list_append(fd_list, fd, &g_err);
+ if (g_err != NULL) {
+ /* LCOV_EXCL_START */
+ ERR("g_unix_fd_list_append [%s]", g_err->message);
+ g_object_unref(fd_list);
+ g_error_free(g_err);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ /* LCOV_EXCL_STOP */
+ }
+
+ msg = __get_new_msg(body, cmd);
+ if (msg == NULL) {
+ g_object_unref(fd_list);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+
+ g_dbus_message_set_unix_fd_list(msg, fd_list);
+
+ ret = __send_message(msg, reply, cmd);
+
+ g_object_unref(msg);
+ g_object_unref(fd_list);
+
+ INFO("Done - send sync message with fd list [%d]", ret);
+ return ret;
+}
+
+static int _send_sync_noti(GVariant *body, GDBusMessage **reply, char *cmd)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ GDBusMessage *msg = NULL;
+
+ msg = __get_new_msg(body, cmd);
+ if (msg == NULL)
+ return NOTIFICATION_ERROR_IO_ERROR;
+
+ ret = __send_message(msg, reply, cmd);
+
+ if (msg)
+ g_object_unref(msg);
+
+ INFO("Done - send sync message [%d]", ret);
+ return ret;
+}
+
+static void _send_message_with_reply_async_cb(GDBusConnection *connection,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GVariant *body;
+ int result = NOTIFICATION_ERROR_NONE;
+ int priv_id;
+ GDBusMessage *reply = NULL;
+ GError *err = NULL;
+ result_cb_item *cb_item = (result_cb_item *)user_data;
+
+ if (cb_item == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get a callback item");
+ return;
+ /* LCOV_EXCL_START */
+ }
+
+ reply = g_dbus_connection_send_message_with_reply_finish(
+ connection,
+ res,
+ &err);
+
+ if (!reply) {
+ /* LCOV_EXCL_START */
+ if (err != NULL) {
+ ERR("No reply[%s]", err->message);
+ g_error_free(err);
+ }
+ result = NOTIFICATION_ERROR_SERVICE_NOT_READY;
+ /* LCOV_EXCL_STOP */
+
+ } else if (g_dbus_message_to_gerror(reply, &err)) {
+ /* LCOV_EXCL_START */
+ if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
+ result = NOTIFICATION_ERROR_PERMISSION_DENIED;
+ else
+ result = err->code;
+
+ ERR("Failed to send message[%s]", err->message);
+ g_error_free(err);
+ /* LCOV_EXCL_STOP */
+ }
+
+ INFO("Async message callback result[%d]", result);
+ if (result == NOTIFICATION_ERROR_NONE) {
+ body = g_dbus_message_get_body(reply);
+ g_variant_get(body, "(i)", &priv_id);
+
+ if (cb_item->result_cb)
+ cb_item->result_cb(priv_id, result, cb_item->data);
+ } else {
+ if (cb_item->result_cb)
+ cb_item->result_cb(NOTIFICATION_PRIV_ID_NONE, result, cb_item->data);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+ free(cb_item);
+}
+
+static int _send_async_noti(GVariant *body, result_cb_item *cb_item, char *cmd)
+{
+ GDBusMessage *msg;
+
+ msg = g_dbus_message_new_method_call(
+ PROVIDER_BUS_NAME,
+ PROVIDER_OBJECT_PATH,
+ PROVIDER_NOTI_INTERFACE_NAME,
+ cmd);
+ if (!msg) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc new method call");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (g_variant_is_floating(body))
+ g_variant_ref(body);
+
+ if (body != NULL)
+ g_dbus_message_set_body(msg, body);
+
+ g_dbus_connection_send_message_with_reply(
+ _gdbus_conn,
+ msg,
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL,
+ (GAsyncReadyCallback)_send_message_with_reply_async_cb,
+ cb_item);
+
+ if (msg)
+ g_object_unref(msg);
+
+ DBG("Success to send async message");
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_ipc_request_insert(notification_h noti, int *priv_id)
+{
+ int result;
+ int id = NOTIFICATION_PRIV_ID_NONE;
+ bool event_flag;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ result = notification_get_event_flag(noti, &event_flag);
+ if (result != NOTIFICATION_ERROR_NONE)
+ return result;
+
+ if (event_flag == true && event_monitor_id == 0) {
+ result = _dbus_event_handler_signal_init();
+ if (result != NOTIFICATION_ERROR_NONE)
+ return result;
+ }
+
+ /* Initialize private ID */
+ noti->group_id = NOTIFICATION_GROUP_ID_NONE;
+ noti->internal_group_id = NOTIFICATION_GROUP_ID_NONE;
+
+ _print_noti(noti);
+ body = notification_ipc_make_gvariant_from_noti(noti, false);
+ if (body == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to make gvariant from notification handle");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ result = _send_sync_noti(body, &reply, "add_noti");
+ DBG("_send_sync_noti %d", result);
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &id);
+
+ if (priv_id != NULL)
+ *priv_id = id;
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("priv_id[%d] result[%d]", id, result);
+ return result;
+}
+
+int notification_ipc_request_update(notification_h noti)
+{
+ int result;
+ int priv_id = NOTIFICATION_PRIV_ID_NONE;
+
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = notification_ipc_make_gvariant_from_noti(noti, false);
+ if (body == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("cannot make gvariant");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ result = _send_sync_noti(body, &reply, "update_noti");
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &priv_id);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("priv_id[%d] result[%d]", priv_id, result);
+ return result;
+}
+
+int notification_ipc_request_update_async(notification_h noti,
+ void (*result_cb)(int priv_id, int result, void *data), void *user_data)
+{
+ int result;
+ result_cb_item *cb_item;
+ GVariant *body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ cb_item = calloc(1, sizeof(result_cb_item));
+ if (cb_item == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+
+ cb_item->result_cb = result_cb;
+ cb_item->data = user_data;
+
+ body = notification_ipc_make_gvariant_from_noti(noti, false);
+ if (body == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to make gvariant from notification handle");
+ free(cb_item);
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ result = _send_async_noti(body, cb_item, "update_noti");
+ DBG("Update async result[%d]", result);
+
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ free(cb_item);
+ cb_item = NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ g_variant_unref(body);
+
+ return result;
+}
+
+int notification_ipc_request_refresh(uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(i)", uid);
+ result = _send_sync_noti(body, &reply, "refresh_noti");
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_delete_single(notification_type_e type, char *app_id, int priv_id, uid_t uid)
+{
+ int result;
+ int id;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(sii)", app_id, priv_id, uid);
+ result = _send_sync_noti(body, &reply, "del_noti_single");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &id);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_delete_multiple(notification_type_e type, char *app_id, uid_t uid)
+{
+ int result;
+ int num_deleted;
+ GVariant *body;
+ GVariant *reply_body;
+ GDBusMessage *reply = NULL;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (!app_id)
+ app_id = "";
+
+ body = g_variant_new("(sii)", app_id, type, uid);
+ result = _send_sync_noti(body, &reply, "del_noti_multiple");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &num_deleted);
+ DBG("Deleted count[%d]", num_deleted);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_delete_by_display_applist(int display_applist, uid_t uid)
+{
+ int result;
+ int num_deleted;
+ GVariant *body;
+ GVariant *reply_body;
+ GDBusMessage *reply = NULL;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ }
+
+ body = g_variant_new("(ii)", display_applist, uid);
+
+ result = _send_sync_noti(body, &reply, "del_noti_by_display_applist");
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &num_deleted);
+ DBG("Deleted count[%d]", num_deleted);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_load_noti_by_tag(notification_h noti, const char *app_id, const char *tag, uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ GVariant *noti_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(ssi)", app_id, tag, uid);
+ result = _send_sync_noti(body, &reply, "load_noti_by_tag");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(v)", &noti_body);
+
+ notification_ipc_make_noti_from_gvariant(noti, noti_body);
+ g_variant_unref(noti_body);
+ _print_noti(noti);
+
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("tag[%s] result[%d]", tag, result);
+ return result;
+}
+
+/* LCOV_EXCL_START */
+int notification_ipc_request_load_noti_by_priv_id(notification_h noti, const char *app_id, int priv_id, uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ GVariant *noti_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ }
+
+ if (!app_id)
+ app_id = "";
+
+ body = g_variant_new("(sii)", app_id, priv_id, uid);
+ result = _send_sync_noti(body, &reply, "load_noti_by_priv_id");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(v)", &noti_body);
+
+ notification_ipc_make_noti_from_gvariant(noti, noti_body);
+ g_variant_unref(noti_body);
+ _print_noti(noti);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("priv id[%d], result[%d]", priv_id, result);
+ return result;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+int notification_ipc_request_get_count(notification_type_e type,
+ const char *app_id, int group_id, int priv_id, int *count, uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ int re_count;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ }
+
+ body = g_variant_new("(isiii)", type, app_id, group_id, priv_id, uid);
+ result = _send_sync_noti(body, &reply, "get_noti_count");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &re_count);
+
+ *count = re_count;
+ DBG("notification count[%d]", re_count);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("Count notification result[%d]", result);
+ return result;
+}
+/* LCOV_EXCL_STOP */
+
+static int __receive_list_from_socket(int fd, notification_list_h *list, int list_count)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *data = NULL;
+ unsigned int data_size = 0;
+ unsigned int buf_size = 0;
+ notification_h noti;
+ GVariant *noti_body;
+ GVariant *reply_body;
+
+ ret = notification_ipc_socket_get_read_buf_size(fd, &buf_size);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("get read buf size");
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+
+ data = (char *)calloc(buf_size, sizeof(char));
+ if (data == NULL) {
+ ERR("OOM - socket buffer");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ while (list_count > 0) {
+ ret = notification_ipc_socket_read(fd, (char *)&data_size, sizeof(data_size));
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("socket read buf [%d]", ret);
+ goto out;
+ }
+
+ if (data_size > buf_size) {
+ buf_size = data_size;
+ if (data)
+ free(data);
+ data = (char *)calloc(data_size, sizeof(char));
+ if (data == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ ERR("OOM - socket bulk buffer");
+ goto out;
+ }
+ }
+
+ ret = notification_ipc_socket_read(fd, data, data_size);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("socket read buf [%d]", ret);
+ goto out;
+ }
+
+ noti = (notification_h)calloc(1, sizeof(struct _notification));
+ if (noti == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ ERR("OOM - notification handle");
+ goto out;
+ }
+
+ reply_body = g_variant_new_from_data(G_VARIANT_TYPE("(v)"),
+ data, data_size, TRUE, NULL, NULL);
+ g_variant_get(reply_body, "(v)", &noti_body);
+ notification_ipc_make_noti_from_gvariant(noti, noti_body);
+ *list = notification_list_append(*list, noti);
+ g_variant_unref(noti_body);
+ g_variant_unref(reply_body);
+ list_count--;
+ }
+
+out:
+ if (ret != NOTIFICATION_ERROR_NONE)
+ notification_free_list(*list);
+ if (data)
+ free(data);
+
+ return ret;
+}
+
+int notification_ipc_request_load_noti_grouping_list(notification_type_e type,
+ int count, int count_per_page, notification_list_h *list, uid_t uid)
+{
+#define RCV_SOCK 0
+#define SND_SOCK 1
+ int result;
+ int sockfd[2] = { 0, };
+ int list_count;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ result = notification_ipc_socket_pair(sockfd);
+ if (result != NOTIFICATION_ERROR_NONE)
+ return result;
+ INFO("socket receive[%d] send[%d]", sockfd[RCV_SOCK], sockfd[SND_SOCK]);
+
+ body = g_variant_new("(iiii)", type, count, count_per_page, uid);
+ result = _send_sync_noti_with_fd(sockfd[SND_SOCK], body, &reply, "load_noti_grouping_list");
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &list_count);
+ result = __receive_list_from_socket(sockfd[RCV_SOCK], list, list_count);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+ if (sockfd[RCV_SOCK])
+ close(sockfd[RCV_SOCK]);
+ if (sockfd[SND_SOCK])
+ close(sockfd[SND_SOCK]);
+
+ INFO("result [%d]", result);
+ return result;
+}
+
+int notification_ipc_request_load_noti_detail_list(const char *app_id,
+ int group_id,
+ int priv_id,
+ int count,
+ notification_list_h *list,
+ uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ GVariant *iter_body;
+ GVariantIter *iter;
+ notification_h noti;
+ GVariant *noti_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ }
+
+ body = g_variant_new("(siiii)", app_id, group_id, priv_id, count, uid);
+ result = _send_sync_noti(body, &reply, "load_noti_detail_list");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(a(v))", &iter);
+
+ while (g_variant_iter_loop(iter, "(v)", &iter_body)) {
+ noti = notification_create(NOTIFICATION_TYPE_NOTI);
+ if (!noti) {
+ result = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ ERR("failed to create a notification");
+ notification_free_list(*list);
+ break;
+ }
+ g_variant_get(iter_body, "(v)", &noti_body);
+ notification_ipc_make_noti_from_gvariant(noti, noti_body);
+ *list = notification_list_append(*list, noti);
+ g_variant_unref(noti_body);
+ }
+ g_variant_iter_free(iter);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_get_setting_array(
+ notification_setting_h *setting_array,
+ int *count,
+ uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *reply_body;
+ GVariant *iter_body;
+ GVariantIter *iter;
+ int setting_cnt;
+ notification_setting_h result_setting_array;
+ notification_setting_h temp;
+ int setting_idx;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ result = _send_sync_noti(g_variant_new("(i)", uid), &reply, "get_setting_array");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(ia(v))", &setting_cnt, &iter);
+
+ DBG("get setting arr cnt: %d", setting_cnt);
+ result_setting_array = (struct notification_setting *)malloc(sizeof(struct notification_setting) * setting_cnt);
+ if (result_setting_array == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("malloc failed");
+ g_object_unref(reply);
+ g_variant_iter_free(iter);
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ setting_idx = 0;
+ while (g_variant_iter_loop(iter, "(v)", &iter_body)) {
+ temp = result_setting_array + setting_idx;
+ notification_ipc_make_setting_from_gvariant(temp, iter_body);
+ setting_idx++;
+ }
+
+ *count = setting_cnt;
+ *setting_array = result_setting_array;
+ g_variant_iter_free(iter);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_get_setting_by_app_id(
+ const char *app_id, notification_setting_h *setting, uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ GVariant *setting_body;
+ notification_setting_h result_setting;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ }
+
+ body = g_variant_new("(si)", app_id, uid);
+ result = _send_sync_noti(body, &reply, "get_setting_by_app_id");
+
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(v)", &setting_body);
+
+ result_setting = (struct notification_setting *)malloc(sizeof(struct notification_setting));
+ if (result_setting == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("malloc failed");
+ g_object_unref(reply);
+ g_variant_unref(body);
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+ notification_ipc_make_setting_from_gvariant(result_setting, setting_body);
+
+ *setting = result_setting;
+ g_variant_unref(setting_body);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_load_system_setting(notification_system_setting_h *setting, uid_t uid)
+{
+ int result;
+ int count;
+ GDBusMessage *reply = NULL;
+ GVariant *setting_body = NULL;
+ GVariant *reply_body = NULL;
+ GVariant *iter_body = NULL;
+ GVariantIter *iter = NULL;
+ notification_system_setting_h result_setting = NULL;
+ dnd_allow_exception_h dnd_allow_exception;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ result = _send_sync_noti(g_variant_new("(i)", uid), &reply, "load_system_setting");
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(v)", &setting_body);
+
+ result_setting = (struct notification_system_setting *)calloc(1, sizeof(struct notification_system_setting));
+ if (result_setting == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("malloc failed");
+ result = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ notification_ipc_make_system_setting_from_gvariant(result_setting, setting_body);
+
+ result = _send_sync_noti(g_variant_new("(i)", uid), &reply, "load_dnd_allow_exception");
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(ia(v))", &count, &iter);
+
+ while (g_variant_iter_loop(iter, "(v)", &iter_body)) {
+ dnd_allow_exception = (dnd_allow_exception_h)calloc(1, sizeof(struct notification_system_setting_dnd_allow_exception));
+ if (dnd_allow_exception == NULL) {
+ /* LCOV_EXCL_START */
+ result = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ notification_ipc_make_dnd_allow_exception_from_gvariant(dnd_allow_exception, iter_body);
+ result_setting->dnd_allow_exceptions = g_list_append(result_setting->dnd_allow_exceptions, dnd_allow_exception);
+ }
+ *setting = result_setting;
+ }
+ }
+
+out:
+ if (result != NOTIFICATION_ERROR_NONE && result_setting)
+ notification_system_setting_free_system_setting(result_setting);
+ if (iter)
+ g_variant_iter_free(iter);
+ if (setting_body)
+ g_variant_unref(setting_body);
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_update_setting(notification_setting_h setting, uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(ssiiiiii)",
+ setting->package_name,
+ setting->app_id,
+ (int)(setting->allow_to_notify),
+ (int)(setting->do_not_disturb_except),
+ (int)(setting->visibility_class),
+ (int)(setting->pop_up_notification),
+ (int)(setting->lock_screen_content_level),
+ uid);
+
+ result = _send_sync_noti(body, &reply, "update_noti_setting");
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_update_system_setting(notification_system_setting_h system_setting, uid_t uid)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GList *list;
+ dnd_allow_exception_h dnd_allow_exception;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(iiiiiiiiii)",
+ (int)(system_setting->do_not_disturb),
+ (int)(system_setting->visibility_class),
+ (int)(system_setting->dnd_schedule_enabled),
+ (int)(system_setting->dnd_schedule_day),
+ (int)(system_setting->dnd_start_hour),
+ (int)(system_setting->dnd_start_min),
+ (int)(system_setting->dnd_end_hour),
+ (int)(system_setting->dnd_end_min),
+ (int)(system_setting->lock_screen_content_level),
+ uid);
+
+ result = _send_sync_noti(body, &reply, "update_noti_sys_setting");
+
+ /* update dnd_allow_exceptions */
+ list = g_list_first(system_setting->dnd_allow_exceptions);
+
+ for (; list != NULL; list = list->next) {
+ dnd_allow_exception = list->data;
+
+ body = g_variant_new("(iii)",
+ (int)(dnd_allow_exception->type),
+ (int)(dnd_allow_exception->value),
+ uid);
+ result = _send_sync_noti(body, &reply, "update_dnd_allow_exception");
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_save_as_template(notification_h noti, const char *template_name)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = notification_ipc_make_gvariant_from_noti(noti, false);
+ if (body == NULL) {
+ ERR("Failed to make gvariant from notification handle");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ result = _send_sync_noti(g_variant_new("(vs)", body, template_name), &reply, "save_as_template");
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+ return result;
+}
+
+int notification_ipc_request_create_from_template(notification_h noti, const char *template_name)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ GVariant *noti_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(s)", template_name);
+
+ result = _send_sync_noti(body, &reply, "create_from_template");
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(v)", &noti_body);
+
+ notification_ipc_make_noti_from_gvariant(noti, noti_body);
+ g_variant_unref(noti_body);
+ _print_noti(noti);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+
+ return result;
+}
+
+int notification_ipc_request_create_from_package_template(notification_h noti, const char *app_id, const char *template_name)
+{
+ int result;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ GVariant *noti_body;
+
+ result = _dbus_init();
+ if (result != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", result);
+ return result;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(ss)", app_id, template_name);
+
+ result = _send_sync_noti(body, &reply, "create_from_package_template");
+ if (result == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(v)", &noti_body);
+
+ notification_ipc_make_noti_from_gvariant(noti, noti_body);
+ g_variant_unref(noti_body);
+ _print_noti(noti);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", result);
+
+ return result;
+}
+
+int notification_ipc_get_noti_block_state(const char *app_id, int *do_not_disturb,
+ int *do_not_disturb_except, int *allow_to_notify,
+ uid_t uid)
+{
+ int ret;
+ int dnd;
+ int dnd_except;
+ int allow;
+ GDBusMessage *reply = NULL;
+ GVariant *body;
+ GVariant *reply_body;
+ GVariant *result_body;
+
+ if (app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = _dbus_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ body = g_variant_new("(si)", app_id, uid);
+
+ ret = _send_sync_noti(body, &reply, "get_noti_block_state");
+
+ if (ret == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(v)", &result_body);
+ g_variant_get(result_body, "(iii)", &dnd, &dnd_except, &allow);
+ *do_not_disturb = dnd;
+ *do_not_disturb_except = dnd_except;
+ *allow_to_notify = allow;
+ g_variant_unref(result_body);
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", ret);
+
+ return ret;
+}
+
+int notification_ipc_request_get_all_count(notification_type_e type, int *count, uid_t uid)
+{
+ int ret;
+ int ret_count = -1;
+ GDBusMessage *reply = NULL;
+ GVariant *reply_body = NULL;
+
+ ret = _dbus_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", ret);
+ return ret;
+ }
+
+ ret = _send_sync_noti(g_variant_new("(ii)", type, uid),
+ &reply, "get_noti_all_count");
+ if (ret == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &ret_count);
+ *count = ret_count;
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ return ret;
+}
+
+int notification_ipc_send_event(notification_h noti, int event_type, int priv_id)
+{
+ int ret;
+ GVariant *body = NULL;
+ GDBusMessage *reply = NULL;
+
+ ret = _dbus_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (priv_id > 0) {
+ ret = _send_sync_noti(g_variant_new("(ii)", priv_id, event_type), &reply, "send_noti_event_by_priv_id");
+ } else {
+ body = notification_ipc_make_gvariant_from_noti(noti, false);
+ if (body == NULL) {
+ ERR("Can't make gvariant to noti");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = _send_sync_noti(g_variant_new("(vi)", body, event_type), &reply, "send_noti_event");
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", ret);
+
+ return ret;
+}
+
+int notification_ipc_check_event_receiver(int priv_id, bool *available)
+{
+ int ret;
+ int ret_available;
+ GVariant *reply_body = NULL;
+ GDBusMessage *reply = NULL;
+
+ ret = _dbus_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _send_sync_noti(g_variant_new("(i)", priv_id), &reply, "check_event_receiver");
+ if (ret == NOTIFICATION_ERROR_NONE) {
+ reply_body = g_dbus_message_get_body(reply);
+ g_variant_get(reply_body, "(i)", &ret_available);
+ *available = (bool)ret_available;
+ }
+
+ if (reply)
+ g_object_unref(reply);
+
+ DBG("result[%d]", ret);
+ return ret;
+}
+
+/* LCOV_EXCL_START */
+void notification_ipc_reset_event_handler(int priv_id)
+{
+ int ret;
+ GDBusMessage *reply = NULL;
+
+ ret = _dbus_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to init dbus connection[%d]", ret);
+ return;
+ }
+
+ _send_sync_noti(g_variant_new("(i)", priv_id), &reply, "reset_event_handler");
+
+ if (reply)
+ g_object_unref(reply);
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API GVariant *notification_ipc_make_gvariant_from_noti(notification_h noti, bool translate)
+{
+ DBG("make gvariant from noti");
+ int i = 0;
+ int b_encode_len = 0;
+ bundle_raw *args = NULL;
+ bundle_raw *group_args = NULL;
+ bundle_raw *b_image_path = NULL;
+ bundle_raw *b_priv_image_path = NULL;
+ bundle_raw *b_execute_option = NULL;
+ bundle_raw *b_service_responding = NULL;
+ bundle_raw *b_service_single_launch = NULL;
+ bundle_raw *b_service_multi_launch = NULL;
+ bundle_raw *b_event_handler[NOTIFICATION_EVENT_TYPE_MAX+1] = {NULL, };
+ bundle_raw *b_text = NULL;
+ bundle_raw *b_key = NULL;
+ bundle_raw *b_format_args = NULL;
+ GVariant *body = NULL;
+ GVariant *result_body = NULL;
+ GVariantBuilder builder;
+
+ if (translate)
+ notification_translate_localized_text(noti);
+
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("a{iv}"));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_NOTI_TYPE, g_variant_new_int32(noti->type));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LAYOUT, g_variant_new_int32(noti->layout));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_GROUP_ID, g_variant_new_int32(noti->group_id));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_INTERNAL_GROUP_ID, g_variant_new_int32(noti->internal_group_id));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PRIV_ID, g_variant_new_int32(noti->priv_id));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PKG_ID, g_variant_new_string((const gchar *)noti->pkg_id));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_CALLER_APP_ID, g_variant_new_string((const gchar *)noti->caller_app_id));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_DISPLAY_APPLIST, g_variant_new_int32(noti->display_applist));
+
+ if (noti->args) {
+ bundle_encode(noti->args, (bundle_raw **)&args, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_ARGS, g_variant_new_string((const gchar *)args));
+
+ if (args)
+ bundle_free_encoded_rawdata(&args);
+ }
+
+ if (noti->group_args) {
+ bundle_encode(noti->group_args, (bundle_raw **)&group_args,
+ &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_GROUP_ARGS, g_variant_new_string((const gchar *)group_args));
+
+ if (group_args)
+ bundle_free_encoded_rawdata(&group_args);
+ }
+
+ if (noti->b_execute_option) {
+ bundle_encode(noti->b_execute_option,
+ (bundle_raw **)&b_execute_option, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_EXECUTE_OPTION, g_variant_new_string((const gchar *)b_execute_option));
+
+ if (b_execute_option)
+ bundle_free_encoded_rawdata(&b_execute_option);
+ }
+
+ if (noti->b_service_responding) {
+ bundle_encode(noti->b_service_responding,
+ (bundle_raw **)&b_service_responding, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SERVICE_RESPONDING, g_variant_new_string((const gchar *)b_service_responding));
+
+ if (b_service_responding)
+ bundle_free_encoded_rawdata(&b_service_responding);
+ }
+
+ if (noti->b_service_single_launch) {
+ bundle_encode(noti->b_service_single_launch,
+ (bundle_raw **)&b_service_single_launch, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SERVICE_SINGLE_LAUNCH, g_variant_new_string((const gchar *)b_service_single_launch));
+
+ if (b_service_single_launch)
+ bundle_free_encoded_rawdata(&b_service_single_launch);
+ }
+
+ if (noti->b_service_multi_launch) {
+ bundle_encode(noti->b_service_multi_launch,
+ (bundle_raw **)&b_service_multi_launch, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SERVICE_MULTI_LAUNCH, g_variant_new_string((const gchar *)b_service_multi_launch));
+
+ if (b_service_multi_launch)
+ bundle_free_encoded_rawdata(&b_service_multi_launch);
+ }
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++) {
+ if (noti->b_event_handler[i]) {
+ bundle_encode(noti->b_event_handler[i],
+ (bundle_raw **)&b_event_handler[i], &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_BUTTON1_EVENT + i, g_variant_new_string((const gchar *)b_event_handler[i]));
+
+ if (b_event_handler[i])
+ bundle_free_encoded_rawdata(&b_event_handler[i]);
+ }
+ }
+
+ if (noti->launch_app_id)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LAUNCH_APP_ID, g_variant_new_string((const gchar *)noti->launch_app_id));
+
+ if (noti->domain != NULL)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_DOMAIN, g_variant_new_string((const gchar *)noti->domain));
+
+ if (noti->dir != NULL)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_DIR, g_variant_new_string((const gchar *)noti->dir));
+
+ if (noti->b_text) {
+ bundle_encode(noti->b_text, (bundle_raw **)&b_text, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TEXT, g_variant_new_string((const gchar *)b_text));
+
+ if (b_text)
+ bundle_free_encoded_rawdata(&b_text);
+ }
+
+ if (noti->b_key) {
+ bundle_encode(noti->b_key, (bundle_raw **)&b_key, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_KEY, g_variant_new_string((const gchar *)b_key));
+
+ if (b_key)
+ bundle_free_encoded_rawdata(&b_key);
+ }
+
+ if (noti->b_format_args) {
+ bundle_encode(noti->b_format_args,
+ (bundle_raw **)&b_format_args, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_FORMAT_ARGS, g_variant_new_string((const gchar *)b_format_args));
+
+ if (b_format_args)
+ bundle_free_encoded_rawdata(&b_format_args);
+ }
+
+ if (noti->num_format_args != 0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_NUM_FORMAT_ARGS, g_variant_new_int32(noti->num_format_args));
+
+ if (noti->b_image_path) {
+ bundle_encode(noti->b_image_path,
+ (bundle_raw **)&b_image_path, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_IMAGE_PATH, g_variant_new_string((const gchar *)b_image_path));
+
+ if (b_image_path)
+ bundle_free_encoded_rawdata(&b_image_path);
+ }
+
+ if (noti->b_priv_image_path) {
+ bundle_encode(noti->b_priv_image_path,
+ (bundle_raw **)&b_priv_image_path, &b_encode_len);
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PRIV_IMAGE_PATH, g_variant_new_string((const gchar *)b_priv_image_path));
+
+ if (b_priv_image_path)
+ bundle_free_encoded_rawdata(&b_priv_image_path);
+ }
+
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SOUND_TYPE, g_variant_new_int32(noti->sound_type));
+
+ if (noti->sound_path)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_SOUND_PATH, g_variant_new_string((const gchar *)noti->sound_path));
+
+ if (noti->priv_sound_path)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PRIV_SOUND_PATH, g_variant_new_string((const gchar *)noti->priv_sound_path));
+
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_VIBRATION_TYPE, g_variant_new_int32(noti->vibration_type));
+
+ if (noti->vibration_path)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_VIBRATION_PATH, g_variant_new_string((const gchar *)noti->vibration_path));
+
+ if (noti->priv_vibration_path)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PRIV_VIBRATION_PATH, g_variant_new_string((const gchar *)noti->priv_vibration_path));
+
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LED_OPERATION, g_variant_new_int32(noti->led_operation));
+
+ if (noti->led_argb != 0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LED_ARGB, g_variant_new_int32(noti->led_argb));
+
+ if (noti->led_on_ms != 0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LED_ON_MS, g_variant_new_int32(noti->led_on_ms));
+
+ if (noti->led_off_ms != 0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_LED_OFF_MS, g_variant_new_int32(noti->led_off_ms));
+
+ if (noti->time != 0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TIME, g_variant_new_int32(noti->time));
+
+ if (noti->insert_time != 0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_INSERT_TIME, g_variant_new_int32(noti->insert_time));
+
+ if (noti->flags_for_property != 0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_FLAGS_FOR_PROPERTY, g_variant_new_int32(noti->flags_for_property));
+
+ if (noti->progress_size != 0.0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PROGRESS_SIZE, g_variant_new_double(noti->progress_size));
+
+ if (noti->progress_percentage != 0.0)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_PROGRESS_PERCENTAGE, g_variant_new_double(noti->progress_percentage));
+
+ if (noti->app_icon_path != NULL)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_APP_ICON_PATH, g_variant_new_string((const gchar *)noti->app_icon_path));
+ if (noti->app_label != NULL)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_APP_LABEL, g_variant_new_string((const gchar *)noti->app_label));
+ if (noti->temp_title != NULL)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TEMP_TITLE, g_variant_new_string((const gchar *)noti->temp_title));
+ if (noti->temp_content != NULL)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TEMP_CONTENT, g_variant_new_string((const gchar *)noti->temp_content));
+ if (noti->tag != NULL)
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TAG, g_variant_new_string((const gchar *)noti->tag));
+
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_ONGOING_FLAG, g_variant_new_int32(noti->ongoing_flag));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_ONGOING_VALUE_TYPE, g_variant_new_int32(noti->ongoing_value_type));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_ONGOING_CURRENT, g_variant_new_int32(noti->ongoing_current));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_ONGOING_DURATION, g_variant_new_int32(noti->ongoing_duration));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_AUTO_REMOVE, g_variant_new_int32(noti->auto_remove));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_DEFAULT_BUTTON, g_variant_new_int32(noti->default_button_index));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_HIDE_TIMEOUT, g_variant_new_int32(noti->hide_timeout));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_DELETE_TIMEOUT, g_variant_new_int32(noti->delete_timeout));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TEXT_INPUT_MAX_LENGTH, g_variant_new_int32(noti->text_input_max_length));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_EVENT_FLAG, g_variant_new_int32(noti->event_flag));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_TRANSLATION, g_variant_new_int32(noti->is_translation));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_EXTENSION_IMAGE_SIZE, g_variant_new_int32(noti->extension_image_size));
+ g_variant_builder_add(&builder, "{iv}", NOTIFICATION_DATA_TYPE_UID, g_variant_new_int32(noti->uid));
+
+ result_body = g_variant_builder_end(&builder);
+ body = g_variant_new("(v)", result_body);
+
+ return body;
+}
+
+static gboolean _variant_to_int_dict(GHashTable **dict, GVariant *variant)
+{
+ GVariantIter iter;
+ int key;
+ int *hash_key;
+ GVariant *value;
+
+ *dict = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, (GDestroyNotify)g_variant_unref);
+ if (*dict == NULL)
+ return FALSE;
+
+ g_variant_iter_init(&iter, variant);
+ while (g_variant_iter_next(&iter, "{iv}", &key, &value)) {
+ hash_key = (int *)calloc(sizeof(int), 1);
+ if (hash_key == NULL) {
+ /* LCOV_EXCL_START */
+ g_hash_table_unref(*dict);
+ return FALSE;
+ /* LCOV_EXCL_STOP */
+ }
+ *hash_key = key;
+ g_hash_table_insert(*dict, (gpointer)hash_key, value);
+ }
+ return TRUE;
+}
+
+static gboolean _variant_dict_lookup(GHashTable *dict,
+ int key,
+ const gchar *format_string,
+ ...)
+{
+ GVariant *value;
+ va_list ap;
+
+ value = g_hash_table_lookup(dict, (gpointer)&key);
+
+ if (value == NULL || !g_variant_check_format_string(value, format_string, FALSE))
+ return FALSE;
+
+ va_start(ap, format_string);
+ g_variant_get_va(value, format_string, NULL, &ap);
+ va_end(ap);
+
+ return TRUE;
+}
+
+/*!
+ * functions creating notification packet
+ */
+EXPORT_API int notification_ipc_make_noti_from_gvariant(notification_h noti,
+ GVariant *variant) {
+
+ DBG("make noti from GVariant");
+ GHashTable *dict;
+
+ int i;
+ char *pkg_id = NULL;
+ char *caller_app_id = NULL;
+ char *launch_app_id = NULL;
+ bundle_raw *args = NULL;
+ bundle_raw *group_args = NULL;
+ bundle_raw *b_execute_option = NULL;
+ bundle_raw *b_service_responding = NULL;
+ bundle_raw *b_service_single_launch = NULL;
+ bundle_raw *b_service_multi_launch = NULL;
+ bundle_raw *b_event_handler[NOTIFICATION_EVENT_TYPE_MAX+1] = { NULL, };
+ char *domain = NULL;
+ char *dir = NULL;
+ bundle_raw *b_text = NULL;
+ bundle_raw *b_key = NULL;
+ bundle_raw *b_format_args = NULL;
+ bundle_raw *b_image_path = NULL;
+ bundle_raw *b_priv_image_path = NULL;
+ char *sound_path = NULL;
+ char *priv_sound_path = NULL;
+ char *vibration_path = NULL;
+ char *priv_vibration_path = NULL;
+ char *app_icon_path = NULL;
+ char *app_label = NULL;
+ char *temp_title = NULL;
+ char *temp_content = NULL;
+ char *tag = NULL;
+
+ if (noti == NULL) {
+ ERR("Invalid noti NULL");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (variant == NULL) {
+ ERR("Invalid variant NULL");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!_variant_to_int_dict(&dict, variant))
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_NOTI_TYPE, "i", &noti->type);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LAYOUT, "i", &noti->layout);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_GROUP_ID, "i", &noti->group_id);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_INTERNAL_GROUP_ID, "i", &noti->internal_group_id);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PRIV_ID, "i", &noti->priv_id);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PKG_ID, "&s", &pkg_id);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_CALLER_APP_ID, "&s", &caller_app_id);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LAUNCH_APP_ID, "&s", &launch_app_id);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ARGS, "&s", &args);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_GROUP_ARGS, "&s", &group_args);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_EXECUTE_OPTION, "&s", &b_execute_option);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SERVICE_RESPONDING, "&s", &b_service_responding);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SERVICE_SINGLE_LAUNCH, "&s", &b_service_single_launch);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SERVICE_MULTI_LAUNCH, "&s", &b_service_multi_launch);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON1_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON2_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_2]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON3_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_3]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON4_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_4]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON5_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_5]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON6_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_6]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ICON_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_ICON]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_THUMBNAIL_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_THUMBNAIL]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TEXT_INPUT_BUTTON_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON7_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_7]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON8_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_8]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON9_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_9]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_BUTTON10_EVENT, "&s", &b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_10]);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DOMAIN, "&s", &domain);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DIR, "&s", &dir);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TEXT, "&s", &b_text);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_KEY, "&s", &b_key);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_FORMAT_ARGS, "&s", &b_format_args);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_NUM_FORMAT_ARGS, "i", &noti->num_format_args);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_IMAGE_PATH, "&s", &b_image_path);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PRIV_IMAGE_PATH, "&s", &b_priv_image_path);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SOUND_TYPE, "i", &noti->sound_type);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_SOUND_PATH, "&s", &sound_path);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PRIV_SOUND_PATH, "&s", &priv_sound_path);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_VIBRATION_TYPE, "i", &noti->vibration_type);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_VIBRATION_PATH, "&s", &vibration_path);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PRIV_VIBRATION_PATH, "&s", &priv_vibration_path);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_OPERATION, "i", &noti->led_operation);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_ARGB, "i", &noti->led_argb);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_ON_MS, "i", &noti->led_on_ms);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_LED_OFF_MS, "i", &noti->led_off_ms);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TIME, "i", &noti->time);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_INSERT_TIME, "i", &noti->insert_time);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_FLAGS_FOR_PROPERTY, "i", &noti->flags_for_property);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DISPLAY_APPLIST, "i", &noti->display_applist);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PROGRESS_SIZE, "d", &noti->progress_size);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_PROGRESS_PERCENTAGE, "d", &noti->progress_percentage);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_APP_ICON_PATH, "&s", &app_icon_path);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_APP_LABEL, "&s", &app_label);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TEMP_TITLE, "&s", &temp_title);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TEMP_CONTENT, "&s", &temp_content);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TAG, "&s", &tag);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ONGOING_FLAG, "i", &noti->ongoing_flag);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ONGOING_VALUE_TYPE, "i", &noti->ongoing_value_type);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ONGOING_CURRENT, "i", &noti->ongoing_current);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_ONGOING_DURATION, "i", &noti->ongoing_duration);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_AUTO_REMOVE, "i", &noti->auto_remove);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DEFAULT_BUTTON, "i", &noti->default_button_index);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_HIDE_TIMEOUT, "i", &noti->hide_timeout);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_DELETE_TIMEOUT, "i", &noti->delete_timeout);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TEXT_INPUT_MAX_LENGTH, "i", &noti->text_input_max_length);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_EVENT_FLAG, "i", &noti->event_flag);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_TRANSLATION, "i", &noti->is_translation);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_EXTENSION_IMAGE_SIZE, "i", &noti->extension_image_size);
+ _variant_dict_lookup(dict, NOTIFICATION_DATA_TYPE_UID, "i", &noti->uid);
+
+ if (noti->pkg_id)
+ free(noti->pkg_id);
+ noti->pkg_id = _dup_string(pkg_id);
+
+ if (noti->caller_app_id)
+ free(noti->caller_app_id);
+ noti->caller_app_id = _dup_string(caller_app_id);
+
+ noti->launch_app_id = _dup_string(launch_app_id);
+
+ noti->args = _create_bundle_from_bundle_raw(args);
+ noti->group_args = _create_bundle_from_bundle_raw(group_args);
+ noti->b_execute_option = _create_bundle_from_bundle_raw(b_execute_option);
+ noti->b_service_responding = _create_bundle_from_bundle_raw(
+ b_service_responding);
+ noti->b_service_single_launch = _create_bundle_from_bundle_raw(
+ b_service_single_launch);
+ noti->b_service_multi_launch = _create_bundle_from_bundle_raw(
+ b_service_multi_launch);
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++) {
+ noti->b_event_handler[i] = _create_bundle_from_bundle_raw(
+ b_event_handler[i]);
+ }
+
+ if (noti->domain)
+ free(noti->domain);
+ noti->domain = _dup_string(domain);
+
+ if (noti->dir)
+ free(noti->dir);
+ noti->dir = _dup_string(dir);
+
+ noti->b_text = _create_bundle_from_bundle_raw(b_text);
+ noti->b_key = _create_bundle_from_bundle_raw(b_key);
+ noti->b_format_args = _create_bundle_from_bundle_raw(b_format_args);
+ noti->b_image_path = _create_bundle_from_bundle_raw(b_image_path);
+ noti->b_priv_image_path = _create_bundle_from_bundle_raw(b_priv_image_path);
+ noti->sound_path = _dup_string(sound_path);
+ noti->priv_sound_path = _dup_string(priv_sound_path);
+ noti->vibration_path = _dup_string(vibration_path);
+ noti->priv_vibration_path = _dup_string(priv_vibration_path);
+ noti->app_icon_path = _dup_string(app_icon_path);
+ noti->app_label = _dup_string(app_label);
+ noti->temp_title = _dup_string(temp_title);
+ noti->temp_content = _dup_string(temp_content);
+ noti->tag = _dup_string(tag);
+
+ g_hash_table_unref(dict);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API GVariant *notification_ipc_make_gvariant_from_system_setting(struct notification_system_setting *noti_setting)
+{
+ GVariant *body = NULL;
+
+ body = g_variant_new("(iiiiiiiii)",
+ noti_setting->do_not_disturb,
+ noti_setting->visibility_class,
+ noti_setting->dnd_schedule_enabled,
+ noti_setting->dnd_schedule_day,
+ noti_setting->dnd_start_hour,
+ noti_setting->dnd_start_min,
+ noti_setting->dnd_end_hour,
+ noti_setting->dnd_end_min,
+ noti_setting->lock_screen_content_level);
+ return body;
+}
+
+EXPORT_API int notification_ipc_make_system_setting_from_gvariant(struct notification_system_setting *noti_setting,
+ GVariant *variant)
+{
+ int do_not_disturb;
+ int visibility_class;
+ int dnd_schedule_enabled;
+ int dnd_schedule_day;
+ int dnd_start_hour;
+ int dnd_start_min;
+ int dnd_end_hour;
+ int dnd_end_min;
+ int lock_screen_content_level;
+
+ if (noti_setting == NULL) {
+ ERR("Invalid setting handle");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ g_variant_get(variant,
+ "(iiiiiiiii)",
+ &do_not_disturb,
+ &visibility_class,
+ &dnd_schedule_enabled,
+ &dnd_schedule_day,
+ &dnd_start_hour,
+ &dnd_start_min,
+ &dnd_end_hour,
+ &dnd_end_min,
+ &lock_screen_content_level);
+
+ DBG("system setting %d, %d, %d, %d, [%d:%d] [%d:%d], %d",
+ do_not_disturb, visibility_class, dnd_schedule_enabled,
+ dnd_schedule_day, dnd_start_hour, dnd_start_min,
+ dnd_end_hour, dnd_end_min, lock_screen_content_level);
+
+ noti_setting->do_not_disturb = do_not_disturb;
+ noti_setting->visibility_class = visibility_class;
+ noti_setting->dnd_schedule_enabled = dnd_schedule_enabled;
+ noti_setting->dnd_schedule_day = dnd_schedule_day;
+ noti_setting->dnd_start_hour = dnd_start_hour;
+ noti_setting->dnd_start_min = dnd_start_min;
+ noti_setting->dnd_end_hour = dnd_end_hour;
+ noti_setting->dnd_end_min = dnd_end_min;
+ noti_setting->lock_screen_content_level = lock_screen_content_level;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API GVariant *notification_ipc_make_gvariant_from_setting(struct notification_setting *noti_setting)
+{
+ GVariant *body = NULL;
+
+ body = g_variant_new("(ssiiiiii)",
+ noti_setting->package_name,
+ noti_setting->app_id,
+ noti_setting->allow_to_notify,
+ noti_setting->do_not_disturb_except,
+ noti_setting->visibility_class,
+ noti_setting->pop_up_notification,
+ noti_setting->lock_screen_content_level,
+ noti_setting->app_disabled);
+
+ return body;
+}
+
+EXPORT_API int notification_ipc_make_setting_from_gvariant(struct notification_setting *noti_setting,
+ GVariant *variant)
+{
+ char *pkgname;
+ char *app_id;
+ int allow_to_notify;
+ int do_not_disturb_except;
+ int visibility_class;
+ int pop_up_notification;
+ int lock_screen_content_level;
+ int app_disabled;
+
+ if (noti_setting == NULL || variant == NULL) {
+ ERR("invalid data");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+ g_variant_get(variant,
+ "(&s&siiiiii)",
+ &pkgname,
+ &app_id,
+ &allow_to_notify,
+ &do_not_disturb_except,
+ &visibility_class,
+ &pop_up_notification,
+ &lock_screen_content_level,
+ &app_disabled);
+
+ DBG("setting from variant %s !!", pkgname);
+
+ noti_setting->package_name = _dup_string(pkgname);
+ noti_setting->app_id = _dup_string(app_id);
+ noti_setting->allow_to_notify = allow_to_notify;
+ noti_setting->do_not_disturb_except = do_not_disturb_except;
+ noti_setting->visibility_class = visibility_class;
+ noti_setting->pop_up_notification = pop_up_notification;
+ noti_setting->lock_screen_content_level = lock_screen_content_level;
+ noti_setting->app_disabled = app_disabled;
+
+ DBG("setting->pkgname[%s] pkgname[%s]",
+ noti_setting->package_name, pkgname);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API GVariant *notification_ipc_make_gvariant_from_dnd_allow_exception(struct notification_system_setting_dnd_allow_exception *dnd_allow_exception)
+{
+ GVariant *body = NULL;
+
+ body = g_variant_new("(ii)",
+ dnd_allow_exception->type,
+ dnd_allow_exception->value);
+
+ return body;
+}
+
+int notification_ipc_make_dnd_allow_exception_from_gvariant(struct notification_system_setting_dnd_allow_exception *dnd_allow_exception, GVariant *variant)
+{
+ int type;
+ int value;
+
+ if (dnd_allow_exception == NULL) {
+ ERR("Invalid data");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ g_variant_get(variant, "(ii)", &type, &value);
+
+ dnd_allow_exception->type = type;
+ dnd_allow_exception->value = value;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static int _send_service_register(uid_t uid)
+{
+ int result;
+ notification_op *noti_op = NULL;
+ GDBusMessage *reply = NULL;
+
+ result = _send_sync_noti(g_variant_new("(i)", uid), &reply, "noti_service_register");
+ if (reply)
+ g_object_unref(reply);
+ if (result != NOTIFICATION_ERROR_NONE) {
+ ERR("send sync noti [%d]", result);
+ return result;
+ }
+
+ is_master_started = 1;
+
+ noti_op = _ipc_create_op(NOTIFICATION_OP_SERVICE_READY, 1, NULL, 1, NULL);
+ if (noti_op != NULL) {
+ notification_call_changed_cb_for_uid(noti_op, 1, uid);
+ free(noti_op);
+ } else {
+ ERR("Failed to create op");
+ }
+
+ DBG("bus name[%s] result[%d]", _bus_name, result);
+ return result;
+}
+
+static int _ipc_monitor_register(uid_t uid)
+{
+ return _send_service_register(uid);
+}
+
+/* LCOV_EXCL_START */
+static void _on_name_appeared(GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ int uid = GPOINTER_TO_INT(user_data);
+
+ DBG("uid[%d] name[%s]", uid, name);
+
+ if (is_master_started == 0)
+ _ipc_monitor_register(uid);
+
+ /* TODO: dbus activation isn't enough ? */
+ _do_deffered_task();
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static void _on_name_vanished(GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ int uid = GPOINTER_TO_INT(user_data);
+
+ DBG("uid[%d] name[%s]", uid, name);
+ is_master_started = 0;
+}
+/* LCOV_EXCL_STOP */
+
+int notification_ipc_monitor_init(uid_t uid)
+{
+ int ret;
+
+ ret = _dbus_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init dbus connection[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _dbus_signal_init();
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init signal[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _ipc_monitor_register(uid);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to register service[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (provider_monitor_id == 0) {
+ provider_monitor_id = g_bus_watch_name_on_connection(
+ _gdbus_conn,
+ PROVIDER_BUS_NAME,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ _on_name_appeared,
+ _on_name_vanished,
+ GINT_TO_POINTER((int)uid),
+ NULL);
+ if (provider_monitor_id == 0) {
+ /* LCOV_EXCL_START */
+ g_dbus_connection_signal_unsubscribe(_gdbus_conn, monitor_id);
+ monitor_id = 0;
+ ERR("Failed to watch name");
+ return NOTIFICATION_ERROR_IO_ERROR;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static int _ipc_monitor_deregister(void)
+{
+ if (provider_monitor_id) {
+ g_bus_unwatch_name(provider_monitor_id);
+ provider_monitor_id = 0;
+ }
+
+ if (monitor_id) {
+ g_dbus_connection_signal_unsubscribe(_gdbus_conn, monitor_id);
+ monitor_id = 0;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_ipc_monitor_fini(void)
+{
+ return _ipc_monitor_deregister();
+}
+
+/* LCOV_EXCL_START */
+void notification_ipc_event_monitor_fini(void)
+{
+ if (event_monitor_id == 0)
+ return;
+
+ g_dbus_connection_signal_unsubscribe(_gdbus_conn, event_monitor_id);
+ event_monitor_id = 0;
+}
+/* LCOV_EXCL_STOP */
diff --git a/notification/src/notification_ipc_socket.c b/notification/src/notification_ipc_socket.c
new file mode 100644
index 0000000..54090ac
--- /dev/null
+++ b/notification/src/notification_ipc_socket.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2017 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.
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "notification_ipc.h"
+#include "notification_debug.h"
+
+#define RCV_SOCK 0
+#define SND_SOCK 1
+
+#define MAX_RETRY_CNT 10
+#define WRITE_TIMEOUT 20 /* milliseconds*/
+
+EXPORT_API int notification_ipc_socket_pair(int *fd)
+{
+ int ret_fd[2];
+ int err;
+
+ if (fd == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ errno = 0;
+ err = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, ret_fd);
+ if (err < 0) {
+ ERR("socketpair [%d]", errno);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+
+ fd[RCV_SOCK] = ret_fd[RCV_SOCK];
+ fd[SND_SOCK] = ret_fd[SND_SOCK];
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static int __get_socket_buffer_size(int fd, unsigned int *size, int optname)
+{
+ unsigned int ret_size = 0;
+ socklen_t len = sizeof(ret_size);
+
+ errno = 0;
+ if (getsockopt(fd, SOL_SOCKET, optname, &ret_size, &len) < 0) {
+ ERR("read socket size [%d]", errno);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+
+ *size = ret_size;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_ipc_socket_get_read_buf_size(int fd, unsigned int *size)
+{
+ return __get_socket_buffer_size(fd, size, SO_RCVBUF);
+}
+
+EXPORT_API int notification_ipc_socket_get_write_buf_size(int fd, unsigned int *size)
+{
+ return __get_socket_buffer_size(fd, size, SO_SNDBUF);
+}
+
+
+EXPORT_API int notification_ipc_socket_write(int fd, const char *buffer, unsigned int nbytes)
+{
+ int retry_cnt = 0;
+ unsigned int left = nbytes;
+ ssize_t nb;
+ const struct timespec SLEEP_TIME = { 0, 20 * 1000 * 1000 };
+
+ while (left && (retry_cnt < MAX_RETRY_CNT)) {
+ errno = 0;
+ nb = write(fd, buffer, left);
+ if (nb == -1) {
+ /* LCOV_EXCL_START */
+ if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
+ ERR("continue..");
+ retry_cnt++;
+ nanosleep(&SLEEP_TIME, 0);
+ continue;
+ }
+ ERR("error fd [%d] errno [%d]", fd, errno);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ /* LCOV_EXCL_STOP */
+ }
+
+ left -= nb;
+ buffer += nb;
+ retry_cnt = 0;
+ }
+
+ if (left != 0) {
+ ERR("error fd [%d], retry_cnt [%d]", fd, retry_cnt);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_ipc_socket_write_string(int fd, const char *buffer, unsigned int string_len)
+{
+ int ret;
+
+ ret = notification_ipc_socket_write(fd, (char *)&string_len, sizeof(string_len));
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("write string_len fail");
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (string_len > 0) {
+ ret = notification_ipc_socket_write(fd, buffer, string_len);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("write string fail");
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_ipc_socket_read(int fd, char *buffer, unsigned int nbytes)
+{
+ unsigned int left = nbytes;
+ ssize_t nb;
+ int retry_cnt = 0;
+ const struct timespec SLEEP_TIME = { 0, 20 * 1000 * 1000 };
+
+ while (left && (retry_cnt < MAX_RETRY_CNT)) {
+ errno = 0;
+ nb = read(fd, buffer, left);
+ if (nb == 0) {
+ ERR("read socket - EOF, fd close [%d]", fd);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ } else if (nb == -1) {
+ if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
+ ERR("errno [%d], sleep and retry", errno);
+ retry_cnt++;
+ nanosleep(&SLEEP_TIME, 0);
+ continue;
+ }
+ ERR("errno [%d] fd [%d]", errno, fd);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+ left -= nb;
+ buffer += nb;
+ retry_cnt = 0;
+ }
+
+ if (left != 0) {
+ ERR("error fd [%d] retry_cnt [%d]", fd, retry_cnt);
+ return NOTIFICATION_ERROR_IO_ERROR;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
diff --git a/notification/src/notification_list.c b/notification/src/notification_list.c
new file mode 100644
index 0000000..18d14b2
--- /dev/null
+++ b/notification/src/notification_list.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2000 - 2017 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.
+ */
+
+#include <stdlib.h>
+
+#include <tizen.h>
+
+#include <notification.h>
+#include <notification_list.h>
+#include <notification_noti.h>
+#include <notification_debug.h>
+#include <notification_private.h>
+#include <notification_ipc.h>
+
+
+struct _notification_list {
+ notification_list_h prev;
+ notification_list_h next;
+ notification_h noti;
+};
+
+notification_list_h _notification_list_create(void)
+{
+ notification_list_h list = NULL;
+
+ list = (notification_list_h)malloc(sizeof(struct _notification_list));
+ if (list == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ list->prev = NULL;
+ list->next = NULL;
+
+ list->noti = NULL;
+
+ return list;
+}
+
+EXPORT_API notification_list_h notification_list_get_head(notification_list_h list)
+{
+ notification_list_h cur_list = NULL;
+
+ if (list == NULL) {
+ ERR("Invalid parameter");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ cur_list = list;
+
+ while (cur_list->prev != NULL)
+ cur_list = cur_list->prev;
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ return cur_list;
+}
+
+EXPORT_API notification_list_h notification_list_get_tail(notification_list_h list)
+{
+ notification_list_h cur_list = NULL;
+
+ if (list == NULL) {
+ ERR("INVALID DATA : list == NULL");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ cur_list = list;
+
+ while (cur_list->next != NULL)
+ cur_list = cur_list->next;
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ return cur_list;
+}
+
+EXPORT_API notification_list_h notification_list_get_prev(notification_list_h list)
+{
+ notification_list_h cur_list = NULL;
+
+ if (list == NULL) {
+ ERR("INVALID DATA : list == NULL");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ cur_list = list;
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ return cur_list->prev;
+}
+
+EXPORT_API notification_list_h notification_list_get_next(notification_list_h list)
+{
+ notification_list_h cur_list = NULL;
+
+ if (list == NULL) {
+ ERR("INVALID DATA : list == NULL");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ cur_list = list;
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ return cur_list->next;
+}
+
+EXPORT_API notification_h notification_list_get_data(notification_list_h list)
+{
+ notification_list_h cur_list = NULL;
+
+ if (list == NULL) {
+ ERR("INVALID DATA : list == NULL");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ cur_list = list;
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ return cur_list->noti;
+}
+
+EXPORT_API int notification_list_get_count(notification_list_h list)
+{
+ int count = 0;
+ notification_list_h cur_list = NULL;
+
+ if (list == NULL) {
+ ERR("Invalid paramter");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ cur_list = notification_list_get_head(list);
+
+ while (cur_list != NULL) {
+ count++;
+ cur_list = cur_list->next;
+ }
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ return count;
+}
+
+EXPORT_API notification_list_h notification_list_append(notification_list_h list,
+ notification_h noti)
+{
+ notification_list_h new_list = NULL;
+ notification_list_h cur_list = NULL;
+
+ if (noti == NULL) {
+ ERR("Invalid parameter");
+ set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ if (list != NULL) {
+ cur_list = notification_list_get_tail(list);
+
+ new_list = _notification_list_create();
+ if (new_list == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ cur_list->next = new_list;
+ new_list->prev = cur_list;
+
+ new_list->noti = noti;
+ } else {
+ cur_list = _notification_list_create();
+ if (cur_list == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ new_list = cur_list;
+ new_list->noti = noti;
+ }
+
+ set_last_result(NOTIFICATION_ERROR_NONE);
+ return new_list;
+}
+
+EXPORT_API notification_list_h notification_list_remove(notification_list_h list,
+ notification_h noti)
+{
+ notification_list_h cur_list = NULL;
+ notification_list_h prev_list = NULL;
+ notification_list_h next_list = NULL;
+
+ cur_list = notification_list_get_head(list);
+ while (cur_list != NULL) {
+ if (cur_list->noti == noti) {
+ /* remove */
+ prev_list = cur_list->prev;
+ next_list = cur_list->next;
+
+ if (next_list != NULL) {
+ if (prev_list != NULL) {
+ prev_list->next = next_list;
+ next_list->prev = prev_list;
+ } else {
+ next_list->prev = NULL;
+ }
+ } else {
+ if (prev_list != NULL)
+ prev_list->next = NULL;
+ }
+
+ free(cur_list);
+ break;
+ }
+
+ cur_list = cur_list->next;
+ }
+
+ if (prev_list != NULL)
+ return notification_list_get_head(prev_list);
+ else if (next_list != NULL)
+ return next_list;
+
+ return NULL;
+}
+
+EXPORT_API int notification_get_list_for_uid(notification_type_e type,
+ int count,
+ notification_list_h *list, uid_t uid)
+{
+ notification_list_h get_list = NULL;
+ int ret = 0;
+
+ if (list == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_ipc_request_load_noti_grouping_list(type, 1, count, &get_list, uid);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ if (get_list != NULL)
+ *list = notification_list_get_head(get_list);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_list(notification_type_e type,
+ int count,
+ notification_list_h *list)
+{
+ return notification_get_list_for_uid(type, count, list, getuid());
+}
+
+EXPORT_API int notification_get_list_by_page_for_uid(notification_type_e type,
+ int page_number,
+ int count_per_page,
+ notification_list_h *list,
+ uid_t uid)
+{
+#define COUNT_PER_PAGE_MAX 100
+
+ int ret;
+ notification_list_h get_list = NULL;
+
+ if (list == NULL) {
+ ERR("Invalid parameter - list is null");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (page_number <= 0) {
+ ERR("Invalid parameter - page_number [%d]", page_number);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (count_per_page > COUNT_PER_PAGE_MAX) {
+ WARN("count_per_page exceeds max value, max must be set %d",
+ COUNT_PER_PAGE_MAX);
+ count_per_page = COUNT_PER_PAGE_MAX;
+ }
+
+ ret = notification_ipc_request_load_noti_grouping_list(type,
+ page_number, count_per_page, &get_list, uid);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("fail request load noti grouping list");
+ return ret;
+ }
+
+ *list = notification_list_get_head(get_list);
+
+ return ret;
+}
+
+EXPORT_API int notification_get_list_by_page(notification_type_e type,
+ int page_number, int count_per_page, notification_list_h *list)
+{
+ return notification_get_list_by_page_for_uid(type,
+ page_number, count_per_page, list, getuid());
+}
+
+EXPORT_API int notification_get_detail_list_for_uid(const char *app_id,
+ int group_id,
+ int priv_id,
+ int count,
+ notification_list_h *list,
+ uid_t uid)
+{
+ int ret = 0;
+ notification_list_h get_list = NULL;
+
+ if (list == NULL || app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ ret = notification_ipc_request_load_noti_detail_list(app_id, group_id, priv_id, count,
+ &get_list, uid);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ return ret;
+
+ if (get_list != NULL)
+ *list = notification_list_get_head(get_list);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_get_detail_list(const char *app_id,
+ int group_id,
+ int priv_id,
+ int count,
+ notification_list_h *list)
+{
+ return notification_get_detail_list_for_uid(app_id, group_id,
+ priv_id, count, list, getuid());
+}
+
+EXPORT_API int notification_free_list(notification_list_h list)
+{
+ notification_list_h cur_list = NULL;
+ notification_h noti = NULL;
+
+ if (list == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ cur_list = notification_list_get_head(list);
+
+ while (cur_list != NULL) {
+ noti = notification_list_get_data(cur_list);
+ cur_list = notification_list_remove(cur_list, noti);
+
+ notification_free(noti);
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
diff --git a/notification/src/notification_noti.c b/notification/src/notification_noti.c
new file mode 100644
index 0000000..df0455e
--- /dev/null
+++ b/notification/src/notification_noti.c
@@ -0,0 +1,2299 @@
+/*
+ * Copyright (c) 2000 - 2017 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.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <vconf.h>
+#include <pkgmgr-info.h>
+#include <package_manager.h>
+#include <app_control_internal.h>
+#include <bundle_internal.h>
+#include <iniparser.h>
+
+#include <notification.h>
+#include <notification_internal.h>
+#include <notification_db.h>
+#include <notification_list.h>
+#include <notification_noti.h>
+#include <notification_debug.h>
+#include <notification_private.h>
+#include <notification_setting.h>
+#include <notification_setting_internal.h>
+#include <notification_setting_service.h>
+#include "notification_db_query.h"
+
+#define NOTI_BURST_DELETE_UNIT 10
+#define ERR_BUFFER_SIZE 1024
+#define NOTI_LIMIT 100
+
+static void __free_and_set(void **target_ptr, void *new_ptr)
+{
+ if (target_ptr != NULL) {
+ if (*target_ptr != NULL)
+ free(*target_ptr);
+
+ *target_ptr = new_ptr;
+ }
+}
+
+static void __free_encoded_data(char *encoded_data)
+{
+ if (encoded_data)
+ bundle_free_encoded_rawdata((bundle_raw **)&encoded_data);
+}
+
+static void __free_deleted_list(notification_deleted_list_info_s *info, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if ((info + i)->app_id != NULL)
+ free((info + i)->app_id);
+ }
+
+ free(info);
+}
+
+static void __notification_noti_populate_from_stmt(sqlite3_stmt *stmt, notification_h noti)
+{
+ int col = 0;
+ int i = 0;
+
+ if (stmt == NULL || noti == NULL)
+ return;
+
+ noti->type = sqlite3_column_int(stmt, col++);
+ noti->layout = sqlite3_column_int(stmt, col++);
+ __free_and_set((void **)&(noti->pkg_id), notification_db_column_text(stmt, col++));
+ __free_and_set((void **)&(noti->caller_app_id), notification_db_column_text(stmt, col++));
+ __free_and_set((void **)&(noti->launch_app_id), notification_db_column_text(stmt, col++));
+ __free_and_set((void **)&(noti->app_label), notification_db_column_text(stmt, col++));
+ noti->b_image_path = notification_db_column_bundle(stmt, col++);
+ noti->b_priv_image_path = notification_db_column_bundle(stmt, col++);
+ noti->group_id = sqlite3_column_int(stmt, col++);
+ noti->internal_group_id = 0;
+ noti->priv_id = sqlite3_column_int(stmt, col++);
+ noti->b_text = notification_db_column_bundle(stmt, col++);
+ noti->b_key = notification_db_column_bundle(stmt, col++);
+ __free_and_set((void **)&(noti->tag), notification_db_column_text(stmt, col++));
+ noti->b_format_args = notification_db_column_bundle(stmt, col++);
+ noti->num_format_args = sqlite3_column_int(stmt, col++);
+
+ __free_and_set((void **)&(noti->domain), notification_db_column_text(stmt, col++));
+ __free_and_set((void **)&(noti->dir), notification_db_column_text(stmt, col++));
+ noti->time = sqlite3_column_int(stmt, col++);
+ noti->insert_time = sqlite3_column_int(stmt, col++);
+ noti->args = notification_db_column_bundle(stmt, col++);
+ noti->group_args = notification_db_column_bundle(stmt, col++);
+
+ noti->b_execute_option = notification_db_column_bundle(stmt, col++);
+ noti->b_service_responding = notification_db_column_bundle(stmt, col++);
+ noti->b_service_single_launch =
+ notification_db_column_bundle(stmt, col++);
+ noti->b_service_multi_launch =
+ notification_db_column_bundle(stmt, col++);
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++)
+ noti->b_event_handler[i] = notification_db_column_bundle(stmt, col++);
+
+ noti->sound_type = sqlite3_column_int(stmt, col++);
+ __free_and_set((void **)&(noti->sound_path), notification_db_column_text(stmt, col++));
+ __free_and_set((void **)&(noti->priv_sound_path), notification_db_column_text(stmt, col++));
+ noti->vibration_type = sqlite3_column_int(stmt, col++);
+ __free_and_set((void **)&(noti->vibration_path), notification_db_column_text(stmt, col++));
+ __free_and_set((void **)&(noti->priv_vibration_path), notification_db_column_text(stmt, col++));
+ noti->led_operation = sqlite3_column_int(stmt, col++);
+ noti->led_argb = sqlite3_column_int(stmt, col++);
+ noti->led_on_ms = sqlite3_column_int(stmt, col++);
+ noti->led_off_ms = sqlite3_column_int(stmt, col++);
+
+ noti->flags_for_property = sqlite3_column_int(stmt, col++);
+ noti->display_applist = sqlite3_column_int(stmt, col++);
+ noti->progress_size = sqlite3_column_double(stmt, col++);
+ noti->progress_percentage = sqlite3_column_double(stmt, col++);
+
+ noti->ongoing_flag = sqlite3_column_int(stmt, col++);
+ noti->ongoing_value_type = sqlite3_column_int(stmt, col++);
+ noti->ongoing_current = sqlite3_column_int(stmt, col++);
+ noti->ongoing_duration = sqlite3_column_int(stmt, col++);
+ noti->auto_remove = sqlite3_column_int(stmt, col++);
+ noti->default_button_index = sqlite3_column_int(stmt, col++);
+ noti->hide_timeout = sqlite3_column_int(stmt, col++);
+ noti->delete_timeout = sqlite3_column_int(stmt, col++);
+ noti->text_input_max_length = sqlite3_column_int(stmt, col++);
+ noti->event_flag = sqlite3_column_int(stmt, col++);
+ noti->extension_image_size = sqlite3_column_int(stmt, col++);
+ noti->uid = sqlite3_column_int(stmt, col++);
+
+ noti->app_icon_path = NULL;
+ noti->temp_title = NULL;
+ noti->temp_content = NULL;
+}
+
+static int _notification_noti_check_priv_id(notification_h noti, sqlite3 *db)
+{
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ int result = 0;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ query = sqlite3_mprintf("SELECT count(*) FROM noti_list "
+ "WHERE caller_app_id = %Q AND priv_id = %d",
+ noti->caller_app_id, noti->priv_id);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc query");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to sqlite3_prepare_v2 Failed [%d][%s]",
+ ret, sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ result = sqlite3_column_int(stmt, 0);
+ else
+ result = 0;
+
+ /* If result > 0, there is priv_id in DB */
+ if (result > 0)
+ ret = NOTIFICATION_ERROR_ALREADY_EXIST_ID;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ return ret;
+}
+
+static int _notification_noti_get_internal_group_id_by_priv_id(const char *app_id,
+ int priv_id,
+ sqlite3 *db)
+{
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int result = 0;
+
+ query = sqlite3_mprintf("SELECT internal_group_id FROM noti_list "
+ "WHERE caller_app_id = %Q AND priv_id = %d",
+ app_id, priv_id);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc query"); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 Failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ result = sqlite3_column_int(stmt, 0);
+ else
+ result = 0;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (ret != NOTIFICATION_ERROR_NONE)
+ ERR("Failed to get internal group ID [%d]", ret);
+
+ return result;
+}
+
+static int _create_insertion_query(sqlite3 *db, notification_h noti, sqlite3_stmt *stmt, int *index)
+{
+ char buf_key[32] = { 0, };
+ char *title_key = NULL;
+ char *b_text = NULL;
+ char *b_key = NULL;
+ char *b_format_args = NULL;
+ char *args = NULL;
+ char *group_args = NULL;
+ char *b_image_path = NULL;
+ char *b_priv_image_path = NULL;
+ char *b_execute_option = NULL;
+ char *b_service_responding = NULL;
+ char *b_service_single_launch = NULL;
+ char *b_service_multi_launch = NULL;
+ char *b_event_handler[NOTIFICATION_EVENT_TYPE_MAX+1] = { NULL, };
+ int flag_simmode = 0;
+ int idx = 1;
+ int i = 0;
+ int b_encode_len = 0;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (noti == NULL || stmt == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (noti->b_image_path)
+ bundle_encode(noti->b_image_path, (bundle_raw **)&b_image_path,
+ &b_encode_len);
+
+ if (noti->b_priv_image_path)
+ bundle_encode(noti->b_priv_image_path,
+ (bundle_raw **)&b_priv_image_path, &b_encode_len);
+
+ /* Get title key */
+ if (noti->b_key != NULL) {
+ snprintf(buf_key, sizeof(buf_key), "%d",
+ NOTIFICATION_TEXT_TYPE_TITLE);
+
+ bundle_get_str(noti->b_key, buf_key, &title_key);
+ }
+
+ if (title_key == NULL && noti->b_text != NULL) {
+ snprintf(buf_key, sizeof(buf_key), "%d",
+ NOTIFICATION_TEXT_TYPE_TITLE);
+
+ bundle_get_str(noti->b_text, buf_key, &title_key);
+ }
+
+ if (title_key == NULL)
+ title_key = noti->caller_app_id;
+
+ if (noti->b_text)
+ bundle_encode(noti->b_text, (bundle_raw **)&b_text, &b_encode_len);
+
+ if (noti->b_key)
+ bundle_encode(noti->b_key, (bundle_raw **)&b_key, &b_encode_len);
+
+ if (noti->b_format_args)
+ bundle_encode(noti->b_format_args,
+ (bundle_raw **)&b_format_args, &b_encode_len);
+
+ if (noti->args)
+ bundle_encode(noti->args, (bundle_raw **)&args, &b_encode_len);
+
+ if (noti->group_args)
+ bundle_encode(noti->group_args, (bundle_raw **)&group_args,
+ &b_encode_len);
+
+ if (noti->b_execute_option)
+ bundle_encode(noti->b_execute_option,
+ (bundle_raw **)&b_execute_option, &b_encode_len);
+
+ if (noti->b_service_responding)
+ bundle_encode(noti->b_service_responding,
+ (bundle_raw **)&b_service_responding, &b_encode_len);
+
+ if (noti->b_service_single_launch)
+ bundle_encode(noti->b_service_single_launch,
+ (bundle_raw **)&b_service_single_launch, &b_encode_len);
+
+ if (noti->b_service_multi_launch)
+ bundle_encode(noti->b_service_multi_launch,
+ (bundle_raw **)&b_service_multi_launch, &b_encode_len);
+
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++) {
+ if (noti->b_event_handler[i])
+ bundle_encode(noti->b_event_handler[i],
+ (bundle_raw **)&b_event_handler[i], &b_encode_len);
+ }
+
+ /* Check only simmode property is enable */
+ if (noti->flags_for_property & NOTIFICATION_PROP_DISPLAY_ONLY_SIMMODE)
+ flag_simmode = 1;
+
+ __BIND_INT(db, stmt, idx++, noti->type, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->layout, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->pkg_id), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->caller_app_id), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->launch_app_id), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->app_label), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_image_path), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_priv_image_path), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->group_id, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->internal_group_id, ret, out);
+ __BIND_TEXT_STATIC(db, stmt, idx++, NOTIFICATION_CHECK_STR(title_key), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_text), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_key), ret, out);
+ __BIND_TEXT_STATIC(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->tag), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_format_args), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->num_format_args, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->domain), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->dir), ret, out);
+ __BIND_INT(db, stmt, idx++, (int)noti->time, ret, out);
+ __BIND_INT(db, stmt, idx++, (int)noti->insert_time, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(args), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(group_args), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_execute_option), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_service_responding), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_service_single_launch), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_service_multi_launch), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_2]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_3]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_4]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_5]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_6]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_ICON]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_THUMBNAIL]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_7]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_8]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_9]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_10]), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->sound_type, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->sound_path), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->priv_sound_path), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->vibration_type, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->vibration_path), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->priv_vibration_path), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_operation, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_argb, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_on_ms, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_off_ms, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->flags_for_property, ret, out);
+ __BIND_INT(db, stmt, idx++, flag_simmode, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->display_applist, ret, out);
+ __BIND_DOUBLE(db, stmt, idx++, noti->progress_size, ret, out);
+ __BIND_DOUBLE(db, stmt, idx++, noti->progress_percentage, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_flag, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_value_type, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_current, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_duration, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->auto_remove, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->default_button_index, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->hide_timeout, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->delete_timeout, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->text_input_max_length, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->event_flag, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->extension_image_size, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->uid, ret, out);
+
+out:
+ __free_encoded_data(b_image_path);
+ __free_encoded_data(b_priv_image_path);
+ __free_encoded_data(b_text);
+ __free_encoded_data(b_key);
+ __free_encoded_data(b_format_args);
+ __free_encoded_data(args);
+ __free_encoded_data(group_args);
+ __free_encoded_data(b_execute_option);
+ __free_encoded_data(b_service_responding);
+ __free_encoded_data(b_service_single_launch);
+ __free_encoded_data(b_service_multi_launch);
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++)
+ __free_encoded_data(b_event_handler[i]);
+
+ if (index != NULL && ret == NOTIFICATION_ERROR_NONE)
+ *index = idx;
+
+ return ret;
+}
+
+static int _create_update_query(sqlite3 *db, notification_h noti, sqlite3_stmt *stmt)
+{
+ char *b_image_path = NULL;
+ char *b_priv_image_path = NULL;
+ char *b_text = NULL;
+ char *b_key = NULL;
+ char *b_format_args = NULL;
+ char *args = NULL;
+ char *group_args = NULL;
+ char *b_execute_option = NULL;
+ char *b_service_responding = NULL;
+ char *b_service_single_launch = NULL;
+ char *b_service_multi_launch = NULL;
+ char *b_event_handler[NOTIFICATION_EVENT_TYPE_MAX+1] = { NULL, };
+ int flag_simmode = 0;
+ int idx = 1;
+ int i = 0;
+ int b_encode_len = 0;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (noti == NULL || stmt == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ /* Decode bundle to update DB */
+ if (noti->b_image_path)
+ bundle_encode(noti->b_image_path,
+ (bundle_raw **)&b_image_path, &b_encode_len);
+
+ if (noti->b_priv_image_path)
+ bundle_encode(noti->b_priv_image_path,
+ (bundle_raw **)&b_priv_image_path, &b_encode_len);
+
+ if (noti->b_text)
+ bundle_encode(noti->b_text,
+ (bundle_raw **)&b_text, &b_encode_len);
+
+ if (noti->b_key)
+ bundle_encode(noti->b_key,
+ (bundle_raw **)&b_key, &b_encode_len);
+
+ if (noti->b_format_args)
+ bundle_encode(noti->b_format_args,
+ (bundle_raw **)&b_format_args, &b_encode_len);
+
+ if (noti->args)
+ bundle_encode(noti->args, (bundle_raw **)&args, &b_encode_len);
+
+ if (noti->group_args)
+ bundle_encode(noti->group_args, (bundle_raw **)&group_args,
+ &b_encode_len);
+
+ if (noti->b_execute_option)
+ bundle_encode(noti->b_execute_option,
+ (bundle_raw **)&b_execute_option, &b_encode_len);
+
+ if (noti->b_service_responding)
+ bundle_encode(noti->b_service_responding,
+ (bundle_raw **)&b_service_responding, &b_encode_len);
+
+ if (noti->b_service_single_launch)
+ bundle_encode(noti->b_service_single_launch,
+ (bundle_raw **)&b_service_single_launch, &b_encode_len);
+
+ if (noti->b_service_multi_launch)
+ bundle_encode(noti->b_service_multi_launch,
+ (bundle_raw **)&b_service_multi_launch, &b_encode_len);
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++) {
+ if (noti->b_event_handler[i])
+ bundle_encode(noti->b_event_handler[i],
+ (bundle_raw **)&b_event_handler[i], &b_encode_len);
+ }
+
+ /* Check only simmode property is enable */
+ if (noti->flags_for_property & NOTIFICATION_PROP_DISPLAY_ONLY_SIMMODE)
+ flag_simmode = 1;
+
+ __BIND_INT(db, stmt, idx++, noti->type, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->layout, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->launch_app_id), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->app_label), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_image_path), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_priv_image_path), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_text), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_key), ret, out);
+ __BIND_TEXT_STATIC(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->tag), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_format_args), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->num_format_args, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->domain), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->dir), ret, out);
+ __BIND_INT(db, stmt, idx++, (int)noti->time, ret, out);
+ __BIND_INT(db, stmt, idx++, (int)noti->insert_time, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(args), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(group_args), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_execute_option), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_service_responding), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_service_single_launch), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_service_multi_launch), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_2]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_3]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_4]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_5]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_6]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_ICON]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_THUMBNAIL]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_7]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_8]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_9]), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(b_event_handler[NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_10]), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->sound_type, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->sound_path), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->priv_sound_path), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->vibration_type, ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->vibration_path), ret, out);
+ __BIND_TEXT(db, stmt, idx++, NOTIFICATION_CHECK_STR(noti->priv_vibration_path), ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_operation, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_argb, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_on_ms, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->led_off_ms, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->flags_for_property, ret, out);
+ __BIND_INT(db, stmt, idx++, flag_simmode, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->display_applist, ret, out);
+ __BIND_DOUBLE(db, stmt, idx++, noti->progress_size, ret, out);
+ __BIND_DOUBLE(db, stmt, idx++, noti->progress_percentage, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_flag, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_value_type, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_current, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->ongoing_duration, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->auto_remove, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->default_button_index, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->hide_timeout, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->delete_timeout, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->text_input_max_length, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->event_flag, ret, out);
+ __BIND_INT(db, stmt, idx++, noti->extension_image_size, ret, out);
+
+out:
+ __free_encoded_data(b_image_path);
+ __free_encoded_data(b_priv_image_path);
+ __free_encoded_data(b_text);
+ __free_encoded_data(b_key);
+ __free_encoded_data(b_format_args);
+ __free_encoded_data(args);
+ __free_encoded_data(group_args);
+ __free_encoded_data(b_execute_option);
+ __free_encoded_data(b_service_responding);
+ __free_encoded_data(b_service_single_launch);
+ __free_encoded_data(b_service_multi_launch);
+
+ for (i = 0; i <= NOTIFICATION_EVENT_TYPE_MAX; i++)
+ __free_encoded_data(b_event_handler[i]);
+
+ return ret;
+}
+
+static int _get_notification(char *query_where, notification_h noti)
+{
+ int ret;
+ char *query = NULL;
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+
+ if (query_where == NULL || noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT %s FROM %s",
+ NOTI_LIST_DB_ATTRIBUTES_SELECT, query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW) {
+ __notification_noti_populate_from_stmt(stmt, noti);
+ ret = NOTIFICATION_ERROR_NONE;
+ } else {
+ if (ret == SQLITE_DONE)
+ DBG("No valid record found");
+ else
+ ERR("sqlite3_step failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ }
+
+err:
+ if (query)
+ sqlite3_free(query);
+
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (db != NULL)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+static int _get_notification_list(char *query_where, notification_list_h *list, int *list_count, int count)
+{
+ int ret;
+ int internal_count = 0;
+ char *query = NULL;
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+ notification_list_h get_list = NULL;
+ notification_h noti = NULL;
+
+ if (query_where == NULL || list == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT %s FROM %s",
+ NOTI_LIST_DB_ATTRIBUTES_SELECT, query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ noti = (notification_h)calloc(1, sizeof(struct _notification));
+ if (noti == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ if (get_list) {
+ get_list = notification_list_get_head(get_list);
+ notification_free_list(get_list);
+ }
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ __notification_noti_populate_from_stmt(stmt, noti);
+ if (noti != NULL) {
+ internal_count++;
+ get_list = notification_list_append(get_list, noti);
+ if (count != -1 && internal_count >= count) {
+ INFO("internal count[%d] count[%d]",
+ internal_count, count);
+ break;
+ }
+ }
+ }
+
+ if (get_list != NULL) {
+ *list = notification_list_get_head(get_list);
+ if (list_count)
+ *list_count = internal_count;
+ }
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (db != NULL)
+ notification_db_close(&db);
+
+ if (query)
+ sqlite3_free(query);
+
+ return ret;
+}
+int notification_noti_set_tag(const char *tag, char *value, char *buf, int buf_len)
+{
+ int len_total = 0;
+
+ len_total += (strlen(tag) * 2) + 5 + strlen(value) + 1;
+
+ if (buf_len <= len_total)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ snprintf(buf, buf_len, "<%s>%s</%s>", tag, value, tag);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+char *notification_noti_strip_tag(const char *tagged_str)
+{
+ if (tagged_str == NULL)
+ return NULL;
+
+ int len_total = strlen(tagged_str);
+
+ if (len_total == 0)
+ return NULL;
+
+ char *b_f_e = strstr(tagged_str, ">");
+ char *b_e_s = strstr(tagged_str, "</");
+
+ if (b_f_e == NULL || b_e_s == NULL || (b_e_s - b_f_e - 1) <= 0)
+ return NULL;
+
+ return strndup(b_f_e + 1, b_e_s - b_f_e - 1);
+}
+
+int notification_noti_get_tag_type(const char *tagged_str)
+{
+ if (tagged_str == NULL)
+ return TAG_TYPE_INVALID;
+
+ if (strlen(tagged_str) == 0)
+ return TAG_TYPE_INVALID;
+
+ char *b_f_s = strstr(tagged_str, "<");
+ char *b_f_e = strstr(tagged_str, ">");
+
+ if (b_f_s == NULL || b_f_e == NULL || (b_f_e - b_f_s - 1) <= 0)
+ return TAG_TYPE_INVALID;
+
+ char *start = b_f_s + 1;
+ int len_tag = b_f_e - b_f_s - 1;
+
+ if (strncmp(start, TAG_TIME, len_tag) == 0)
+ return TAG_TYPE_TIME;
+
+ return TAG_TYPE_INVALID;
+}
+
+/* LCOV_EXCL_START */
+static int __get_setting_from_app_control(notification_h noti, notification_setting_h *setting)
+{
+ notification_setting_h setting_new = NULL;
+ app_control_h app_control = NULL;
+ bundle *b = NULL;
+ char *app_id = NULL;
+ int ret;
+
+ ret = notification_get_execute_option(noti,
+ NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH,
+ NULL,
+ &b);
+ if (ret != NOTIFICATION_ERROR_NONE || b == NULL) {
+ WARN("Failed to get or no the excute option [%x]", ret);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ ret = app_control_create(&app_control);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ ERR("Failed to create app_control [%x]", ret);
+ goto out;
+ }
+
+ ret = app_control_import_from_bundle(app_control, b);
+ if (ret != APP_CONTROL_ERROR_NONE) {
+ ERR("Failed to import from bundle to app_control [%x]", ret);
+ goto out;
+ }
+
+ ret = app_control_get_app_id(app_control, &app_id);
+ if (ret != APP_CONTROL_ERROR_NONE || app_id == NULL) {
+ ERR("Failed to get app id from app_control [%x]", ret);
+ goto out;
+ }
+
+ ret = noti_setting_service_get_setting_by_app_id(app_id, &setting_new, noti->uid);
+ if (ret != APP_CONTROL_ERROR_NONE || setting == NULL) {
+ ERR("Failed to get setting by app id[%s][%x]",
+ app_id, ret);
+ goto out;
+ }
+
+ *setting = setting_new;
+
+out:
+ if (app_id)
+ free(app_id);
+
+ if (app_control)
+ app_control_destroy(app_control);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+static bool _is_allowed_to_notify(notification_h noti)
+{
+ notification_setting_h setting = NULL;
+ bool allow_to_notify = true;
+ bool app_disabled = false;
+ bool ret = true;
+ int err;
+
+ err = noti_setting_service_get_setting_by_app_id(noti->caller_app_id,
+ &setting, noti->uid);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ err = __get_setting_from_app_control(noti, &setting);
+ if (err != NOTIFICATION_ERROR_NONE)
+ return ret;
+ }
+
+ err = notification_setting_get_allow_to_notify(setting, &allow_to_notify);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get allow_to_notify [%x]", err);
+ goto out;
+ }
+
+ err = notification_setting_get_app_disabled(setting, &app_disabled);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get app_disabled [%x]", err);
+ goto out;
+ }
+
+ if (!allow_to_notify || app_disabled)
+ ret = false;
+
+out:
+ if (setting)
+ notification_setting_free_notification(setting);
+
+ return ret;
+}
+
+static int _handle_do_not_disturb_option(notification_h noti)
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ bool do_not_disturb = false;
+ bool do_not_disturb_exception = false;
+ notification_setting_h setting = NULL;
+ notification_system_setting_h system_setting = NULL;
+
+ if (noti == NULL) {
+ ERR("Invalid notification handle");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ /* Get system setting */
+ err = noti_system_setting_load_system_setting(&system_setting, noti->uid);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to load system setting [%d]", err);
+ goto out;
+ }
+
+ err = notification_system_setting_get_do_not_disturb(system_setting,
+ &do_not_disturb);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get do_not_disturb [%d]", err);
+ goto out;
+ }
+
+ DBG("do_not_disturb [%d]", do_not_disturb);
+
+ if (do_not_disturb) {
+ /* Check exception option of the caller app_id */
+ err = noti_setting_service_get_setting_by_app_id(noti->caller_app_id, &setting, noti->uid);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get setting by app_id [%d]", err);
+ goto out;
+ }
+
+ err = notification_setting_get_do_not_disturb_except(setting, &do_not_disturb_exception);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get do_not_disturb_exception [%d]", err);
+ goto out;
+ }
+
+ if (do_not_disturb_exception == false) {
+ /* do_not_disturb is ON and do_not_disturb_exception is OFF */
+ /* Then add this notification only on quick panel and indicator */
+ noti->display_applist = noti->display_applist &
+ (NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY |
+ NOTIFICATION_DISPLAY_APP_INDICATOR);
+ /* and reset all sound and vibration and led options */
+ noti->sound_type = NOTIFICATION_SOUND_TYPE_NONE;
+ SAFE_FREE(noti->sound_path);
+ SAFE_FREE(noti->priv_sound_path);
+ noti->vibration_type = NOTIFICATION_VIBRATION_TYPE_NONE;
+ SAFE_FREE(noti->vibration_path);
+ SAFE_FREE(noti->priv_vibration_path);
+ noti->led_operation = NOTIFICATION_LED_OP_OFF;
+ noti->led_argb = 0;
+ noti->led_on_ms = 0;
+ noti->led_off_ms = 0;
+ }
+ }
+
+out:
+ if (system_setting)
+ notification_system_setting_free_system_setting(system_setting);
+
+ if (setting)
+ notification_setting_free_notification(setting);
+
+ return err;
+}
+
+static bool _is_pop_up_notification(const char *app_id, uid_t uid)
+{
+ int err;
+ bool ret = true;
+ notification_setting_h setting = NULL;
+
+ err = noti_setting_service_get_setting_by_app_id(app_id, &setting, uid);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ WARN("Failed get the setting for [%s] [%x]", app_id, err);
+ goto out;
+ }
+
+ err = notification_setting_get_pop_up_notification(setting, &ret);
+ if (err != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get pop_up_notification [%d]", err);
+ goto out;
+ }
+
+ if (ret != true)
+ DBG("[%s] is not allowed Pop-up notification", app_id);
+
+out:
+ if (setting)
+ notification_setting_free_notification(setting);
+
+ return ret;
+}
+
+static int _check_text_input(notification_h noti)
+{
+ int err;
+ int text_input_max_length;
+ app_control_h app_control = NULL;
+
+ err = notification_get_text_input_max_length(noti, &text_input_max_length);
+ if (err == NOTIFICATION_ERROR_NONE && text_input_max_length != 0) {
+ err = notification_get_event_handler(noti, NOTIFICATION_EVENT_TYPE_CLICK_ON_TEXT_INPUT_BUTTON, &app_control);
+ if (err != NOTIFICATION_ERROR_NONE || app_control == NULL) {
+ ERR("Event handler for text_input is not set");
+ return -1;
+ }
+ app_control_destroy(app_control);
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static int _get_noti_count(sqlite3 *db, char *query_where, int *count)
+{
+ int ret;
+ char *query = NULL;
+ sqlite3_stmt *stmt = NULL;
+
+ if (db == NULL || query_where == NULL || count == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ query = sqlite3_mprintf("SELECT COUNT(*) FROM noti_list %s", query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_mprintf Failed");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 Failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW) {
+ *count = sqlite3_column_int(stmt, 0);
+ ret = NOTIFICATION_ERROR_NONE;
+ } else {
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ }
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+ if (query)
+ sqlite3_free(query);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_insert(notification_h noti)
+{
+ int ret = 0;
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+
+ if (noti == NULL) {
+ ERR("Invalid notification handle");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (_is_allowed_to_notify(noti) == false) {
+ ERR("[%s] is not allowed to notify", noti->caller_app_id);
+ return NOTIFICATION_ERROR_PERMISSION_DENIED;
+ }
+
+ if (_handle_do_not_disturb_option(noti) != NOTIFICATION_ERROR_NONE)
+ WARN("Failed to handle do_not_disturb");
+
+ if (_is_pop_up_notification((const char *)noti->caller_app_id, noti->uid) == false) {
+ noti->display_applist = (noti->display_applist & (~NOTIFICATION_DISPLAY_APP_ACTIVE));
+ DBG("notification display applist - app_id [%s], applist [%d]",
+ noti->caller_app_id, noti->display_applist);
+ }
+
+ if (_check_text_input(noti) != NOTIFICATION_ERROR_NONE)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ /* Initialize private ID */
+ noti->group_id = NOTIFICATION_GROUP_ID_NONE;
+ noti->internal_group_id = NOTIFICATION_GROUP_ID_NONE;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("INSERT INTO noti_list (%s) VALUES (%s)",
+ NOTI_LIST_DB_ATTRIBUTES_INSERT, NOTI_LIST_INSERT_VALUES);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_mprintf Failed");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 Failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _create_insertion_query(db, noti, stmt, NULL);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto err;
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_OK || ret == SQLITE_DONE) {
+ noti->priv_id = (int)sqlite3_last_insert_rowid(db);
+ ret = NOTIFICATION_ERROR_NONE;
+ } else {
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ }
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_noti_get_by_priv_id(notification_h noti, int priv_id)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *query_where = NULL;
+
+ if (priv_id < 0 || noti == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ query_where = sqlite3_mprintf("noti_list WHERE priv_id = %d", priv_id);
+ if (query_where == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _get_notification(query_where, noti);
+
+err:
+ if (query_where)
+ sqlite3_free(query_where);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_noti_get_by_tag(notification_h noti, char *app_id, char *tag, uid_t uid)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *query_where;
+
+ if (tag == NULL || noti == NULL) {
+ ERR("Invalid paramter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ query_where = sqlite3_mprintf("noti_list WHERE caller_app_id = %Q "
+ "AND tag = %Q AND uid = %d", app_id, tag, uid);
+ if (query_where == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _get_notification(query_where, noti);
+
+err:
+ if (query_where)
+ sqlite3_free(query_where);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_update(notification_h noti)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ sqlite3 *db;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+
+ if (noti == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (_is_allowed_to_notify(noti) == false) {
+ DBG("[%s] is not allowed to notify", noti->caller_app_id);
+ return NOTIFICATION_ERROR_PERMISSION_DENIED;
+ }
+
+ if (_handle_do_not_disturb_option(noti) != NOTIFICATION_ERROR_NONE)
+ WARN("Failed to handle do_not_disturb");
+
+ if (_is_pop_up_notification((const char *)noti->caller_app_id, noti->uid) == false) {
+ noti->display_applist = (noti->display_applist & (~NOTIFICATION_DISPLAY_APP_ACTIVE));
+ DBG("notification display applist - app_id [%s], applist [%d]",
+ noti->caller_app_id, noti->display_applist);
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ /* Check private ID is exist */
+ ret = _notification_noti_check_priv_id(noti, db);
+ if (ret != NOTIFICATION_ERROR_ALREADY_EXIST_ID) {
+ ERR("The ID is not existed");
+ ret = NOTIFICATION_ERROR_NOT_EXIST_ID;
+ goto err;
+ }
+
+ query = sqlite3_mprintf("UPDATE noti_list SET %s WHERE priv_id = %d ",
+ NOTI_LIST_DB_ATTRIBUTES_UPDATE, noti->priv_id);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 Failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _create_update_query(db, noti, stmt);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto err;
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_OK || ret == SQLITE_DONE)
+ ret = NOTIFICATION_ERROR_NONE;
+ else
+ ret = NOTIFICATION_ERROR_FROM_DB;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_delete_all(notification_type_e type,
+ const char *app_id, int *deleted_num,
+ int **deleted_list, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ char *query_where = NULL;
+ int *tmp = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int count = 0;
+ int i = 0;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ /* create query_where according to appid and type */
+ if (app_id == NULL || strlen(app_id) == 0) {
+ if (type == NOTIFICATION_TYPE_NONE)
+ query_where = sqlite3_mprintf("WHERE uid = %d", uid);
+ else
+ query_where = sqlite3_mprintf("WHERE type = %d "
+ "AND uid = %d", type, uid);
+ if (query_where == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+ } else {
+ if (type == NOTIFICATION_TYPE_NONE)
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND uid = %d", app_id, uid);
+ else
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND type = %d AND uid = %d",
+ app_id, type, uid);
+
+ if (query_where == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ /* check count to delete */
+ ret = _get_noti_count(db, query_where, &count);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get count to delete %d", ret);
+ goto err;
+ }
+
+ /* Get priv_id and add to list */
+ if (count > 0 && deleted_list != NULL) {
+ query = sqlite3_mprintf("SELECT priv_id FROM noti_list %s",
+ query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to sqlite3_prepare_V2 [%d][%s]",
+ ret, sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ tmp = (int *)calloc(count, sizeof(int));
+ if (tmp == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ *(tmp + i) = sqlite3_column_int(stmt, 0);
+ i++;
+ }
+
+ sqlite3_free(query);
+ query = NULL;
+ }
+
+ /* execute main query */
+ query = sqlite3_mprintf("DELETE FROM noti_list %s", query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto err;
+
+ if (deleted_list)
+ *deleted_list = tmp;
+
+ if (deleted_num != NULL)
+ *deleted_num = count;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (query_where)
+ sqlite3_free(query_where);
+
+ if (db)
+ notification_db_close(&db);
+
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ if (tmp != NULL)
+ free(tmp);
+ }
+
+ return ret;
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_noti_delete_by_priv_id(const char *app_id, int priv_id)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("DELETE FROM noti_list WHERE caller_app_id = %Q "
+ "AND priv_id = %d", app_id, priv_id);
+ if (query == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+
+err:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_noti_delete_by_priv_id_get_changes(const char *app_id,
+ int priv_id,
+ int *num_changes,
+ uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("DELETE FROM noti_list WHERE caller_app_id = %Q "
+ "AND priv_id = %d AND uid = %d",
+ app_id, priv_id, uid);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, num_changes);
+
+err:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_delete_by_display_applist(int display_applist,
+ int *deleted_num,
+ notification_deleted_list_info_s **deleted_list,
+ uid_t uid)
+{
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+ notification_deleted_list_info_s *info = NULL;
+ char *query = NULL;
+ char *query_where = NULL;
+ int count = 0;
+ int ret;
+ int i = 0;
+
+ if (display_applist < NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query_where = sqlite3_mprintf("WHERE (display_applist & %d) = %d "
+ "AND uid = %d", display_applist, display_applist,
+ uid);
+ if (query_where == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_mprintf Failed");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* check count to delete */
+ ret = _get_noti_count(db, query_where, &count);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get count to delete %d", ret);
+ goto err;
+ }
+
+ /* get priv_id, app_id to add deleted_list */
+ if (count > 0 && deleted_list != NULL) {
+ query = sqlite3_mprintf("SELECT priv_id, caller_app_id "
+ "FROM noti_list %s", query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to sqlite3_prepare [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ info = (notification_deleted_list_info_s *)calloc(count,
+ sizeof(notification_deleted_list_info_s));
+ if (info == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ (info + i)->priv_id = sqlite3_column_int(stmt, 0);
+ (info + i)->app_id = notification_db_column_text(stmt, 1);
+ i++;
+ }
+
+ if (query) {
+ sqlite3_free(query);
+ query = NULL;
+ }
+ }
+
+ /* execute main query */
+ query = sqlite3_mprintf("DELETE FROM noti_list %s", query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_mprintf Failed");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto err;
+
+
+ if (deleted_num != NULL)
+ *deleted_num = count;
+
+ if (deleted_list != NULL)
+ *deleted_list = info;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+ if (query_where)
+ sqlite3_free(query_where);
+ if (query)
+ sqlite3_free(query);
+ if (db)
+ notification_db_close(&db);
+
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ if (info != NULL)
+ __free_deleted_list(info, count);
+ }
+
+ return ret;
+}
+
+/* todo refactoring */
+/* LCOV_EXCL_START */
+EXPORT_API int notification_noti_get_count(notification_type_e type,
+ const char *app_id,
+ int group_id, int priv_id,
+ int *count, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ char *query_base = NULL;
+ char *query_where = NULL;
+ char *query_where_more = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int get_count = 0;
+ int internal_group_id = 0;
+ int status = VCONFKEY_TELEPHONY_SIM_UNKNOWN;
+
+ /* Check current sim status */
+ ret = vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &status);
+ if (ret < 0) {
+ status = VCONFKEY_TELEPHONY_SIM_INSERTED;
+ WARN("vconf_get_int");
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query_base = sqlite3_mprintf("SELECT count(*) FROM noti_list ");
+ if (query_base == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+
+ internal_group_id =
+ _notification_noti_get_internal_group_id_by_priv_id(app_id, priv_id, db);
+
+ if (group_id == NOTIFICATION_GROUP_ID_NONE) {
+ if (priv_id == NOTIFICATION_PRIV_ID_NONE)
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND uid = %d ", app_id, uid);
+ else
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND internal_group_id = %d AND uid = %d ",
+ app_id, internal_group_id, uid);
+ } else {
+ if (priv_id == NOTIFICATION_PRIV_ID_NONE)
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND group_id = %d AND uid = %d ",
+ app_id, group_id, uid);
+ else
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND internal_group_id = %d AND uid = %d ",
+ app_id, internal_group_id, uid);
+ }
+
+ if (query_where == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+
+ if (status == VCONFKEY_TELEPHONY_SIM_INSERTED) {
+ if (type != NOTIFICATION_TYPE_NONE) {
+ query_where_more = sqlite3_mprintf("type = %d ", type);
+ if (query_where_more == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+ }
+ } else {
+ if (type != NOTIFICATION_TYPE_NONE)
+ query_where_more = sqlite3_mprintf("type = %d AND "
+ "flag_simmode = 0 ", type);
+ else
+ query_where_more = sqlite3_mprintf("flag_simmode = 0 ");
+
+ if (query_where_more == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+ }
+
+ if (query_where_more) {
+ query = sqlite3_mprintf("%s %s AND %s", query_base, query_where,
+ query_where_more);
+ if (query == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+ } else {
+ query = sqlite3_mprintf("%s %s", query_base, query_where);
+ if (query == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ERR("Failed to sqlite3_prepare_v2[%d][%s]",
+ ret, sqlite3_errmsg(db));
+
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ get_count = sqlite3_column_int(stmt, 0);
+
+ ret = NOTIFICATION_ERROR_NONE;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (query_base)
+ sqlite3_free(query_base);
+
+ if (query_where)
+ sqlite3_free(query_where);
+
+ if (query_where_more)
+ sqlite3_free(query_where_more);
+
+ if (db)
+ notification_db_close(&db);
+
+ *count = get_count;
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_noti_get_all_count(notification_type_e type, int *count, uid_t uid)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *sql_buf = NULL;
+
+ if (count == NULL) {
+ ERR("Invalid parameter - count is null");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ db = notification_db_open();
+ if (db == NULL) {
+ /* LCOV_EXCL_START */
+ ret = get_last_result();
+ ERR("Failed to open db [%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (type != NOTIFICATION_TYPE_NONE)
+ sql_buf = sqlite3_mprintf("SELECT count(*) FROM %q "
+ "WHERE uid = %d AND type = %d",
+ NOTIFICATION_DB_TABLE, uid, type);
+ else
+ sql_buf = sqlite3_mprintf("SELECT count(*) FROM %q WHERE uid = %d",
+ NOTIFICATION_DB_TABLE, uid);
+
+ if (sql_buf == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ ERR("OOM - sqlite3_mprintf");
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_prepare_v2(db, sql_buf, -1, &stmt, NULL);
+ if (sql_ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ ERR("SQLITE3 Error - sqlite3_prepare_v2 [%d][%s]",
+ sql_ret, sqlite3_errmsg(db));
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_step(stmt);
+ if (sql_ret == SQLITE_ROW)
+ *count = sqlite3_column_int(stmt, 0);
+ else
+ *count = 0;
+
+ INFO("The numbers of all notification is [%d]", *count);
+
+out:
+ if (stmt)
+ sqlite3_finalize(stmt);
+ if (sql_buf)
+ sqlite3_free(sql_buf);
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_get_grouping_list(notification_type_e type,
+ int page_number,
+ int count_per_page,
+ notification_list_h *list,
+ int *list_count,
+ uid_t uid)
+{
+ char *query = NULL;
+ char *query_uid = NULL;
+ char *query_where = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int status;
+ int start_index;
+
+ /* Check current sim status */
+ ret = vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &status);
+ if (ret < 0) {
+ status = VCONFKEY_TELEPHONY_SIM_INSERTED;
+ WARN("vconf_get_int");
+ }
+
+ if (status == VCONFKEY_TELEPHONY_SIM_INSERTED) {
+ if (type != NOTIFICATION_TYPE_NONE) {
+ query_where = sqlite3_mprintf(" AND type = %d ", type);
+ if (query_where == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ if (type != NOTIFICATION_TYPE_NONE)
+ query_where = sqlite3_mprintf(" AND type = %d AND "
+ "flag_simmode = 0 ", type);
+ else
+ query_where = sqlite3_mprintf(" AND flag_simmode = 0 ");
+
+ if (query_where == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (uid != NOTIFICATION_GLOBAL_UID) {
+ query_uid = sqlite3_mprintf(" AND uid = %d ", uid);
+ if (query_uid == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ if (count_per_page > 0) {
+ start_index = (page_number - 1) * count_per_page;
+ query = sqlite3_mprintf("noti_list WHERE 1 > 0 %s %s "
+ "ORDER BY rowid DESC, time DESC LIMIT %d,%d",
+ query_where, query_uid, start_index, count_per_page);
+ } else {
+ query = sqlite3_mprintf("noti_list WHERE 1 > 0 %s %s "
+ "ORDER BY rowid DESC, time DESC",
+ query_where, query_uid);
+ count_per_page = -1;
+ }
+
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _get_notification_list(query, list, list_count, count_per_page);
+
+err:
+ if (query_where)
+ sqlite3_free(query_where);
+
+ if (query_uid)
+ sqlite3_free(query_uid);
+
+ if (query)
+ sqlite3_free(query);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_get_detail_list(const char *app_id,
+ int group_id,
+ int priv_id, int count,
+ notification_list_h *list,
+ uid_t uid)
+{
+ char *query_where = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int internal_group_id = 0;
+ int status = 0;
+ sqlite3 *db = NULL;
+
+ /* Check current sim status */
+ ret = vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &status);
+ if (ret < 0) {
+ status = VCONFKEY_TELEPHONY_SIM_INSERTED;
+ WARN("vconf_get_int");
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ if (priv_id == NOTIFICATION_PRIV_ID_NONE &&
+ group_id == NOTIFICATION_GROUP_ID_NONE) {
+ if (status == VCONFKEY_TELEPHONY_SIM_INSERTED)
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND uid = %d ", app_id, uid);
+ else
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND flag_simmode = 0 AND uid = %d ", app_id, uid);
+
+ } else {
+ internal_group_id =
+ _notification_noti_get_internal_group_id_by_priv_id(app_id,
+ priv_id, db);
+
+ if (status == VCONFKEY_TELEPHONY_SIM_INSERTED)
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND internal_group_id = %d AND uid = %d ",
+ app_id, internal_group_id, uid);
+ else
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q "
+ "AND internal_group_id = %d AND flag_simmode = 0 "
+ "AND uid = %d ",
+ app_id, internal_group_id, uid);
+ }
+
+ if (query_where == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ query = sqlite3_mprintf("noti_list %s ORDER BY rowid DESC, time DESC",
+ query_where);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _get_notification_list(query, list, NULL, count);
+
+err:
+ if (query_where)
+ sqlite3_free(query_where);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_check_tag(notification_h noti)
+{
+ sqlite3 *db;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int result = 0;
+
+ if (noti->tag == NULL)
+ return NOTIFICATION_ERROR_NOT_EXIST_ID;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT priv_id FROM noti_list "
+ "WHERE caller_app_id = %Q AND tag = %Q",
+ NOTIFICATION_CHECK_STR(noti->caller_app_id),
+ NOTIFICATION_CHECK_STR(noti->tag));
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to sqlite3_prepare_v2[%d][%s]",
+ ret, sqlite3_errmsg(db));
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ result = sqlite3_column_int(stmt, 0);
+ else
+ result = 0;
+
+ /* If result > 0, there is priv_id in DB */
+ if (result > 0) {
+ noti->priv_id = result;
+ ret = NOTIFICATION_ERROR_ALREADY_EXIST_ID;
+ } else {
+ ret = NOTIFICATION_ERROR_NOT_EXIST_ID;
+ }
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_check_count_for_template(notification_h noti, int *count)
+{
+ sqlite3 *db;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int result = 0;
+
+ if (noti == NULL || count == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT COUNT(caller_app_id) FROM noti_template "
+ "WHERE caller_app_id = %Q",
+ NOTIFICATION_CHECK_STR(noti->caller_app_id));
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to sqlite3_prepare_v2[%d][%s]",
+ ret, sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ result = sqlite3_column_int(stmt, 0);
+ else
+ result = 0;
+
+ *count = result;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_add_template(notification_h noti, char *template_name)
+{
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ int idx = 1;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (noti == NULL || template_name == NULL) {
+ ERR("NOTIFICATION_ERROR_INVALID_PARAMETER");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ /* Initialize private ID */
+ noti->group_id = NOTIFICATION_GROUP_ID_NONE;
+ noti->internal_group_id = NOTIFICATION_GROUP_ID_NONE;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("INSERT OR REPLACE INTO noti_template "
+ "(%s, template_name) VALUES (%s, %Q)",
+ NOTI_LIST_DB_ATTRIBUTES_INSERT,
+ NOTI_LIST_INSERT_VALUES,
+ template_name);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to sqlite3_prepare_v2[%d][%s]",
+ ret, sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = _create_insertion_query(db, noti, stmt, &idx);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto err;
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_OK || ret == SQLITE_DONE)
+ ret = NOTIFICATION_ERROR_NONE;
+ else
+ ret = NOTIFICATION_ERROR_FROM_DB;
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_get_package_template(notification_h noti, char *app_id, char *template_name)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ char *query_where = NULL;
+
+ if (noti == NULL || app_id == NULL || template_name == NULL) {
+ ERR("NOTIFICATION_ERROR_INVALID_PARAMETER");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ query_where = sqlite3_mprintf("noti_template WHERE caller_app_id = %Q "
+ "AND template_name = %Q", app_id, template_name);
+ if (query_where == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+
+ ret = _get_notification(query_where, noti);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ ERR("Failed to get notification [%d]", ret);
+
+ if (query_where)
+ sqlite3_free(query_where);
+
+ return ret;
+}
+
+EXPORT_API int notification_noti_delete_template(const char *pkg_id)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (pkg_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("DELETE FROM noti_template WHERE pkg_id = %Q",
+ NOTIFICATION_CHECK_STR(pkg_id));
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+
+err:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API void notification_noti_init_data(void)
+{
+ int ret;
+ sqlite3 *db = NULL;
+ char *query = NULL;
+
+ db = notification_db_open();
+ if (!db) {
+ ERR("db open");
+ return;
+ }
+
+ query = sqlite3_mprintf("DELETE FROM noti_list WHERE type = %d OR flags_for_property & %d",
+ NOTIFICATION_TYPE_ONGOING, NOTIFICATION_PROP_VOLATILE_DISPLAY);
+ if (!query) {
+ ERR("OOM - sql query");
+ notification_db_close(&db);
+ return;
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ ERR("notification_db_exec");
+
+ sqlite3_free(query);
+ notification_db_close(&db);
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_noti_check_limit(notification_h noti, uid_t uid, GList **list)
+{
+ int ret;
+ int priv_id;
+ int count = 0;
+ char *query = NULL;
+ char *query_where = NULL;
+ sqlite3 *db = NULL;
+ sqlite3_stmt *stmt = NULL;
+
+ if (noti == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query_where = sqlite3_mprintf("WHERE caller_app_id = %Q AND uid = %d ",
+ noti->caller_app_id, uid);
+ if (query_where == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_mprintf Failed");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* check count to delete */
+ ret = _get_noti_count(db, query_where, &count);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ ERR("Failed to get count to delete %d", ret);
+ goto err;
+ }
+
+ /* get priv_id to delete */
+ if (count > NOTI_LIMIT) {
+ count -= NOTI_LIMIT;
+
+ query = sqlite3_mprintf("SELECT priv_id FROM noti_list %s "
+ "AND type = %d ORDER BY insert_time ASC, priv_id ASC",
+ query_where, NOTIFICATION_TYPE_NOTI);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_mprintf Failed");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 Failed [%d][%s]", ret,
+ sqlite3_errmsg(db));
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto err;
+ /* LCOV_EXCL_STOP */
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW && count > 0) {
+ priv_id = sqlite3_column_int(stmt, 0);
+ *list = g_list_append(*list, GINT_TO_POINTER(priv_id));
+ count--;
+ }
+ }
+
+err:
+ if (stmt)
+ sqlite3_finalize(stmt);
+ if (query)
+ sqlite3_free(query);
+ if (query_where)
+ sqlite3_free(query_where);
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
diff --git a/notification/src/notification_ongoing.c b/notification/src/notification_ongoing.c
new file mode 100644
index 0000000..89ee0c9
--- /dev/null
+++ b/notification/src/notification_ongoing.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2000 - 2017 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <notification_db.h>
+#include <notification_debug.h>
+#include <notification_ongoing.h>
+#include <notification_private.h>
+
+#define PATH_NAME "/dbus/signal"
+#define INTERFACE_NAME "notification.ongoing"
+#define MEMBER_PROGRESS "update_progress"
+#define MEMBER_SIZE "update_size"
+#define MEMBER_CONTENT "update_content"
+
+struct _ongoing_update_cb_data {
+ notification_ongoing_update_cb callback;
+ void *data;
+ GDBusConnection *conn;
+ guint subscribe_id;
+};
+
+static struct _ongoing_update_cb_data od;
+
+static void __notification_ongoing_update_callback(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ struct ongoing_info_s *info;
+ char *app_id = NULL;
+ int priv_id = 0;
+ double progress = 0;
+ double size = 0;
+ char *content = NULL;
+
+ info = calloc(1, sizeof(struct ongoing_info_s));
+ if (info == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ return;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (g_strcmp0(signal_name, MEMBER_PROGRESS) == 0) {
+ g_variant_get(parameters, "(&sid)", &app_id, &priv_id, &progress);
+ info->type = ONGOING_TYPE_PROGRESS;
+ } else if (g_strcmp0(signal_name, MEMBER_SIZE) == 0) {
+ g_variant_get(parameters, "(&sid)", &app_id, &priv_id, &size);
+ info->type = ONGOING_TYPE_SIZE;
+ } else if (g_strcmp0(signal_name, MEMBER_CONTENT) == 0) {
+ g_variant_get(parameters, "(&si&s)", &app_id, &priv_id, &content);
+ info->type = ONGOING_TYPE_CONTENT;
+ }
+
+ if (app_id == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("app_id is NULL");
+ free(info);
+ return;
+ /* LCOV_EXCL_STOP */
+ }
+
+ info->pkgname = app_id;
+ info->priv_id = priv_id;
+ info->progress = progress;
+ info->size = size;
+ info->content = content;
+
+ od.callback(info, od.data);
+
+ free(info);
+}
+
+static int __send_ongoing_update_signal(const char *signal_name, GVariant *param)
+{
+ GError *err = NULL;
+ GDBusConnection *conn;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (signal_name == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+ if (conn == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to connect to the D-BUS Daemon[%s]",
+ err->message);
+ ret = NOTIFICATION_ERROR_FROM_DBUS;
+ goto end;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (g_dbus_connection_emit_signal(conn,
+ NULL,
+ PATH_NAME,
+ INTERFACE_NAME,
+ signal_name,
+ param,
+ &err) == FALSE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to emit gdbus signal[%s]",
+ err->message);
+ ret = NOTIFICATION_ERROR_FROM_DBUS;
+ goto end;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (g_dbus_connection_flush_sync(conn, NULL, &err) == FALSE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to flush connection sync[%s]",
+ err->message);
+ ret = NOTIFICATION_ERROR_FROM_DBUS;
+ goto end;
+ /* LCOV_EXCL_STOP */
+ }
+
+
+end:
+ if (err)
+ g_error_free(err);
+
+ if (conn)
+ g_object_unref(conn);
+
+
+ return ret;
+}
+
+EXPORT_API
+int notification_ongoing_update_cb_set(notification_ongoing_update_cb callback,
+ void *user_data)
+{
+ GError *error = NULL;
+
+ if (!callback)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (od.conn == NULL) {
+ od.conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (od.conn == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to connect to the D-BUS Daemon: %s",
+ error->message);
+ g_error_free(error);
+ return NOTIFICATION_ERROR_FROM_DBUS;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ if (!od.subscribe_id) {
+ od.subscribe_id = g_dbus_connection_signal_subscribe(od.conn,
+ NULL,
+ INTERFACE_NAME,
+ NULL,
+ PATH_NAME,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ __notification_ongoing_update_callback,
+ NULL,
+ NULL);
+ if (od.subscribe_id == 0) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to subscribe signal");
+ g_object_unref(od.conn);
+ return NOTIFICATION_ERROR_FROM_DBUS;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ od.callback = callback;
+ od.data = user_data;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API
+int notification_ongoing_update_cb_unset(void)
+{
+ if (od.subscribe_id) {
+ g_dbus_connection_signal_unsubscribe(od.conn, od.subscribe_id);
+ od.subscribe_id = 0;
+ }
+
+ if (od.conn) {
+ g_object_unref(od.conn);
+ od.conn = NULL;
+ }
+
+ od.callback = NULL;
+ od.data = NULL;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_ongoing_update_progress(const char *caller_app_id,
+ int priv_id, double progress)
+{
+ GVariant *param;
+ int ret;
+
+ param = g_variant_new("(sid)", caller_app_id, priv_id, progress);
+
+ ret = __send_ongoing_update_signal(MEMBER_PROGRESS, param);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to update progress[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_ongoing_update_size(const char *caller_app_id,
+ int priv_id, double size)
+{
+ GVariant *param;
+ int ret;
+
+ param = g_variant_new("(sid)", caller_app_id, priv_id, size);
+
+ ret = __send_ongoing_update_signal(MEMBER_SIZE, param);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to update size[%d]", ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_ongoing_update_content(const char *caller_app_id,
+ int priv_id, const char *content)
+{
+ GVariant *param;
+ int ret;
+
+ param = g_variant_new("(sis)", caller_app_id, priv_id, content);
+
+ ret = __send_ongoing_update_signal(MEMBER_CONTENT, param);
+ if (ret != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to update content[%d]",
+ ret);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+ return NOTIFICATION_ERROR_NONE;
+}
diff --git a/notification/src/notification_setting.c b/notification/src/notification_setting.c
new file mode 100644
index 0000000..6be851f
--- /dev/null
+++ b/notification/src/notification_setting.c
@@ -0,0 +1,1125 @@
+/*
+ * Copyright (c) 2000 - 2017 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <package_manager.h>
+#include <pkgmgr-info.h>
+#include <tizen_type.h>
+#include <tzplatform_config.h>
+
+#include <notification.h>
+#include <notification_db.h>
+#include <notification_list.h>
+#include <notification_noti.h>
+#include <notification_debug.h>
+#include <notification_ipc.h>
+#include <notification_private.h>
+#include <notification_setting.h>
+#include <notification_setting_internal.h>
+#include "notification_db_query.h"
+
+#define NOTIFICATION_PRIVILEGE "http://tizen.org/privilege/notification"
+
+typedef struct _noti_dnd_cb_info noti_dnd_cb_info_s;
+
+typedef struct {
+ uid_t uid;
+ sqlite3 *db;
+} setting_local_info;
+
+struct _noti_dnd_cb_info {
+ dnd_changed_cb callback;
+ void *user_data;
+};
+
+static GHashTable *_noti_dnd_cb_hash = NULL;
+
+EXPORT_API int notification_setting_get_setting_array_for_uid(notification_setting_h *setting_array, int *count, uid_t uid)
+{
+ if (setting_array == NULL || count == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return notification_ipc_request_get_setting_array(setting_array, count, uid);
+}
+
+EXPORT_API int notification_setting_get_setting_array(notification_setting_h *setting_array, int *count)
+{
+ return notification_setting_get_setting_array_for_uid(setting_array, count, getuid());
+}
+
+EXPORT_API int notification_setting_get_setting_by_appid_for_uid(const char *app_id, notification_setting_h *setting, uid_t uid)
+{
+ if (app_id == NULL || setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return notification_ipc_request_get_setting_by_app_id(app_id, setting, uid);
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_setting_get_setting_by_package_name(const char *package_name, notification_setting_h *setting)
+{
+ return notification_setting_get_setting_by_appid_for_uid(package_name, setting, getuid());
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_setting_get_setting(notification_setting_h *setting)
+{
+ int ret;
+ char *app_id = NULL;
+
+ app_id = notification_get_app_id_by_pid(getpid());
+ if (app_id == NULL)
+ return NOTIFICATION_ERROR_NOT_EXIST_ID;
+
+ ret = notification_setting_get_setting_by_package_name(app_id, setting);
+
+ free(app_id);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_setting_get_package_name(notification_setting_h setting, char **value)
+{
+ if (setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (setting->package_name == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("setting->package_name is null");
+ return NOTIFICATION_ERROR_NOT_EXIST_ID;
+ /* LCOV_EXCL_STOP */
+ }
+
+ *value = SAFE_STRDUP(setting->package_name);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_get_appid(notification_setting_h setting, char **app_id)
+{
+ if (setting == NULL || app_id == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (setting->app_id == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("setting->app_id is null");
+ return NOTIFICATION_ERROR_NOT_EXIST_ID;
+ /* LCOV_EXCL_STOP */
+ }
+
+ *app_id = SAFE_STRDUP(setting->app_id);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_get_allow_to_notify(notification_setting_h setting, bool *value)
+{
+ if (setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = setting->allow_to_notify;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_set_allow_to_notify(notification_setting_h setting, bool value)
+{
+ if (setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ setting->allow_to_notify = value;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_get_do_not_disturb_except(notification_setting_h setting, bool *value)
+{
+ if (setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = setting->do_not_disturb_except;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_set_do_not_disturb_except(notification_setting_h setting, bool value)
+{
+ if (setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ setting->do_not_disturb_except = value;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_get_visibility_class(notification_setting_h setting, int *value)
+{
+ if (setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = setting->visibility_class;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_set_visibility_class(notification_setting_h setting, int value)
+{
+ if (setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ setting->visibility_class = value;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_get_pop_up_notification(notification_setting_h setting, bool *value)
+{
+ if (setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = setting->pop_up_notification;
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_set_pop_up_notification(notification_setting_h setting, bool value)
+{
+ if (setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ setting->pop_up_notification = value;
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_get_lock_screen_content(notification_setting_h setting, lock_screen_content_level_e *level)
+{
+ if (setting == NULL || level == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *level = setting->lock_screen_content_level;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_set_lock_screen_content(notification_setting_h setting, lock_screen_content_level_e level)
+{
+ if (setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ setting->lock_screen_content_level = level;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_get_app_disabled(notification_setting_h setting, bool *value)
+{
+ if (setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = setting->app_disabled;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_setting_update_setting_for_uid(notification_setting_h setting, uid_t uid)
+{
+ if (setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return notification_ipc_update_setting(setting, uid);
+}
+
+EXPORT_API int notification_setting_update_setting(notification_setting_h setting)
+{
+ return notification_setting_update_setting_for_uid(setting, getuid());
+}
+
+EXPORT_API int notification_setting_free_notification(notification_setting_h setting)
+{
+ if (setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ SAFE_FREE(setting->package_name);
+ SAFE_FREE(setting->app_id);
+
+ /* add codes to free all properties */
+
+ SAFE_FREE(setting);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static bool _is_package_in_setting_table(sqlite3 *db, const char *package_name,
+ const char *app_id, uid_t uid)
+{
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ int sql_ret;
+ bool err = true;
+
+ if (app_id != NULL)
+ query = sqlite3_mprintf("SELECT app_id FROM %s WHERE uid = %d "
+ "AND package_name = %Q AND app_id = %Q",
+ NOTIFICATION_SETTING_DB_TABLE,
+ uid, package_name, app_id);
+ else
+ query = sqlite3_mprintf("SELECT package_name FROM %s "
+ "WHERE uid = %d AND package_name = %Q",
+ NOTIFICATION_SETTING_DB_TABLE,
+ uid, package_name);
+
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("fail to alloc query");
+ return false;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (sql_ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_prepare_v2 failed [%d][%s]", sql_ret,
+ sqlite3_errmsg(db));
+ err = false;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_step(stmt);
+ if (sql_ret == SQLITE_DONE) {
+ INFO("No matched [%s] from package_name [%s], [%d]",
+ app_id, package_name, sql_ret);
+ err = false;
+ goto out;
+ }
+
+ if (sql_ret != SQLITE_OK && sql_ret != SQLITE_ROW) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_step failed [%d][%s]", sql_ret,
+ sqlite3_errmsg(db));
+ err = false;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+out:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ return err;
+}
+
+static int _foreach_app_info_callback(const pkgmgrinfo_appinfo_h handle,
+ void *user_data)
+{
+ setting_local_info *info = (setting_local_info *)user_data;
+ sqlite3 *db = info->db;
+ char *query = NULL;
+ int ret;
+ int err = true;
+ char *app_id = NULL;
+ char *package_name = NULL;
+
+ ret = pkgmgrinfo_appinfo_get_appid(handle, &app_id);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get appid from pkgmgrinfo [%d]",
+ ret);
+ err = false;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = pkgmgrinfo_appinfo_get_pkgname(handle, &package_name);
+ if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get pkgname from pkgmgrinfo[%d]",
+ ret);
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (_is_package_in_setting_table(db, package_name, app_id, info->uid) == true) {
+ INFO("uid %d [%s] is exist", info->uid, app_id);
+ err = false;
+ goto out;
+ }
+
+ query = sqlite3_mprintf("INSERT INTO %s (uid, package_name, app_id) "
+ "VALUES (%d, %Q, %Q) ",
+ NOTIFICATION_SETTING_DB_TABLE,
+ info->uid, package_name, app_id);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("fail to alloc query");
+ err = false;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ err = false;
+ else
+ INFO("uid [%d] package_name [%s] appid [%s] is inserted",
+ info->uid, package_name, app_id);
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ return err;
+}
+
+static int _install_and_update_package(const char *package_name, uid_t uid)
+{
+ sqlite3 *db;
+ int err = NOTIFICATION_ERROR_NONE;
+ int pkgmgr_ret;
+ setting_local_info info;
+ pkgmgrinfo_appinfo_filter_h handle = NULL;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ pkgmgr_ret = pkgmgrinfo_appinfo_filter_create(&handle);
+ if (pkgmgr_ret != PMINFO_R_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to create appinfo_filter[%d]", pkgmgr_ret);
+ err = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ pkgmgr_ret = pkgmgrinfo_appinfo_filter_add_string(handle,
+ PMINFO_APPINFO_PROP_PRIVILEGE, NOTIFICATION_PRIVILEGE);
+ if (pkgmgr_ret != PMINFO_R_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to add string to appinfo_filter[%d]", pkgmgr_ret);
+ err = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ pkgmgr_ret = pkgmgrinfo_appinfo_filter_add_string(handle,
+ PMINFO_APPINFO_PROP_APP_PACKAGE, package_name);
+ if (pkgmgr_ret != PMINFO_R_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to add string to appinfo_filter[%d]", pkgmgr_ret);
+ err = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ info.db = db;
+ info.uid = uid;
+ pkgmgr_ret = pkgmgrinfo_appinfo_usr_filter_foreach_appinfo(handle,
+ _foreach_app_info_callback, &info, uid);
+ if (pkgmgr_ret != PMINFO_R_OK) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to iterate appinfo[%d]", pkgmgr_ret);
+ err = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+out:
+ if (handle)
+ pkgmgrinfo_appinfo_filter_destroy(handle);
+
+ if (db)
+ notification_db_close(&db);
+
+ return err;
+}
+
+static int _delete_package_from_setting_db(const char *package_name, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int err = NOTIFICATION_ERROR_NONE;
+ bool is_package_in_setting_table = false;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ is_package_in_setting_table = _is_package_in_setting_table(db,
+ package_name, NULL, uid);
+ if (is_package_in_setting_table == false) {
+ INFO("[%s] is not exist", package_name);
+ goto out;
+ }
+
+ query = sqlite3_mprintf("DELETE FROM %s WHERE uid = %d "
+ "AND package_name = %Q ",
+ NOTIFICATION_SETTING_DB_TABLE, uid,
+ package_name);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc query");
+ err = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ err = notification_db_exec(db, query, NULL);
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return err;
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_setting_refresh_setting_table(uid_t uid)
+{
+ int err = NOTIFICATION_ERROR_NONE;
+ sqlite3 *db = NULL;
+ int pkgmgr_ret;
+ pkgmgrinfo_appinfo_filter_h filter = NULL;
+ setting_local_info info;
+
+ INFO("Refresh setting table [%d]", uid);
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ pkgmgr_ret = pkgmgrinfo_appinfo_filter_create(&filter);
+ if (pkgmgr_ret != PMINFO_R_OK) {
+ ERR("Failed to create appinfo_filter[%d]", pkgmgr_ret);
+ err = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ pkgmgr_ret = pkgmgrinfo_appinfo_filter_add_string(filter,
+ PMINFO_APPINFO_PROP_PRIVILEGE, NOTIFICATION_PRIVILEGE);
+ if (pkgmgr_ret != PMINFO_R_OK) {
+ ERR("Failed to add string to appinfo_filter[%d]", pkgmgr_ret);
+ err = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ info.db = db;
+ info.uid = uid;
+ pkgmgr_ret = pkgmgrinfo_appinfo_usr_filter_foreach_appinfo(filter,
+ _foreach_app_info_callback, &info, uid);
+ if (pkgmgr_ret != PMINFO_R_OK) {
+ ERR("Failed to foreach appinfo[%d]", pkgmgr_ret);
+ err = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+out:
+ if (filter)
+ pkgmgrinfo_appinfo_filter_destroy(filter);
+
+ if (db)
+ notification_db_close(&db);
+
+ return err;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_setting_insert_package_for_uid(const char *package_name, uid_t uid)
+{
+ return _install_and_update_package(package_name, uid);
+}
+
+EXPORT_API int notification_setting_delete_package_for_uid(const char *package_name, uid_t uid)
+{
+ return _delete_package_from_setting_db(package_name, uid);
+}
+
+EXPORT_API int notification_system_setting_load_system_setting_for_uid(notification_system_setting_h *system_setting, uid_t uid)
+{
+ if (system_setting == NULL) {
+ ERR("NOTIFICATION_ERROR_INVALID_PARAMETER");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return notification_ipc_request_load_system_setting(system_setting, uid);
+}
+
+EXPORT_API int notification_system_setting_load_system_setting(notification_system_setting_h *system_setting)
+{
+ return notification_system_setting_load_system_setting_for_uid(system_setting, getuid());
+}
+
+EXPORT_API int notification_system_setting_update_system_setting_for_uid(notification_system_setting_h system_setting, uid_t uid)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return notification_ipc_update_system_setting(system_setting, uid);
+}
+
+EXPORT_API int notification_system_setting_update_system_setting(notification_system_setting_h system_setting)
+{
+ return notification_system_setting_update_system_setting_for_uid(system_setting, getuid());
+}
+
+EXPORT_API int notification_system_setting_free_system_setting(notification_system_setting_h system_setting)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ /* add codes to free all properties */
+
+ if (system_setting->dnd_allow_exceptions != NULL)
+ g_list_free_full(system_setting->dnd_allow_exceptions, free);
+
+ SAFE_FREE(system_setting);
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_get_do_not_disturb(notification_system_setting_h system_setting, bool *value)
+{
+ if (system_setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = system_setting->do_not_disturb;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_set_do_not_disturb(notification_system_setting_h system_setting, bool value)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ system_setting->do_not_disturb = value;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_get_visibility_class(notification_system_setting_h system_setting, int *value)
+{
+ if (system_setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = system_setting->visibility_class;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_set_visibility_class(notification_system_setting_h system_setting, int value)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ system_setting->visibility_class = value;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_get_enabled(notification_system_setting_h system_setting, bool *enabled)
+{
+ if (system_setting == NULL || enabled == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *enabled = system_setting->dnd_schedule_enabled;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_set_enabled(notification_system_setting_h system_setting, bool enabled)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ system_setting->dnd_schedule_enabled = enabled;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_get_day(notification_system_setting_h system_setting, int *day)
+{
+ if (system_setting == NULL || day == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *day = system_setting->dnd_schedule_day;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_set_day(notification_system_setting_h system_setting, int day)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ system_setting->dnd_schedule_day = day;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_get_start_time(notification_system_setting_h system_setting, int *hour, int *min)
+{
+ if (system_setting == NULL || hour == NULL || min == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *hour = system_setting->dnd_start_hour;
+ *min = system_setting->dnd_start_min;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_set_start_time(notification_system_setting_h system_setting, int hour, int min)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ system_setting->dnd_start_hour = hour;
+ system_setting->dnd_start_min = min;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_get_end_time(notification_system_setting_h system_setting, int *hour, int *min)
+{
+ if (system_setting == NULL || hour == NULL || min == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *hour = system_setting->dnd_end_hour;
+ *min = system_setting->dnd_end_min;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_dnd_schedule_set_end_time(notification_system_setting_h system_setting, int hour, int min)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ system_setting->dnd_end_hour = hour;
+ system_setting->dnd_end_min = min;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_get_lock_screen_content(notification_system_setting_h system_setting, lock_screen_content_level_e *level)
+{
+ if (system_setting == NULL || level == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ *level = system_setting->lock_screen_content_level;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_set_lock_screen_content(notification_system_setting_h system_setting, lock_screen_content_level_e level)
+{
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ system_setting->lock_screen_content_level = level;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static gint _dnd_allow_exception_compare(gconstpointer a, gconstpointer b)
+{
+ dnd_allow_exception_h dnd_allow_exception_data_a;
+
+ if (a == NULL)
+ return -1;
+
+ dnd_allow_exception_data_a = (dnd_allow_exception_h)a;
+
+ if (dnd_allow_exception_data_a->type == GPOINTER_TO_INT(b))
+ return 0;
+
+ return -1;
+}
+
+EXPORT_API int notification_system_setting_get_dnd_allow_exceptions(notification_system_setting_h system_setting, dnd_allow_exception_type_e type, int *value)
+{
+ dnd_allow_exception_h dnd_allow_exception_data;
+ GList *list;
+
+ if (system_setting == NULL || value == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ list = g_list_find_custom(system_setting->dnd_allow_exceptions, GINT_TO_POINTER(type), (GCompareFunc)_dnd_allow_exception_compare);
+ if (list) {
+ dnd_allow_exception_data = (dnd_allow_exception_h)list->data;
+ *value = dnd_allow_exception_data->value;
+ } else {
+ ERR("Invalid type");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_system_setting_set_dnd_allow_exceptions(notification_system_setting_h system_setting, dnd_allow_exception_type_e type, int value)
+{
+ dnd_allow_exception_h dnd_allow_exception_data;
+ GList *list = NULL;
+
+ if (system_setting == NULL) {
+ ERR("Invalid parameter");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ list = g_list_first(system_setting->dnd_allow_exceptions);
+ list = g_list_find_custom(list, GINT_TO_POINTER(type), (GCompareFunc)_dnd_allow_exception_compare);
+
+ if (list) {
+ dnd_allow_exception_data = (dnd_allow_exception_h)list->data;
+ dnd_allow_exception_data->value = value;
+ } else {
+ dnd_allow_exception_data = (dnd_allow_exception_h)malloc(sizeof(struct notification_system_setting_dnd_allow_exception));
+ if (dnd_allow_exception_data == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+
+ dnd_allow_exception_data->type = type;
+ dnd_allow_exception_data->value = value;
+ system_setting->dnd_allow_exceptions = g_list_append(list, dnd_allow_exception_data);
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+static gint _noti_dnd_cb_compare(gconstpointer a, gconstpointer b)
+{
+ noti_dnd_cb_info_s *info = NULL;
+
+ if (a == NULL)
+ return -1;
+
+ info = (noti_dnd_cb_info_s *)a;
+ if (info->callback == b)
+ return 0;
+
+ return 1;
+}
+
+/* LCOV_EXCL_START */
+void notification_call_dnd_changed_cb_for_uid(int do_not_disturb, uid_t uid)
+{
+ GList *noti_dnd_cb_list = NULL;
+ noti_dnd_cb_info_s *dnd_data = NULL;
+
+ if (_noti_dnd_cb_hash == NULL)
+ return;
+
+ noti_dnd_cb_list = (GList *)g_hash_table_lookup(_noti_dnd_cb_hash, GUINT_TO_POINTER(uid));
+ if (noti_dnd_cb_list == NULL) {
+ ERR("Invalid data");
+ return;
+ }
+
+ noti_dnd_cb_list = g_list_first(noti_dnd_cb_list);
+
+ for (; noti_dnd_cb_list != NULL; noti_dnd_cb_list = noti_dnd_cb_list->next) {
+ dnd_data = noti_dnd_cb_list->data;
+
+ if (dnd_data != NULL && dnd_data->callback != NULL)
+ dnd_data->callback(dnd_data->user_data, do_not_disturb);
+ }
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API int notification_register_system_setting_dnd_changed_cb_for_uid(dnd_changed_cb callback, void *user_data, uid_t uid)
+{
+ GList *noti_dnd_list = NULL;
+ GList *noti_dnd_found_list = NULL;
+ noti_dnd_cb_info_s *dnd_data = NULL;
+
+ if (callback == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (notification_ipc_monitor_init(uid) != NOTIFICATION_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to init monitor");
+ return NOTIFICATION_ERROR_IO_ERROR;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (_noti_dnd_cb_hash == NULL)
+ _noti_dnd_cb_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+ dnd_data = (noti_dnd_cb_info_s *)malloc(sizeof(noti_dnd_cb_info_s));
+ if (dnd_data == NULL)
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+
+ dnd_data->callback = callback;
+ dnd_data->user_data = user_data;
+
+ noti_dnd_list = (GList *)g_hash_table_lookup(_noti_dnd_cb_hash, GUINT_TO_POINTER(uid));
+
+ if (noti_dnd_list == NULL) {
+ noti_dnd_list = g_list_append(noti_dnd_list, dnd_data);
+ g_hash_table_insert(_noti_dnd_cb_hash, GUINT_TO_POINTER(uid), noti_dnd_list);
+ } else {
+ noti_dnd_found_list = g_list_find_custom(noti_dnd_list, (gconstpointer)callback,
+ (GCompareFunc)_noti_dnd_cb_compare);
+ if (noti_dnd_found_list) {
+ ERR("Already existing callback");
+ free(dnd_data);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ noti_dnd_list = g_list_append(noti_dnd_list, dnd_data);
+ }
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_register_system_setting_dnd_changed_cb(dnd_changed_cb callback, void *user_data)
+{
+ return notification_register_system_setting_dnd_changed_cb_for_uid(callback, user_data, getuid());
+}
+
+EXPORT_API int notification_unregister_system_setting_dnd_changed_cb_for_uid(dnd_changed_cb callback, uid_t uid)
+{
+ GList *noti_dnd_cb_list = NULL;
+ GList *noti_dnd_del_list = NULL;
+ noti_dnd_cb_info_s *dnd_data = NULL;
+
+ if (callback == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (_noti_dnd_cb_hash == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti_dnd_cb_list = (GList *)g_hash_table_lookup(_noti_dnd_cb_hash, GUINT_TO_POINTER(uid));
+
+ if (noti_dnd_cb_list == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ noti_dnd_del_list = g_list_find_custom(noti_dnd_cb_list, (gconstpointer)callback,
+ (GCompareFunc)_noti_dnd_cb_compare);
+
+ if (noti_dnd_del_list) {
+ dnd_data = g_list_nth_data(noti_dnd_del_list, 0);
+ noti_dnd_cb_list = g_list_delete_link(noti_dnd_cb_list, noti_dnd_del_list);
+ free(dnd_data);
+ } else {
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ if (noti_dnd_cb_list == NULL) {
+ g_hash_table_steal(_noti_dnd_cb_hash, GUINT_TO_POINTER(uid));
+ } else {
+ noti_dnd_cb_list = g_list_first(noti_dnd_cb_list);
+ g_hash_table_replace(_noti_dnd_cb_hash, GUINT_TO_POINTER(uid), noti_dnd_cb_list);
+ }
+
+ if (g_hash_table_size(_noti_dnd_cb_hash) == 0)
+ notification_ipc_monitor_fini();
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API int notification_unregister_system_setting_dnd_changed_cb(dnd_changed_cb callback)
+{
+ return notification_unregister_system_setting_dnd_changed_cb_for_uid(callback, getuid());
+}
+
+/* LCOV_EXCL_START */
+static bool _is_uid_in_system_setting_table(sqlite3 *db, uid_t uid)
+{
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ int sql_ret;
+ bool err = true;
+
+ query = sqlite3_mprintf("SELECT uid FROM %s WHERE uid = %d",
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE, uid);
+ if (query == NULL) {
+ ERR("Failed to alloc query");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ sql_ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
+ if (sql_ret != SQLITE_OK) {
+ ERR("sqlite3_prepare_v2 failed [%d][%s]", sql_ret,
+ sqlite3_errmsg(db));
+ err = false;
+ goto out;
+ }
+
+ sql_ret = sqlite3_step(stmt);
+ if (sql_ret == SQLITE_DONE) {
+ INFO("No matched uid[%d] err[%d]", uid, sql_ret);
+ err = false;
+ goto out;
+ }
+
+ if (sql_ret != SQLITE_OK && sql_ret != SQLITE_ROW) {
+ ERR("sqlite3_step failed [%d][%s]",
+ sql_ret, sqlite3_errmsg(db));
+ err = false;
+ }
+
+out:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (query)
+ sqlite3_free(query);
+
+ return err;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_system_setting_init_system_setting_table(uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query_system_setting = NULL;
+ char *query_dnd_allow_exception = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ INFO("init system setting table [%d]", uid);
+
+ db = notification_db_open();
+ if (db == NULL)
+ return get_last_result();
+
+ if (_is_uid_in_system_setting_table(db, uid) == true) {
+ INFO("Setting table is already initialized.");
+ goto out;
+ }
+
+ /* notification_system_setting */
+ query_system_setting = sqlite3_mprintf("INSERT INTO %s (uid) "
+ "VALUES (%d) ",
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE,
+ uid);
+ if (query_system_setting == NULL) {
+ ERR("fail to alloc query");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = notification_db_exec(db, query_system_setting, NULL);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto out;
+
+ /* dnd_allow_exception */
+ query_dnd_allow_exception = sqlite3_mprintf("INSERT INTO %s "
+ "(uid) VALUES (%d) ",
+ NOTIFICATION_DND_ALLOW_EXCEPTION,
+ uid);
+ if (query_dnd_allow_exception == NULL) {
+ ERR("Failed to alloc query");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = notification_db_exec(db, query_dnd_allow_exception, NULL);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto out;
+
+ DBG("Initialization is success.");
+
+out:
+ if (query_system_setting)
+ sqlite3_free(query_system_setting);
+
+ if (query_dnd_allow_exception)
+ sqlite3_free(query_dnd_allow_exception);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
diff --git a/notification/src/notification_setting_service.c b/notification/src/notification_setting_service.c
new file mode 100644
index 0000000..7faee55
--- /dev/null
+++ b/notification/src/notification_setting_service.c
@@ -0,0 +1,931 @@
+/*
+ * Copyright (c) 2000 - 2017 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.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <sqlite3.h>
+#include <tizen.h>
+
+#include <notification.h>
+#include <notification_db.h>
+#include <notification_error.h>
+#include <notification_debug.h>
+#include <notification_private.h>
+#include <notification_setting.h>
+#include <notification_setting_internal.h>
+#include <notification_setting_service.h>
+#include "notification_db_query.h"
+
+static int _get_table_field_data_int(char **table, int *buf, int index)
+{
+ if (table == NULL || buf == NULL || index < 0) {
+ /* LCOV_EXCL_START */
+ ERR("table[%p], buf[%p], index[%d]", table, buf, index);
+ return false;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (table[index] != NULL) {
+ *buf = atoi(table[index]);
+ return true;
+ }
+
+ /* LCOV_EXCL_START */
+ *buf = 0;
+ return false;
+ /* LCOV_EXCL_STOP */
+}
+
+static int _get_table_field_data_string(char **table, char **buf, int ucs2, int index)
+{
+ int ret = false;
+ int sLen = 0;
+ char *pTemp;
+
+ if (table == NULL || buf == NULL || index < 0) {
+ /* LCOV_EXCL_START */
+ ERR("table[%p], buf[%p], index[%d]", table, buf, index);
+ return false;
+ /* LCOV_EXCL_STOP */
+ }
+
+ pTemp = table[index];
+
+ if (pTemp == NULL) {
+ *buf = NULL; /* LCOV_EXCL_LINE */
+ } else {
+ sLen = strlen(pTemp);
+ if (sLen) {
+ *buf = (char *)malloc(sLen + 1);
+ if (*buf == NULL) {
+ ERR("Failed to alloc memory"); /* LCOV_EXCL_LINE */
+ goto out;
+ }
+ memset(*buf, 0, sLen + 1);
+ strncpy(*buf, pTemp, sLen);
+ } else {
+ *buf = NULL; /* LCOV_EXCL_LINE */
+ }
+ }
+
+ ret = true;
+
+out:
+ return ret;
+}
+
+EXPORT_API
+int noti_setting_service_get_setting_by_app_id(const char *app_id, notification_setting_h *setting, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ char **query_result = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ int row_count = 0;
+ int column_count = 0;
+ int i = 0;
+ int col_index = 0;
+ notification_setting_h result_setting_array = NULL;
+
+ if (app_id == NULL || setting == NULL) {
+ ERR("Invalid parameter"); /* LCOV_EXCL_LINE */
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT %s FROM %s WHERE app_id = %Q AND uid = %d",
+ NOTIFICATION_SETTING_DB_ATTRIBUTES, NOTIFICATION_SETTING_DB_TABLE,
+ app_id, uid);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc query");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_get_table(db, query, &query_result, &row_count, &column_count, NULL);
+ if (sql_ret != SQLITE_OK && sql_ret != -1) {
+ /* LCOV_EXCL_START */
+ ERR("sqlite3_get_table failed [%d][%s]", sql_ret,
+ query);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (!row_count) {
+ DBG("No setting found for [%s]", app_id);
+ ret = NOTIFICATION_ERROR_NOT_EXIST_ID;
+ goto out;
+ }
+
+ DBG("row_count[%d] column_count[%d]", row_count, column_count);
+
+ row_count = 1;
+
+ result_setting_array = (struct notification_setting *)malloc(sizeof(struct notification_setting) * row_count);
+ if (result_setting_array == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ col_index = column_count;
+
+ _get_table_field_data_string(query_result, &(result_setting_array[i].package_name), 1, col_index++);
+ _get_table_field_data_string(query_result, &(result_setting_array[i].app_id), 1, col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].allow_to_notify), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].do_not_disturb_except), col_index++);
+ _get_table_field_data_int(query_result, &(result_setting_array[i].visibility_class), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].pop_up_notification), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].lock_screen_content_level), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].app_disabled), col_index++);
+
+ *setting = result_setting_array;
+
+out:
+ if (query_result)
+ sqlite3_free_table(query_result);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API
+int noti_setting_get_setting_array(notification_setting_h *setting_array, int *count, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ char **query_result = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ int row_count = 0;
+ int column_count = 0;
+ int i = 0;
+ int col_index = 0;
+ notification_setting_h result_setting_array = NULL;
+
+ if (setting_array == NULL || count == NULL) {
+ ERR("NOTIFICATION_ERROR_INVALID_PARAMETER"); /* LCOV_EXCL_LINE */
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT %s FROM %s WHERE uid = %d "
+ "AND app_disabled = %d ORDER BY package_name, "
+ "app_id ", NOTIFICATION_SETTING_DB_ATTRIBUTES,
+ NOTIFICATION_SETTING_DB_TABLE, uid, 0);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc query"); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_get_table(db, query, &query_result, &row_count, &column_count, NULL);
+ if (sql_ret != SQLITE_OK && sql_ret != -1) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get db table [%d][%s]",
+ sql_ret, query); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (!row_count) {
+ DBG("No setting found"); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_NOT_EXIST_ID;
+ goto out;
+ }
+
+ DBG("row_count[%d] column_count[%d]", row_count, column_count);
+
+ result_setting_array = (struct notification_setting *)malloc(sizeof(struct notification_setting) * row_count);
+ if (result_setting_array == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory"); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ col_index = column_count;
+
+ for (i = 0; i < row_count; i++) {
+ _get_table_field_data_string(query_result, &(result_setting_array[i].package_name), 1, col_index++);
+ _get_table_field_data_string(query_result, &(result_setting_array[i].app_id), 1, col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].allow_to_notify), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].do_not_disturb_except), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].visibility_class), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].pop_up_notification), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].lock_screen_content_level), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_setting_array[i].app_disabled), col_index++);
+ }
+
+ *setting_array = result_setting_array;
+ *count = row_count;
+
+out:
+ if (query_result)
+ sqlite3_free_table(query_result);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+
+EXPORT_API
+int noti_system_setting_load_system_setting(notification_system_setting_h *system_setting, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ char **query_result = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ int row_count = 0;
+ int column_count = 0;
+ int col_index = 0;
+ notification_system_setting_h result_system_setting = NULL;
+
+ if (system_setting == NULL) {
+ ERR("Invalid parameter"); /* LCOV_EXCL_LINE */
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT %s FROM %s WHERE uid = %d",
+ NOTIFICATION_SYSTEM_SETTING_DB_ATTRIBUTES,
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE, uid);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc query");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_get_table(db, query, &query_result, &row_count, &column_count, NULL);
+ if (sql_ret != SQLITE_OK && sql_ret != -1) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get db table [%d][%s]", sql_ret, query);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ DBG("row_count [%d] column_count [%d]", row_count, column_count);
+
+ result_system_setting = (struct notification_system_setting *)malloc(sizeof(struct notification_system_setting));
+ if (result_system_setting == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* no system setting record. allow everyting */
+ if (!row_count) {
+ /* LCOV_EXCL_START */
+ DBG("No setting found");
+ result_system_setting->do_not_disturb = 0;
+ result_system_setting->visibility_class = 0;
+ result_system_setting->dnd_schedule_enabled = 0;
+ result_system_setting->dnd_schedule_day = 0;
+ result_system_setting->dnd_start_hour = 0;
+ result_system_setting->dnd_start_min = 0;
+ result_system_setting->dnd_end_hour = 0;
+ result_system_setting->dnd_end_min = 0;
+ result_system_setting->lock_screen_content_level = 0;
+ result_system_setting->dnd_allow_exceptions = NULL;
+ /* LCOV_EXCL_STOP */
+ } else {
+ /* LCOV_EXCL_START */
+ col_index = column_count;
+ _get_table_field_data_int(query_result, (int *)&(result_system_setting->do_not_disturb), col_index++);
+ _get_table_field_data_int(query_result, &(result_system_setting->visibility_class), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_system_setting->dnd_schedule_enabled), col_index++);
+ _get_table_field_data_int(query_result, &(result_system_setting->dnd_schedule_day), col_index++);
+ _get_table_field_data_int(query_result, &(result_system_setting->dnd_start_hour), col_index++);
+ _get_table_field_data_int(query_result, &(result_system_setting->dnd_start_min), col_index++);
+ _get_table_field_data_int(query_result, &(result_system_setting->dnd_end_hour), col_index++);
+ _get_table_field_data_int(query_result, &(result_system_setting->dnd_end_min), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(result_system_setting->lock_screen_content_level), col_index++);
+ result_system_setting->dnd_allow_exceptions = NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ *system_setting = result_system_setting;
+
+out:
+ if (query_result)
+ sqlite3_free_table(query_result);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API
+int notification_setting_db_update(const char *package_name, const char *app_id,
+ int allow_to_notify, int do_not_disturb_except,
+ int visibility_class, int pop_up_notification,
+ int lock_screen_content_level, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (package_name == NULL || app_id == NULL) {
+ ERR("Invalid paramter"); /* LCOV_EXCL_LINE */
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("UPDATE %s SET allow_to_notify = %d, "
+ "do_not_disturb_except = %d, visibility_class = %d, "
+ "pop_up_notification = %d, lock_screen_content_level = %d "
+ "WHERE app_id = %Q AND package_name = %Q AND uid = %d ",
+ NOTIFICATION_SETTING_DB_TABLE, allow_to_notify,
+ do_not_disturb_except, visibility_class,
+ pop_up_notification, lock_screen_content_level, app_id,
+ package_name, uid);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API
+int notification_setting_db_update_system_setting(int do_not_disturb, int visibility_class,
+ int dnd_schedule_enabled, int dnd_schedule_day,
+ int dnd_start_hour, int dnd_start_min,
+ int dnd_end_hour, int dnd_end_min,
+ int lock_screen_content_level, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int num_changes = 0;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("INSERT OR REPLACE INTO %s (uid, %s) "
+ "VALUES(%d, %d, %d, %d, %d, %d, %d, %d, %d, %d) ",
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE,
+ NOTIFICATION_SYSTEM_SETTING_DB_ATTRIBUTES,
+ uid, do_not_disturb, visibility_class,
+ dnd_schedule_enabled, dnd_schedule_day, dnd_start_hour,
+ dnd_start_min, dnd_end_hour, dnd_end_min,
+ lock_screen_content_level);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, &num_changes);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto out;
+
+ if (num_changes == 0)
+ WARN("No changes on DB");
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API
+int notification_setting_db_update_do_not_disturb(int do_not_disturb, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("UPDATE %s SET do_not_disturb = %d "
+ "WHERE uid = %d",
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE,
+ do_not_disturb, uid);
+ if (query == NULL) {
+ ERR("Failed to alloc query");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = notification_db_exec(db, query, NULL);
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API
+int notification_system_setting_get_dnd_schedule_enabled_uid(uid_t **uids, int *count)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ int i;
+ int row_count = 0;
+ int column_count = 0;
+ int column_index = 0;
+ char *query = NULL;
+ char **query_result = NULL;
+ sqlite3 *db = NULL;
+ uid_t *result_uids;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT uid FROM %s "
+ "WHERE dnd_schedule_enabled = 1",
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE);
+ if (query == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = sqlite3_get_table(db, query, &query_result, &row_count, &column_count, NULL);
+ if (ret != SQLITE_OK && ret != -1) {
+ ERR("Failed to get DB table [%d][%s]", ret, query);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ }
+
+ if (row_count == 0) {
+ DBG("No enabled do_not_disturb user");
+ ret = NOTIFICATION_ERROR_NONE;
+ goto out;
+ }
+
+ result_uids = (uid_t *)malloc(sizeof(int) * row_count);
+ if (result_uids == NULL) {
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ column_index = column_count;
+ for (i = 0; i < row_count; i++)
+ _get_table_field_data_int(query_result, (int *)&(result_uids[i]), column_index++);
+
+ *uids = result_uids;
+ *count = row_count;
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (query_result)
+ sqlite3_free_table(query_result);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+EXPORT_API
+int notification_get_dnd_and_allow_to_notify(const char *app_id,
+ int *do_not_disturb,
+ int *do_not_disturb_except,
+ int *allow_to_notify,
+ uid_t uid)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ int row_count;
+ int col_count;
+ int col_index;
+ sqlite3 *db;
+ char *query_setting = NULL;
+ char **query_setting_result = NULL;
+ char *query_system_setting = NULL;
+ char **query_system_setting_result = NULL;
+
+ if (app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query_setting = sqlite3_mprintf("SELECT allow_to_notify, "
+ "do_not_disturb_except FROM %s WHERE app_id = %Q "
+ "AND (uid = %d OR uid = %d) ORDER BY uid DESC",
+ NOTIFICATION_SETTING_DB_TABLE, app_id,
+ uid, tzplatform_getuid(TZ_SYS_GLOBALAPP_USER));
+ if (query_setting == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ query_system_setting = sqlite3_mprintf("SELECT do_not_disturb FROM %s "
+ "WHERE uid = %d",
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE, uid);
+ if (query_system_setting == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_get_table(db, query_setting, &query_setting_result, &row_count, &col_count, NULL);
+ if (sql_ret != SQLITE_OK && sql_ret != -1) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get DB table [%d][%s]", sql_ret, query_setting);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (row_count == 0) {
+ ERR("Invalid uid [%d] or app id [%s]", uid, app_id);
+ ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ goto out;
+ }
+
+ col_index = col_count;
+ _get_table_field_data_int(query_setting_result, (int *)allow_to_notify, col_index++);
+ _get_table_field_data_int(query_setting_result, (int *)do_not_disturb_except, col_index++);
+
+ sql_ret = sqlite3_get_table(db, query_system_setting, &query_system_setting_result, &row_count, &col_count, NULL);
+ if (sql_ret != SQLITE_OK && sql_ret != -1) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get DB table [%d][%s]", sql_ret, query_setting);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (row_count == 0) {
+ ERR("Invalid uid [%d]", uid);
+ ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ goto out;
+ }
+
+ col_index = col_count;
+ _get_table_field_data_int(query_system_setting_result, (int *)do_not_disturb, col_index++);
+
+out:
+ if (query_setting_result)
+ sqlite3_free_table(query_setting_result);
+
+ if (query_system_setting_result)
+ sqlite3_free_table(query_system_setting_result);
+
+ if (query_setting)
+ sqlite3_free(query_setting);
+
+ if (query_system_setting)
+ sqlite3_free(query_system_setting);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API int notification_system_setting_load_dnd_allow_exception(dnd_allow_exception_h *dnd_allow_exception, int *count, uid_t uid)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ int sql_ret;
+ int row_count = 0;
+ int column_count = 0;
+ int col_index = 0;
+ int i;
+ char *query = NULL;
+ char **query_result = NULL;
+ sqlite3 *db = NULL;
+ dnd_allow_exception_h dnd_allow_exception_data = NULL;
+
+ if (dnd_allow_exception == NULL) {
+ ERR("Invalid paramter"); /* LCOV_EXCL_LINE */
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT type, value FROM %s WHERE uid = %d",
+ NOTIFICATION_DND_ALLOW_EXCEPTION, uid);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ sql_ret = sqlite3_get_table(db, query, &query_result, &row_count, &column_count, NULL);
+ if (sql_ret != SQLITE_OK && sql_ret != -1) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get DB table [%d][%s]", sql_ret, query); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (!row_count) {
+ DBG("No setting found"); /* LCOV_EXCL_LINE */
+ goto out;
+ } else {
+ dnd_allow_exception_data = (dnd_allow_exception_h)malloc(sizeof(struct notification_system_setting_dnd_allow_exception) * row_count);
+ if (dnd_allow_exception_data == NULL) {
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ col_index = column_count;
+
+ for (i = 0; i < row_count; i++) {
+ _get_table_field_data_int(query_result, (int *)&(dnd_allow_exception_data[i].type), col_index++);
+ _get_table_field_data_int(query_result, (int *)&(dnd_allow_exception_data[i].value), col_index++);
+ }
+ }
+
+ *dnd_allow_exception = dnd_allow_exception_data;
+ *count = row_count;
+
+out:
+ if (query_result)
+ sqlite3_free_table(query_result);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API
+int notification_system_setting_update_dnd_allow_exception(int type, int value, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int num_changes = 0;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("INSERT OR REPLACE INTO %s (uid, type, value) "
+ "VALUES(%d, %d, %d) ",
+ NOTIFICATION_DND_ALLOW_EXCEPTION,
+ uid, type, value);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = notification_db_exec(db, query, &num_changes);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ goto out;
+
+ if (num_changes == 0)
+ WARN("No changes on DB");
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+EXPORT_API
+int noti_system_setting_get_do_not_disturb(int *do_not_disturb, uid_t uid)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ int row_count = 0;
+ int col_count = 0;
+ int col_index = 0;
+ char *query = NULL;
+ char **query_result = NULL;
+ sqlite3 *db = NULL;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("SELECT do_not_disturb FROM %s WHERE uid = %d",
+ NOTIFICATION_SYSTEM_SETTING_DB_TABLE, uid);
+ if (query == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to alloc memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = sqlite3_get_table(db, query, &query_result, &row_count, &col_count, NULL);
+ if (ret != SQLITE_OK && ret != -1) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to get DB table [%d][%s]", ret, query);
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ col_index = col_count;
+ if (row_count == 0) {
+ /* LCOV_EXCL_START */
+ ERR("No system setting found");
+ ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
+ /* LCOV_EXCL_STOP */
+ } else {
+ if (_get_table_field_data_int(query_result, (int *)do_not_disturb, col_index++) == false)
+ ret = NOTIFICATION_ERROR_FROM_DB;
+ }
+
+out:
+ if (query_result)
+ sqlite3_free_table(query_result);
+
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+
+/* LCOV_EXCL_START */
+EXPORT_API
+int notification_setting_db_update_app_disabled(const char *app_id, bool value, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int num_changes = 0;
+
+ if (app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open();
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("UPDATE %s SET app_disabled= %d " \
+ "WHERE app_id = %Q AND uid = %d",
+ NOTIFICATION_SETTING_DB_TABLE, value,
+ app_id, uid);
+ if (query == NULL) {
+ ERR("Failed to alloc memory"); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = notification_db_exec(db, query, &num_changes);
+ if (ret == NOTIFICATION_ERROR_NONE && num_changes <= 0)
+ ret = NOTIFICATION_ERROR_NOT_EXIST_ID;
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API
+int notification_setting_db_update_pkg_disabled(const char *pkg_id, bool value, uid_t uid)
+{
+ sqlite3 *db = NULL;
+ char *query = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int num_changes = 0;
+
+ if (pkg_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ db = notification_db_open(DBPATH);
+ if (!db)
+ return get_last_result();
+
+ query = sqlite3_mprintf("UPDATE %s SET app_disabled= %d " \
+ "WHERE package_name = %Q AND uid = %d",
+ NOTIFICATION_SETTING_DB_TABLE, value,
+ pkg_id, uid);
+ if (query == NULL) {
+ ERR("Failed to alloc memory"); /* LCOV_EXCL_LINE */
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = notification_db_exec(db, query, &num_changes);
+ if (ret == NOTIFICATION_ERROR_NONE && num_changes <= 0)
+ ret = NOTIFICATION_ERROR_NOT_EXIST_ID;
+
+out:
+ if (query)
+ sqlite3_free(query);
+
+ if (db)
+ notification_db_close(&db);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
diff --git a/notification/src/notification_shared_file.c b/notification/src/notification_shared_file.c
new file mode 100644
index 0000000..7ca23d9
--- /dev/null
+++ b/notification/src/notification_shared_file.c
@@ -0,0 +1,1185 @@
+/*
+ * Copyright (c) 2017 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <gio/gio.h>
+#include <glib/gstdio.h>
+
+#include <tzplatform_config.h>
+#include <security-manager.h>
+#include <sys/smack.h>
+#include <sys/stat.h>
+#include <linux/xattr.h>
+#include <sys/types.h>
+#include <utime.h>
+#include <sys/time.h>
+#include <package_manager.h>
+
+#include "notification.h"
+#include "notification_debug.h"
+#include "notification_shared_file.h"
+#include <notification_private.h>
+
+
+#define DUMMY_PARAM
+#define __OOM_CHECK(value, ret_value, free_fun) \
+do { \
+ if (value == NULL) { \
+ ERR("out of memory"); \
+ free_fun; \
+ return ret_value; \
+ } \
+} while (0)
+
+GList *__uid_list;
+typedef struct uid_info {
+ uid_t uid;
+ GList *sharing_req_list;
+ GList *target_app_list;
+} uid_info_s;
+
+typedef struct sharing_req_data {
+ char *app_id;
+ char *dir;
+ GList *priv_id_list;
+ GList *shared_file_list;
+ GList *target_app_table;
+} sharing_req_data_s;
+
+typedef struct sharing_file_info {
+ char *src_path;
+ char *dst_path;
+ time_t modification_time;
+} sharing_file_info_s;
+
+typedef struct target_app_info {
+ char *app_id;
+ char *dbus_sender_name;
+} target_app_info_s;
+
+static bool __make_sharing_dir(const char *dir)
+{
+ GFile *noti_dir = NULL;
+ GError *g_err = NULL;
+
+ if (access(dir, R_OK) != 0) {
+ noti_dir = g_file_new_for_path(dir);
+ if (g_file_make_directory(noti_dir, NULL, &g_err) == false) {
+ /* LCOV_EXCL_START */
+ if (g_err) {
+ ERR("Failed to make sharing dir[%s]",
+ g_err->message);
+ g_error_free(g_err);
+ }
+ g_object_unref(noti_dir);
+ return false;
+ /* LCOV_EXCL_STOP */
+ }
+ g_object_unref(noti_dir);
+ }
+
+ return true;
+}
+
+static char *__get_data_path_by_pkg_id(const char *pkg_id,
+ const char *file_name, uid_t uid)
+{
+#define NOTI_PRIV_DATA_DIR "data/.notification"
+
+ const char *path;
+ char dir[PATH_MAX];
+
+ tzplatform_set_user(uid);
+ path = tzplatform_getenv(TZ_USER_APP);
+ tzplatform_reset_user();
+
+ if (pkg_id == NULL || path == NULL)
+ return NULL;
+
+ snprintf(dir, sizeof(dir), "%s/%s/%s", path, pkg_id, NOTI_PRIV_DATA_DIR);
+
+ if (__make_sharing_dir(dir) == false)
+ return NULL;
+
+ snprintf(dir, sizeof(dir), "%s/%s/%s/%s", path, pkg_id,
+ NOTI_PRIV_DATA_DIR, file_name);
+
+ return strdup(dir);
+}
+
+static const char *__last_index_of(const char *path, const char *search)
+{
+ int i;
+ int search_len;
+ const char *index;
+
+ if (path == NULL || search == NULL)
+ return NULL;
+
+ search_len = strlen(search);
+ index = path + strlen(path) - search_len;
+
+ while (index >= path) {
+ for (i = 0; i < search_len; i++)
+ if (index[i] != search[i])
+ break;
+
+ if (i == search_len)
+ return index;
+ index--;
+ }
+
+ return NULL;
+}
+
+/* Check path that include res directory */
+/* LCOV_EXCL_START */
+static bool __is_private_file(const char *smack_label, const char *pkg_id)
+{
+ const char *smack_index;
+ bool ret = false;
+
+ if (smack_label == NULL || pkg_id == NULL)
+ return ret;
+
+ smack_index = __last_index_of(smack_label, pkg_id);
+ if (smack_index != NULL && (strlen(smack_index) == strlen(pkg_id)))
+ ret = true;
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+static bool __is_RO_file(const char *smack_label)
+{
+#define CHECK_LABEL "::RO"
+
+ const char *smack_index;
+ bool ret = false;
+
+ smack_index = __last_index_of(smack_label, CHECK_LABEL);
+ if (smack_index != NULL && (strlen(smack_index) == strlen(CHECK_LABEL)))
+ ret = true;
+
+ return ret;
+}
+
+/* file copy from /res to /data */
+int notification_copy_private_file(const char *src_path,
+ const char *dst_path)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ GFile *src = NULL;
+ GFile *dst = NULL;
+ GError *g_err = NULL;
+ struct utimbuf ut = {0,};
+
+ dst = g_file_new_for_path(dst_path);
+ if (dst == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("dst path is wrong [%s]", dst_path);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (g_file_query_exists(dst, NULL) == true) {
+ ret = NOTIFICATION_ERROR_ALREADY_EXIST_ID;
+ INFO("dst path existed [%s]", dst_path);
+ goto out;
+ }
+
+ src = g_file_new_for_path(src_path);
+ if (src == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("src path is wrong [%s]", src_path);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (!g_file_copy(src, dst, G_FILE_COPY_NOFOLLOW_SYMLINKS,
+ /* LCOV_EXCL_START */
+ NULL, NULL, NULL, &g_err)) {
+ if (g_err) {
+ ERR(
+ "Copying file from [%s] to [%s] is failed [%s]",
+ src_path, dst_path, g_err->message);
+ g_error_free(g_err);
+ }
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ut.modtime = time(NULL);
+ if (g_utime(dst_path, &ut) != 0)
+ DBG("Failed to set g_utime %d ", errno);
+
+out:
+ if (src)
+ g_object_unref(src);
+ if (dst)
+ g_object_unref(dst);
+
+ return ret;
+}
+
+static void __free_file_info(gpointer data)
+{
+ sharing_file_info_s *info = (sharing_file_info_s *)data;
+
+ if (info != NULL) {
+ if (info->src_path)
+ free(info->src_path);
+ if (info->dst_path)
+ free(info->dst_path);
+ free(info);
+ }
+}
+
+/* LCOV_EXCL_START */
+static void __free_req_info(gpointer data)
+{
+ sharing_req_data_s *info = (sharing_req_data_s *)data;
+
+ if (info == NULL)
+ return;
+ if (info->app_id)
+ free(info->app_id);
+ if (info->dir)
+ free(info->dir);
+ if (info->shared_file_list)
+ g_list_free_full(info->shared_file_list, __free_file_info);
+ if (info->target_app_table)
+ g_list_free_full(info->target_app_table, free);
+
+ free(info);
+}
+/* LCOV_EXCL_STOP */
+
+static char **__convert_list_to_array(GList *list, int *length)
+{
+ int len, i;
+ char **array;
+ GList *iter;
+
+ if (list == NULL)
+ return NULL;
+
+ len = g_list_length(list);
+ if (len == 0)
+ return NULL;
+
+ array = (char **)calloc(len + 1, sizeof(char *));
+ __OOM_CHECK(array, NULL, DUMMY_PARAM);
+
+ for (i = 0, iter = list; iter != NULL; i++, iter = g_list_next(iter))
+ array[i] = ((sharing_file_info_s *)iter->data)->dst_path;
+
+ *length = len;
+
+ return array;
+}
+
+static gint __comp_str(gconstpointer a, gconstpointer b)
+{
+ char *new_file = (char *)a;
+ char *file = (char *)b;
+
+ if (new_file == NULL || file == NULL)
+ return -1;
+
+ return strcmp(new_file, file);
+}
+
+/* LCOV_EXCL_START */
+static gint __comp_file_info(gconstpointer a, gconstpointer b)
+{
+ sharing_file_info_s *file = (sharing_file_info_s *)a;
+ sharing_file_info_s *new_file = (sharing_file_info_s *)b;
+
+ if (!file || !new_file || !new_file->dst_path || !file->dst_path)
+ return -1;
+
+ return strcmp(new_file->dst_path, file->dst_path);
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static gint __comp_dst_path(gconstpointer a, gconstpointer b)
+{
+ sharing_file_info_s *info = (sharing_file_info_s *)a;
+ char *path = (char *)b;
+
+ if (!info || !path || !info->dst_path)
+ return -1;
+
+ return strcmp(info->dst_path, path);
+}
+/* LCOV_EXCL_STOP */
+
+static sharing_file_info_s *__dup_file_info(sharing_file_info_s *src)
+{
+ sharing_file_info_s *file_info;
+
+ file_info = (sharing_file_info_s *)calloc(1, sizeof(sharing_file_info_s));
+ __OOM_CHECK(file_info, NULL, DUMMY_PARAM);
+
+ file_info->dst_path = strdup(src->dst_path);
+ __OOM_CHECK(file_info->dst_path, NULL, __free_file_info(file_info));
+
+ file_info->src_path = strdup(src->src_path);
+ __OOM_CHECK(file_info->src_path, NULL, __free_file_info(file_info));
+
+ file_info->modification_time = src->modification_time;
+
+ return file_info;
+
+}
+
+static void __make_file_info(char *src_path, char *dst_path,
+ GList **new_file_list, GList *shared_file_list, bool *is_overlapping)
+{
+ int ret;
+ GList *tmp;
+ sharing_file_info_s *file_info;
+ sharing_file_info_s *dup_file_info;
+ struct stat stat_buf = {0,};
+
+ /*
+ * If the file copy is successful,
+ * ignore the shared_file_list check for private sharing
+ */
+ ret = notification_copy_private_file(src_path, dst_path);
+
+ if (ret == NOTIFICATION_ERROR_ALREADY_EXIST_ID) {
+ tmp = g_list_find_custom(shared_file_list, dst_path,
+ __comp_dst_path);
+ if (tmp == NULL) {
+ file_info = (sharing_file_info_s *)calloc(1,
+ sizeof(sharing_file_info_s));
+ __OOM_CHECK(file_info, DUMMY_PARAM, DUMMY_PARAM);
+
+ file_info->dst_path = strdup(dst_path);
+ __OOM_CHECK(file_info->dst_path, DUMMY_PARAM,
+ __free_file_info(file_info));
+
+ file_info->src_path = strdup(src_path);
+ __OOM_CHECK(file_info->src_path, DUMMY_PARAM,
+ __free_file_info(file_info));
+
+ if (stat(dst_path, &stat_buf) != 0)
+ ERR("Failed to get stat info");
+ file_info->modification_time = stat_buf.st_mtime;
+
+ *new_file_list = g_list_append(*new_file_list, file_info);
+ } else {
+ file_info = (sharing_file_info_s *)tmp->data;
+
+ if (stat(file_info->dst_path, &stat_buf) != 0)
+ ERR("Failed to get stat info");
+
+ if (file_info->modification_time != stat_buf.st_mtime) {
+ dup_file_info = __dup_file_info(file_info);
+ __OOM_CHECK(dup_file_info, DUMMY_PARAM, DUMMY_PARAM);
+
+ *new_file_list = g_list_append(*new_file_list,
+ dup_file_info);
+ *is_overlapping = true;
+ }
+ }
+ } else if (ret == NOTIFICATION_ERROR_NONE) {
+ *is_overlapping = true;
+ }
+
+}
+
+static GList *__get_new_file_list(notification_h noti,
+ GList *shared_file_list,
+ bool *is_overlapping)
+{
+ GList *new_file_list = NULL;
+ char *src_path, *dst_path, *dup_str;
+ char buf_key[32] = { 0, };
+ int i = NOTIFICATION_IMAGE_TYPE_ICON;
+
+
+ if (noti->priv_sound_path != NULL && noti->sound_path != NULL) {
+ dst_path = noti->priv_sound_path;
+ src_path = noti->sound_path;
+
+ dup_str = strdup(dst_path);
+ __OOM_CHECK(dup_str, NULL, DUMMY_PARAM);
+
+ __make_file_info(src_path, dst_path, &new_file_list,
+ shared_file_list, is_overlapping);
+
+ free(noti->sound_path);
+ noti->sound_path = dup_str;
+ }
+
+ if (noti->priv_vibration_path != NULL && noti->vibration_path != NULL) {
+ dst_path = noti->priv_vibration_path;
+ src_path = noti->vibration_path;
+
+ dup_str = strdup(dst_path);
+ __OOM_CHECK(dup_str, NULL,
+ g_list_free_full(new_file_list, __free_file_info));
+
+ __make_file_info(src_path, dst_path, &new_file_list,
+ shared_file_list, is_overlapping);
+
+ free(noti->vibration_path);
+ noti->vibration_path = dup_str;
+ }
+
+ if (noti->b_priv_image_path == NULL)
+ return new_file_list;
+
+ for (; i <= NOTIFICATION_IMAGE_TYPE_MAX; i++) {
+ src_path = NULL;
+ dst_path = NULL;
+ snprintf(buf_key, sizeof(buf_key), "%d", i);
+ bundle_get_str(noti->b_priv_image_path, buf_key, &dst_path);
+ bundle_get_str(noti->b_image_path, buf_key, &src_path);
+ if (dst_path != NULL && src_path != NULL) {
+ __make_file_info(src_path, dst_path, &new_file_list,
+ shared_file_list, is_overlapping);
+
+ bundle_del(noti->b_image_path, buf_key);
+ bundle_add_str(noti->b_image_path, buf_key, dst_path);
+ }
+ }
+
+ return new_file_list;
+}
+
+static char *__get_shared_dir(notification_h noti)
+{
+ char *path = NULL;
+ char *dir;
+ const char *index;
+ char buf_key[32] = { 0, };
+ int i = NOTIFICATION_IMAGE_TYPE_ICON, dir_len;
+
+ if (noti->b_priv_image_path != NULL) {
+ for (; i <= NOTIFICATION_IMAGE_TYPE_MAX; i++) {
+ snprintf(buf_key, sizeof(buf_key), "%d", i);
+ bundle_get_str(noti->b_priv_image_path, buf_key, &path);
+ if (path != NULL)
+ break;
+ }
+ }
+
+ if (path == NULL && noti->priv_sound_path != NULL)
+ path = noti->priv_sound_path;
+ else if (path == NULL && noti->priv_vibration_path != NULL)
+ path = noti->priv_vibration_path;
+
+ if (path == NULL) {
+ DBG("No private resource");
+ return NULL;
+ }
+
+ index = __last_index_of(path, "/");
+ if (index == NULL) {
+ ERR("Failed to find directory separator");
+ return NULL;
+ }
+
+ dir_len = index - path + 1;
+ if (dir_len <= 0 || dir_len > PATH_MAX)
+ return NULL;
+
+ dir = (char *)calloc(dir_len, sizeof(char));
+ __OOM_CHECK(dir, NULL, DUMMY_PARAM);
+
+ snprintf(dir, dir_len, "%s", path);
+
+ return dir;
+}
+
+static gint __comp_sharing_req_list(gconstpointer a, gconstpointer b)
+{
+ sharing_req_data_s *req_data = (sharing_req_data_s *)a;
+ char *app_id = (char *)b;
+
+ if (!req_data || !app_id || !req_data->app_id)
+ return -1;
+
+ if (!strcmp(app_id, req_data->app_id))
+ return 0;
+
+ return -1;
+}
+
+static gint __comp_uid_info_list(gconstpointer a, gconstpointer b)
+{
+ uid_info_s *uid_info = (uid_info_s *)a;
+
+ if (!a || !b)
+ return -1;
+
+ if (uid_info->uid == GPOINTER_TO_INT(b))
+ return 0;
+
+ return -1;
+}
+
+static gint __comp_priv_id(gconstpointer a, gconstpointer b)
+{
+ if (!a || !b)
+ return -1;
+
+ if (GPOINTER_TO_INT(a) == GPOINTER_TO_INT(b))
+ return 0;
+
+ return 1;
+}
+
+static gint __comp_target_app(gconstpointer a, gconstpointer b)
+{
+ target_app_info_s *target = (target_app_info_s *)a;
+ char *sender = (char *)b;
+
+ if (!target || !sender || !target->dbus_sender_name)
+ return -1;
+
+ return strcmp(sender, target->dbus_sender_name);
+}
+
+EXPORT_API void notification_remove_private_sharing_target_id(
+ const char *sender, uid_t uid)
+{
+ target_app_info_s *target_info;
+ uid_info_s *uid_info;
+ GList *sharing_req_list, *target_app;
+
+ sharing_req_list = g_list_find_custom(__uid_list, GINT_TO_POINTER(uid),
+ __comp_uid_info_list);
+ if (sharing_req_list == NULL)
+ return;
+
+ uid_info = sharing_req_list->data;
+ target_app = g_list_find_custom(uid_info->target_app_list, sender,
+ __comp_target_app);
+
+ if (target_app != NULL) {
+ target_info = target_app->data;
+ if (target_info) {
+ uid_info->target_app_list = g_list_remove(
+ uid_info->target_app_list, target_info);
+
+ free(target_info->app_id);
+ free(target_info->dbus_sender_name);
+ free(target_info);
+ target_info = NULL;
+ }
+ }
+}
+
+EXPORT_API void notification_add_private_sharing_target_id(pid_t pid,
+ const char *sender, uid_t uid)
+{
+ char *app_id;
+ target_app_info_s *target_info;
+ uid_info_s *uid_info;
+ GList *sharing_req_list, *target_app;
+
+ sharing_req_list = g_list_find_custom(__uid_list, GINT_TO_POINTER(uid),
+ __comp_uid_info_list);
+ if (sharing_req_list == NULL) {
+ uid_info = (uid_info_s *)calloc(1, sizeof(uid_info_s));
+ __OOM_CHECK(uid_info, DUMMY_PARAM, DUMMY_PARAM);
+ uid_info->uid = uid;
+
+ __uid_list = g_list_append(__uid_list, uid_info);
+ } else {
+ uid_info = sharing_req_list->data;
+ }
+
+ target_app = g_list_find_custom(uid_info->target_app_list, sender,
+ __comp_target_app);
+ if (target_app == NULL) {
+ app_id = notification_get_app_id_by_pid((int)pid);
+ if (app_id == NULL) {
+ ERR("Failed to get app id by pid");
+ return;
+ }
+
+ target_info = (target_app_info_s *)calloc(1, sizeof(target_app_info_s));
+ if (target_info == NULL) {
+ ERR("Failed to alloc memory");
+ free(app_id);
+ return;
+ }
+
+ target_info->app_id = app_id;
+ target_info->dbus_sender_name = strdup(sender);
+ if (target_info->dbus_sender_name == NULL) {
+ ERR("Failed to alloc memory");
+ free(target_info);
+ free(app_id);
+ return;
+ }
+
+ uid_info->target_app_list = g_list_append(
+ uid_info->target_app_list, target_info);
+ }
+}
+
+char *notification_check_file_path_is_private(const char *pkg_id,
+ const char *file_path)
+{
+ char *smack_label = NULL;
+ char *dst_path = NULL;
+ int size;
+ uid_t uid = getuid();
+
+ size = smack_new_label_from_path(file_path, XATTR_NAME_SMACK,
+ TRUE, &smack_label);
+ if (size <= 0) {
+ ERR("Failed to get smack info");
+ return NULL;
+ }
+
+ if (__is_RO_file(smack_label))
+ dst_path = __get_data_path_by_pkg_id(pkg_id,
+ __last_index_of(file_path, "/") + 1, uid);
+
+ if (dst_path == NULL && __is_private_file(smack_label, pkg_id)) {
+ dst_path = strdup(file_path);
+ if (dst_path == NULL)
+ ERR("Failed to strdup");
+ }
+
+ free(smack_label);
+ return dst_path;
+}
+
+EXPORT_API bool notification_validate_private_sharing(
+ notification_h updated_noti)
+{
+ char *updated_path = NULL;
+ char *private_path;
+ char buf_key[32] = { 0, };
+ int i = NOTIFICATION_IMAGE_TYPE_ICON;
+
+ if (updated_noti->b_image_path && updated_noti->b_priv_image_path) {
+ for (; i <= NOTIFICATION_IMAGE_TYPE_MAX; i++) {
+ snprintf(buf_key, sizeof(buf_key), "%d", i);
+
+ bundle_get_str(updated_noti->b_image_path, buf_key,
+ &updated_path);
+ if (updated_path == NULL)
+ continue;
+
+ bundle_get_str(updated_noti->b_priv_image_path,
+ buf_key, &private_path);
+ if (private_path == NULL)
+ continue;
+
+ if (strcmp(updated_path, private_path) == 0)
+ return false;
+
+ updated_path = NULL;
+ }
+ }
+
+ if (updated_noti->sound_path && updated_noti->priv_sound_path) {
+ if (strcmp(updated_noti->sound_path,
+ updated_noti->priv_sound_path) == 0)
+ return false;
+ }
+
+ if (updated_noti->vibration_path && updated_noti->priv_vibration_path) {
+ if (strcmp(updated_noti->vibration_path,
+ updated_noti->priv_vibration_path) == 0)
+ return false;
+ }
+
+ return true;
+}
+
+EXPORT_API void notification_calibrate_private_sharing(
+ notification_h updated_noti, notification_h source_noti)
+{
+ char *updated_path = NULL;
+ char *source_path;
+ char *private_path;
+ char buf_key[32] = { 0, };
+ int i = NOTIFICATION_IMAGE_TYPE_ICON;
+
+ if (updated_noti->b_image_path && updated_noti->b_priv_image_path) {
+ for (; i <= NOTIFICATION_IMAGE_TYPE_MAX; i++) {
+ snprintf(buf_key, sizeof(buf_key), "%d", i);
+ bundle_get_str(updated_noti->b_image_path, buf_key,
+ &updated_path);
+ if (updated_path == NULL)
+ continue;
+ bundle_get_str(updated_noti->b_priv_image_path,
+ buf_key, &private_path);
+ if (private_path == NULL)
+ continue;
+ if (strcmp(updated_path, private_path) == 0) {
+ bundle_get_str(source_noti->b_image_path,
+ buf_key, &source_path);
+ bundle_del(updated_noti->b_image_path, buf_key);
+ bundle_add_str(updated_noti->b_image_path,
+ buf_key, source_path);
+ }
+ updated_path = NULL;
+ private_path = NULL;
+ }
+ }
+
+ if (updated_noti->sound_path && updated_noti->priv_sound_path) {
+ if (strcmp(updated_noti->sound_path,
+ updated_noti->priv_sound_path) == 0) {
+ free(updated_noti->sound_path);
+ updated_noti->sound_path = strdup(source_noti->sound_path);
+ if (updated_noti->sound_path == NULL)
+ ERR("out of memory");
+ }
+ }
+
+ if (updated_noti->vibration_path && updated_noti->priv_vibration_path) {
+ if (strcmp(updated_noti->vibration_path,
+ updated_noti->priv_vibration_path) == 0) {
+ free(updated_noti->vibration_path);
+ updated_noti->vibration_path =
+ strdup(source_noti->priv_vibration_path);
+ if (updated_noti->vibration_path == NULL)
+ ERR("out of memory");
+ }
+ }
+}
+
+
+int __set_sharing_for_new_target(sharing_req_data_s *req_data,
+ GList *target_app_list)
+{
+ char **path_array = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int len;
+ private_sharing_req *handle = NULL;
+ GList *iter, *tmp;
+ target_app_info_s *target_info;
+ char *app_info = NULL;
+
+ iter = target_app_list;
+ for (; iter != NULL; iter = g_list_next(iter)) {
+ target_info = (target_app_info_s *)iter->data;
+ tmp = g_list_find_custom(req_data->target_app_table,
+ target_info->app_id, __comp_str);
+ if (tmp != NULL)
+ continue;
+
+ app_info = strdup(target_info->app_id);
+ if (app_info == NULL) {
+ ERR("out of memory");
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ if (handle == NULL) {
+ ret = security_manager_private_sharing_req_new(&handle);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR("Failed to create PS handle");
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_req_set_owner_appid(
+ handle, req_data->app_id);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR(
+ "Failed to set owner appid(%s) %d",
+ req_data->app_id, ret);
+ goto out;
+ }
+ path_array = __convert_list_to_array(
+ req_data->shared_file_list, &len);
+ if (path_array == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_req_add_paths(
+ handle, (const char **)path_array, len);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR("Failed to add paths %d", ret);
+ goto out;
+ }
+ }
+
+ ret = security_manager_private_sharing_req_set_target_appid(
+ handle, target_info->app_id);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR("Failed to set target appid(%s)",
+ (const char *)iter->data);
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_apply(handle);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR("Failed to apply PS %d", ret);
+ goto out;
+ }
+
+ req_data->target_app_table = g_list_append(
+ req_data->target_app_table,
+ app_info);
+ }
+
+out:
+ if (ret != NOTIFICATION_ERROR_NONE && app_info)
+ free(app_info);
+
+ if (handle != NULL)
+ security_manager_private_sharing_req_free(handle);
+ if (path_array != NULL)
+ free(path_array);
+
+ return ret;
+}
+
+int __set_sharing_for_new_file(sharing_req_data_s *req_data,
+ GList *new_file_list, bool is_overlapping)
+{
+ char **path_array = NULL;
+ int ret = NOTIFICATION_ERROR_NONE;
+ int len;
+ private_sharing_req *handle = NULL;
+ GList *iter;
+
+ path_array = __convert_list_to_array(new_file_list, &len);
+ if (path_array == NULL) {
+ ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_req_new(&handle);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ ERR("Failed to create private sharing request handle[%d]", ret);
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_req_set_owner_appid(handle,
+ req_data->app_id);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to set owner appid[%s][%d]",
+ req_data->app_id, ret);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = security_manager_private_sharing_req_add_paths(handle,
+ (const char **)path_array, len);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to add paths [%d]", ret);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (is_overlapping == true) {
+ iter = req_data->target_app_table;
+ for (; iter != NULL; iter = g_list_next(iter)) {
+ ret = security_manager_private_sharing_req_set_target_appid(
+ handle, (const char *)iter->data);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to set target appid [%s]",
+ (const char *)iter->data);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = security_manager_private_sharing_drop(handle);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to drop [%d]", ret);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+ }
+
+ iter = req_data->target_app_table;
+ for (; iter != NULL; iter = g_list_next(iter)) {
+ ret = security_manager_private_sharing_req_set_target_appid(handle,
+ (const char *)iter->data);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to set target appid [%s]",
+ (const char *)iter->data);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = security_manager_private_sharing_apply(handle);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to apply PS [%d]", ret);
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+out:
+ if (handle != NULL)
+ security_manager_private_sharing_req_free(handle);
+ if (path_array != NULL)
+ free(path_array);
+
+ return ret;
+}
+
+EXPORT_API int notification_set_private_sharing(notification_h noti,
+ uid_t uid)
+{
+ int ret = NOTIFICATION_ERROR_NONE;
+ bool is_overlapping = false;
+ sharing_req_data_s *req_data;
+ sharing_file_info_s *file_info, *dup_file_info;
+ uid_info_s *uid_info;
+ GList *req_list, *iter, *tmp;
+ GList *new_file_list = NULL;
+
+ if (noti == NULL || noti->caller_app_id == NULL)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ tmp = g_list_find_custom(__uid_list, GINT_TO_POINTER(uid),
+ __comp_uid_info_list);
+ if (tmp == NULL) {
+ uid_info = (uid_info_s *)calloc(1, sizeof(uid_info_s));
+ __OOM_CHECK(uid_info, NOTIFICATION_ERROR_OUT_OF_MEMORY, DUMMY_PARAM);
+
+ uid_info->uid = uid;
+ __uid_list = g_list_append(__uid_list, uid_info);
+ } else {
+ uid_info = tmp->data;
+ }
+
+ req_list = g_list_find_custom(uid_info->sharing_req_list,
+ noti->caller_app_id, __comp_sharing_req_list);
+ if (req_list == NULL) {
+ req_data = (sharing_req_data_s *)calloc(1, sizeof(sharing_req_data_s));
+ __OOM_CHECK(req_data, NOTIFICATION_ERROR_OUT_OF_MEMORY, DUMMY_PARAM);
+
+ req_data->app_id = strdup(noti->caller_app_id);
+ __OOM_CHECK(req_data->app_id, NOTIFICATION_ERROR_OUT_OF_MEMORY,
+ __free_req_info(req_data));
+
+ req_data->dir = __get_shared_dir(noti);
+ if (req_data->dir == NULL) {
+ __free_req_info(req_data);
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ uid_info->sharing_req_list = g_list_append(
+ uid_info->sharing_req_list, req_data);
+ } else {
+ req_data = (sharing_req_data_s *)req_list->data;
+ }
+
+ __make_sharing_dir(req_data->dir);
+
+ tmp = g_list_find_custom(req_data->priv_id_list,
+ GINT_TO_POINTER(noti->priv_id), __comp_priv_id);
+ if (tmp == NULL)
+ req_data->priv_id_list = g_list_append(req_data->priv_id_list,
+ GINT_TO_POINTER(noti->priv_id));
+
+ new_file_list = __get_new_file_list(noti, req_data->shared_file_list,
+ &is_overlapping);
+ if (new_file_list != NULL) {
+ if (__set_sharing_for_new_file(req_data, new_file_list,
+ is_overlapping) != NOTIFICATION_ERROR_NONE) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ }
+ }
+
+ for (iter = new_file_list; iter != NULL; iter = g_list_next(iter)) {
+ tmp = NULL;
+ file_info = iter->data;
+ if (is_overlapping == true)
+ tmp = g_list_find_custom(
+ req_data->shared_file_list, file_info,
+ __comp_file_info);
+
+ if (tmp == NULL) {
+ dup_file_info = __dup_file_info(file_info);
+ req_data->shared_file_list = g_list_append(
+ req_data->shared_file_list, dup_file_info);
+ }
+ }
+
+ if (__set_sharing_for_new_target(req_data, uid_info->target_app_list)
+ != NOTIFICATION_ERROR_NONE) {
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+ goto out;
+ }
+ INFO("PS success priv id[%d] shared file count[%d] target app count[%d]",
+ noti->priv_id,
+ g_list_length(req_data->shared_file_list),
+ g_list_length(req_data->target_app_table));
+
+out:
+ if (new_file_list != NULL)
+ g_list_free_full(new_file_list, __free_file_info);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ req_data->priv_id_list = g_list_remove(req_data->priv_id_list,
+ GINT_TO_POINTER(noti->priv_id));
+ return ret;
+}
+
+EXPORT_API void notification_remove_private_sharing(
+ const char *src_app_id, int priv_id, uid_t uid)
+{
+ char **path_array = NULL;
+ sharing_req_data_s *req_data;
+ private_sharing_req *handle = NULL;
+ uid_info_s *uid_info;
+ GList *req_list;
+ GList *iter;
+ GList *priv_id_info = NULL;
+ GList *tmp_list = NULL;
+ int len, ret;
+
+ tmp_list = g_list_find_custom(__uid_list, GINT_TO_POINTER(uid),
+ __comp_uid_info_list);
+ if (tmp_list == NULL)
+ return;
+
+ uid_info = tmp_list->data;
+
+ req_list = g_list_find_custom(uid_info->sharing_req_list, src_app_id,
+ __comp_sharing_req_list);
+ if (req_list == NULL)
+ return;
+
+ req_data = (sharing_req_data_s *)req_list->data;
+
+ priv_id_info = g_list_find_custom(req_data->priv_id_list,
+ GINT_TO_POINTER(priv_id), __comp_priv_id);
+ if (priv_id_info == NULL)
+ return;
+
+ len = g_list_length(req_data->priv_id_list);
+ if (len > 1) {
+ req_data->priv_id_list = g_list_remove(req_data->priv_id_list,
+ priv_id_info->data);
+ return;
+ }
+
+ /* If there is no shared file, the private sharing is not dropped. */
+ __make_sharing_dir(req_data->dir);
+ iter = req_data->shared_file_list;
+ for (; iter != NULL; iter = g_list_next(iter))
+ notification_copy_private_file(
+ ((sharing_file_info_s *)(iter->data))->src_path,
+ ((sharing_file_info_s *)(iter->data))->dst_path);
+
+ if (g_list_length(req_data->target_app_table) > 0) {
+ ret = security_manager_private_sharing_req_new(&handle);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ERR("Failed to create PS request handle");
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_req_set_owner_appid(
+ handle, src_app_id);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ERR("Failed to set owner appid(%s) %d",
+ req_data->app_id, ret);
+ goto out;
+ }
+
+ path_array = __convert_list_to_array(req_data->shared_file_list, &len);
+ if (path_array == NULL) {
+ ERR("path_array is null %d",
+ g_list_length(req_data->shared_file_list));
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_req_add_paths(handle,
+ (const char **)path_array, len);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ERR("Failed to add paths %d", ret);
+ goto out;
+ }
+
+ iter = req_data->target_app_table;
+ for (; iter != NULL; iter = g_list_next(iter)) {
+ ret = security_manager_private_sharing_req_set_target_appid(
+ handle, (const char *)iter->data);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ERR("Failed to set target appid(%s)",
+ (const char *)iter->data);
+ goto out;
+ }
+
+ ret = security_manager_private_sharing_drop(handle);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ERR("Failed to drop %d", ret);
+ goto out;
+ }
+ }
+ }
+
+ iter = req_data->shared_file_list;
+ for (; iter != NULL; iter = g_list_next(iter)) {
+ if (g_remove(((sharing_file_info_s *)(iter->data))->dst_path) != 0)
+ ERR("Failed [%s] [%d]",
+ (const char *)iter->data, errno);
+ }
+
+ g_rmdir(req_data->dir);
+ req_data->priv_id_list = g_list_remove(req_data->priv_id_list,
+ priv_id_info->data);
+
+ uid_info->sharing_req_list = g_list_remove(uid_info->sharing_req_list,
+ req_data);
+ __free_req_info(req_data);
+
+out:
+ if (handle != NULL)
+ security_manager_private_sharing_req_free(handle);
+
+ if (path_array)
+ free(path_array);
+}
+
diff --git a/notification/src/notification_status.c b/notification/src/notification_status.c
new file mode 100644
index 0000000..cb69bbc
--- /dev/null
+++ b/notification/src/notification_status.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2000 - 2017 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.
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <notification.h>
+#include <notification_db.h>
+#include <notification_list.h>
+#include <notification_noti.h>
+#include <notification_debug.h>
+#include <notification_private.h>
+#include <notification_status.h>
+#include <notification_status_internal.h>
+
+#define PATH_NAME "/Org/Tizen/System/Notification/Status_message"
+#define INTERFACE_NAME "org.tizen.system.notification.status_message"
+#define MEMBER_NAME "status_message"
+
+struct _message_cb_data {
+ notification_status_message_cb callback;
+ void *data;
+ GDBusConnection *conn;
+ uint message_id;
+};
+
+static struct _message_cb_data md;
+
+static void __notification_status_message_dbus_callback(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ char *message = NULL;
+
+ g_variant_get(parameters, "(&s)", &message);
+ if (strlen(message) <= 0) {
+ /* LCOV_EXCL_START */
+ ERR("message is NULL");
+ return;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (!md.callback) {
+ /* LCOV_EXCL_START */
+ ERR("No callback");
+ return;
+ /* LCOV_EXCL_STOP */
+ }
+
+ md.callback(message, md.data);
+}
+
+EXPORT_API
+int notification_status_monitor_message_cb_set(notification_status_message_cb callback, void *user_data)
+{
+ GError *error = NULL;
+
+ if (!callback)
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+ if (md.conn == NULL) {
+ md.conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (md.conn == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to connect to the D-BUS Daemon[%s]",
+ error->message);
+ g_error_free(error);
+ return NOTIFICATION_ERROR_FROM_DBUS;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ if (!md.message_id) {
+ md.message_id = g_dbus_connection_signal_subscribe(md.conn,
+ NULL,
+ INTERFACE_NAME,
+ MEMBER_NAME,
+ PATH_NAME,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ __notification_status_message_dbus_callback,
+ NULL,
+ NULL);
+ if (md.message_id == 0) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to subscribe signal");
+ g_object_unref(md.conn);
+ return NOTIFICATION_ERROR_FROM_DBUS;
+ /* LCOV_EXCL_STOP */
+ }
+ }
+
+ md.callback = callback;
+ md.data = user_data;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API
+int notification_status_monitor_message_cb_unset(void)
+{
+ if (md.message_id) {
+ g_dbus_connection_signal_unsubscribe(md.conn, md.message_id);
+ md.message_id = 0;
+ }
+
+ if (md.conn) {
+ g_object_unref(md.conn);
+ md.conn = NULL;
+ }
+
+ md.callback = NULL;
+ md.data = NULL;
+
+ return NOTIFICATION_ERROR_NONE;
+}
+
+EXPORT_API
+int notification_status_message_post(const char *message)
+{
+ GError *err = NULL;
+ GDBusConnection *conn;
+ GVariant *param;
+ int ret = NOTIFICATION_ERROR_NONE;
+
+ if (!message) {
+ ERR("message is NULL");
+ return NOTIFICATION_ERROR_INVALID_PARAMETER;
+ }
+
+ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+ if (conn == NULL) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to connect to the D-BUS Daemon[%s]",
+ err->message);
+ ret = NOTIFICATION_ERROR_FROM_DBUS;
+ goto end;
+ /* LCOV_EXCL_STOP */
+ }
+
+ param = g_variant_new("(s)", message);
+
+ if (g_dbus_connection_emit_signal(conn,
+ NULL,
+ PATH_NAME,
+ INTERFACE_NAME,
+ MEMBER_NAME,
+ param,
+ &err) == FALSE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to emit signal[%s]",
+ err->message);
+ ret = NOTIFICATION_ERROR_FROM_DBUS;
+ goto end;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (g_dbus_connection_flush_sync(conn, NULL, &err) == FALSE) {
+ /* LCOV_EXCL_START */
+ ERR("Failed to flush connection sync[%s]",
+ err->message);
+ ret = NOTIFICATION_ERROR_FROM_DBUS;
+ goto end;
+ /* LCOV_EXCL_STOP */
+ }
+
+end:
+ if (err)
+ g_error_free(err); /* LCOV_EXCL_LINE */
+
+ if (conn)
+ g_object_unref(conn);
+
+ return ret;
+}
diff --git a/notification/src/notification_viewer.c b/notification/src/notification_viewer.c
new file mode 100644
index 0000000..6200d6b
--- /dev/null
+++ b/notification/src/notification_viewer.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <app_control_internal.h>
+#include <iniparser.h>
+#include <aul_svc.h>
+
+#include <notification.h>
+#include <notification_debug.h>
+#include <notification_viewer.h>
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_get_default_viewer(const char *path, char **default_viewer)
+{
+ char *viewer = NULL;
+ dictionary *dict = NULL;
+
+ if (access(path, F_OK) != 0) {
+ ERR("can't access file_path(%s)", path);
+ return -1;
+ }
+
+ dict = iniparser_load(path);
+ if (!dict) {
+ ERR("can't load file");
+ return -1;
+ }
+
+ viewer = iniparser_getstring(dict, "Notification:DefaultViewer", NULL);
+ if (viewer != NULL)
+ *default_viewer = strdup(viewer);
+
+ iniparser_freedict(dict);
+
+ return 0;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EXPORT_API int notification_launch_default_viewer(const char *default_viewer,
+ int priv_id, notification_op_type_e status, uid_t uid)
+{
+ int ret;
+ char buf[32] = {0,};
+ bundle *b = NULL;
+
+ b = bundle_create();
+ if (b == NULL) {
+ ERR("Failed to create bundle");
+ return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = aul_svc_set_appid(b, default_viewer);
+ if (ret != AUL_SVC_RET_OK) {
+ ERR("Failed to set appid to bundle[%x]", ret);
+ goto out;
+ }
+
+ snprintf(buf, sizeof(buf), "%d", priv_id);
+
+ ret = aul_svc_add_data(b, "NOTIFICATION_PRIVATE_ID", buf);
+ if (ret != AUL_SVC_RET_OK) {
+ ERR("Failed to add extra_data[%x]", ret);
+ goto out;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, sizeof(buf), "%d", status);
+
+ ret = aul_svc_add_data(b, "NOTIFICATION_OP_TYPE", buf);
+ if (ret != AUL_SVC_RET_OK) {
+ ERR("Failed to add extra_data[%x]", ret);
+ goto out;
+ }
+
+ ret = aul_svc_run_service_async_for_uid(b, 0, NULL, NULL, uid);
+ if (ret < 0) {
+ ERR("Failed to request app launch[%d]", ret);
+ } else {
+ INFO("successed to request app launch[%d],[%d]",
+ ret, uid);
+ ret = APP_CONTROL_ERROR_NONE;
+ }
+
+out:
+ if (b)
+ bundle_free(b);
+
+ if (ret == 0)
+ ret = NOTIFICATION_ERROR_NONE;
+ else
+ ret = NOTIFICATION_ERROR_IO_ERROR;
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */