Implement logic for posts notification with event handler callback 16/88616/4 accepted/tizen/common/20160926.154203 accepted/tizen/ivi/20160927.020942 accepted/tizen/mobile/20160927.020948 accepted/tizen/tv/20160927.020921 accepted/tizen/wearable/20160927.020932 submit/tizen/20160926.012336
authorseungha.son <seungha.son@samsung.com>
Tue, 20 Sep 2016 04:23:20 +0000 (13:23 +0900)
committerseungha.son <seungha.son@samsung.com>
Fri, 23 Sep 2016 04:17:51 +0000 (13:17 +0900)
Signed-off-by: seungha.son <seungha.son@samsung.com>
Change-Id: Ied3e6406287040d47873a58c3bc2cefc1c795376

include/notification_service.h
include/service_common.h
src/notification_service.c
src/service_common.c

index 8d771c1..18f0b79 100755 (executable)
@@ -19,7 +19,7 @@
 extern int notification_service_init(void);
 extern int notification_service_fini(void);
 
-int notification_add_noti(GVariant *parameters, GVariant **reply_body, uid_t uid);
+int notification_add_noti(GVariant *parameters, GVariant **reply_body, const char *sender, uid_t uid);
 int notification_update_noti(GVariant *parameters, GVariant **reply_body, uid_t uid);
 int notification_refresh_noti(GVariant *parameters, GVariant **reply_body, uid_t uid);
 int notification_del_noti_single(GVariant *parameters, GVariant **reply_body, uid_t uid);
@@ -42,6 +42,7 @@ int notification_get_noti_package_template(GVariant *parameters, GVariant **repl
 int notification_get_block_state(GVariant *parameters, GVariant **reply_body, uid_t uid);
 int notification_load_dnd_allow_exception(GVariant *parameters, GVariant **reply_body, uid_t uid);
 int notification_update_dnd_allow_exception(GVariant *parameters, GVariant **reply_body, uid_t uid);
+int notification_send_noti_event(GVariant *parameters, GVariant **reply_body);
 int notification_register_dbus_interface();
 
 /* End of a file */
index 0b3af0d..955a13a 100755 (executable)
@@ -50,6 +50,7 @@ typedef struct monitoring_info {
 
 void print_noti(notification_h noti);
 int send_notify(GVariant *body, char *cmd, GList *monitoring_app_list, char *interface_name);
+int send_event_notify_by_busname(GVariant *body, char *cmd, char *busname, char *interface_name);
 int service_register(GVariant *parameters, GVariant **reply_body, const gchar *sender,
        GBusNameAppearedCallback name_appeared_handler,
        GBusNameVanishedCallback name_vanished_handler,
index c56abc5..45e5442 100755 (executable)
@@ -38,6 +38,7 @@
 #include <notification_db.h>
 
 #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 NOTI_TEMPLATE_LIMIT 10
 #define BUF_LEN 256
 
@@ -54,6 +55,13 @@ typedef struct _dnd_alarm_id {
        alarm_id_t dnd_end_id;
 } dnd_alarm_id_s;
 
+static GHashTable *__event_sender_hash;
+
+typedef struct _event_sender_info {
+       int priv_id;
+       char *busname;
+} event_sender_info_s;
+
 /*!
  * SERVICE HANDLER
  */
@@ -102,7 +110,7 @@ static void _noti_dbus_method_call_handler(GDBusConnection *conn,
        else if (g_strcmp0(method_name, "update_noti") == 0)
                ret = notification_update_noti(parameters, &reply_body, uid);
        else if (g_strcmp0(method_name, "add_noti") == 0)
-               ret = notification_add_noti(parameters, &reply_body, uid);
+               ret = notification_add_noti(parameters, &reply_body, sender, uid);
        else if (g_strcmp0(method_name, "refresh_noti") == 0)
                ret = notification_refresh_noti(parameters, &reply_body, uid);
        else if (g_strcmp0(method_name, "del_noti_single") == 0)
@@ -141,6 +149,8 @@ static void _noti_dbus_method_call_handler(GDBusConnection *conn,
                ret = notification_load_dnd_allow_exception(parameters, &reply_body, uid);
        else if (g_strcmp0(method_name, "update_dnd_allow_exception") == 0)
                ret = notification_update_dnd_allow_exception(parameters, &reply_body, uid);
+       else if (g_strcmp0(method_name, "send_noti_event") == 0)
+               ret = notification_send_noti_event(parameters, &reply_body);
 
        if (ret == NOTIFICATION_ERROR_NONE) {
                DbgPrint("notification service success : %d", ret);
@@ -154,7 +164,6 @@ static void _noti_dbus_method_call_handler(GDBusConnection *conn,
                                ret,
                                "notification service error");
        }
-
 }
 
 static const GDBusInterfaceVTable _noti_interface_vtable = {
@@ -313,6 +322,11 @@ int notification_register_dbus_interface()
                        "          <arg type='a(v)' name='dnd_allow_exception' direction='out'/>"
                        "        </method>"
 
+                       "        <method name='send_noti_event'>"
+                       "          <arg type='v' name='noti' direction='in'/>"
+                       "          <arg type='i' name='event_type' direction='in'/>"
+                       "        </method>"
+
                        "        <method name='post_toast'>"
                        "        </method>"
                        "  </interface>"
@@ -321,6 +335,39 @@ int notification_register_dbus_interface()
        return service_common_register_dbus_interface(introspection_xml, _noti_interface_vtable);
 }
 
+static void __free_event_list(gpointer data)
+{
+       event_sender_info_s *info = (event_sender_info_s *)data;
+
+       if (info) {
+               if (info->busname)
+                       free(info->busname);
+               free(info);
+       }
+}
+
+static void __free_event_hash(gpointer data)
+{
+       GList *event_list = (GList *)data;
+       if (event_list)
+               g_list_free_full(event_list, __free_event_list);
+}
+
+static gint __priv_id_compare(gconstpointer a, gconstpointer b)
+{
+       event_sender_info_s *info = NULL;
+
+       if (!a)
+               return -1;
+
+       info = (event_sender_info_s *)a;
+
+       if (info->priv_id == GPOINTER_TO_UINT(b))
+               return 0;
+
+       return 1;
+}
+
 /* add noti */
 static int _add_noti(GVariant **reply_body, notification_h noti, GList *monitoring_list)
 {
@@ -330,19 +377,23 @@ static int _add_noti(GVariant **reply_body, notification_h noti, GList *monitori
 
        print_noti(noti);
        ret = notification_noti_insert(noti);
-       notification_get_id(noti, NULL, &priv_id);
-       DbgPrint("priv_id: [%d]", priv_id);
-
        if (ret != NOTIFICATION_ERROR_NONE) {
                ErrPrint("failed to update a notification:%d\n", ret);
                return ret;
        }
 
+       ret = notification_get_id(noti, NULL, &priv_id);
+       if (ret != NOTIFICATION_ERROR_NONE) {
+               ErrPrint("failed to gets priv_id:%d\n", ret);
+               return ret;
+       }
+
        body = notification_ipc_make_gvariant_from_noti(noti, true);
        if (body == NULL) {
                ErrPrint("cannot make gvariant to noti");
                return NOTIFICATION_ERROR_OUT_OF_MEMORY;
        }
+
        ret = send_notify(body, "add_noti_notify", monitoring_list, PROVIDER_NOTI_INTERFACE_NAME);
        g_variant_unref(body);
 
@@ -416,9 +467,52 @@ static int _validate_and_set_param_uid_with_uid(uid_t uid, uid_t *param_uid)
        return ret;
 }
 
-int notification_add_noti(GVariant *parameters, GVariant **reply_body, uid_t uid)
+static int __add_sender_info(int priv_id, const char *busname, uid_t uid)
+{
+       GList *event_list = NULL;
+       GList *find_list = NULL;
+       event_sender_info_s *sender_info;
+
+       if (__event_sender_hash == NULL)
+               __event_sender_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, __free_event_hash);
+
+       event_list = g_hash_table_lookup(__event_sender_hash, GUINT_TO_POINTER(uid));
+
+       sender_info = (event_sender_info_s *)malloc(sizeof(event_sender_info_s));
+       if (sender_info == NULL) {
+               DbgPrint("malloc failed");
+               return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+       }
+
+       sender_info->priv_id = priv_id;
+       sender_info->busname = strdup(busname);
+
+       if (event_list == NULL) {
+               event_list = g_list_append(event_list, sender_info);
+               g_hash_table_insert(__event_sender_hash, GUINT_TO_POINTER(uid), event_list);
+       } else {
+               event_list = g_list_first(event_list);
+               find_list = g_list_find_custom(event_list, GUINT_TO_POINTER(priv_id),
+                                              (GCompareFunc)__priv_id_compare);
+               if (find_list == NULL) {
+                       event_list = g_list_append(event_list, sender_info);
+               } else {
+                       if (sender_info) {
+                               if (sender_info->busname)
+                                       free(sender_info->busname);
+                               free(sender_info);
+                       }
+               }
+       }
+
+       return NOTIFICATION_ERROR_NONE;
+}
+
+int notification_add_noti(GVariant *parameters, GVariant **reply_body, const char *sender, uid_t uid)
 {
        int ret;
+       int priv_id;
+       bool event_flag;
        notification_h noti;
        GVariant *body = NULL;
        GList *monitoring_list = NULL;
@@ -442,6 +536,17 @@ int notification_add_noti(GVariant *parameters, GVariant **reply_body, uid_t uid
                else if (ret == NOTIFICATION_ERROR_ALREADY_EXIST_ID)
                        ret = _update_noti(reply_body, noti, monitoring_list);
 
+               ret = notification_get_event_flag(noti, &event_flag);
+               if (ret != NOTIFICATION_ERROR_NONE)
+                       return ret;
+
+               if (event_flag == true) {
+                       ret = notification_get_id(noti, NULL, &priv_id);
+                       if (ret != NOTIFICATION_ERROR_NONE)
+                               return ret;
+
+                       __add_sender_info(priv_id, sender, noti_uid);
+               }
                notification_free(noti);
        } else {
                ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
@@ -840,6 +945,43 @@ int notification_refresh_noti(GVariant *parameters, GVariant **reply_body, uid_t
        return ret;
 }
 
+static int __delete_sender_info(int priv_id, uid_t uid)
+{
+       int ret = NOTIFICATION_ERROR_NONE;
+       event_sender_info_s *info;
+       GList *event_list = NULL;
+       GList *delete_list = NULL;
+       GVariant *body = NULL;
+
+       if (__event_sender_hash == NULL)
+               return NOTIFICATION_ERROR_NONE;
+
+       event_list = g_hash_table_lookup(__event_sender_hash, GUINT_TO_POINTER(uid));
+
+       if (event_list != NULL) {
+               event_list = g_list_first(event_list);
+               delete_list = g_list_find_custom(event_list, GUINT_TO_POINTER(priv_id),
+                                                (GCompareFunc)__priv_id_compare);
+               if (delete_list != NULL) {
+                       info = g_list_nth_data(delete_list, 0);
+                       body = g_variant_new("(i)", priv_id);
+                       ret = send_event_notify_by_busname(body, "delete_noti", info->busname, PROVIDER_NOTI_EVENT_INTERFACE_NAME);
+                       g_variant_unref(body);
+                       if (ret != NOTIFICATION_ERROR_NONE) {
+                               ErrPrint("failed to send event notify:%d\n", ret);
+                               return ret;
+                       }
+                       event_list = g_list_remove(g_list_first(event_list), info);
+                       if (info->busname)
+                               free(info->busname);
+                       if (info)
+                               free(info);
+               }
+       }
+
+       return ret;
+}
+
 /* del_noti_single */
 int notification_del_noti_single(GVariant *parameters, GVariant **reply_body, uid_t uid)
 {
@@ -875,6 +1017,10 @@ int notification_del_noti_single(GVariant *parameters, GVariant **reply_body, ui
                        ErrPrint("failed to send notify:%d\n", ret);
                        return ret;
                }
+
+               ret = __delete_sender_info(priv_id, uid);
+               if (ret != NOTIFICATION_ERROR_NONE)
+                       return ret;
        }
 
        *reply_body = g_variant_new("(i)", priv_id);
@@ -907,6 +1053,7 @@ int notification_del_noti_multiple(GVariant *parameters, GVariant **reply_body,
                return ret;
 
        ret = notification_noti_delete_all(type, pkgname, &num_deleted, &list_deleted, param_uid);
+
        DbgPrint("ret: [%d] num_deleted: [%d]\n", ret, num_deleted);
 
        if (ret != NOTIFICATION_ERROR_NONE) {
@@ -925,15 +1072,20 @@ int notification_del_noti_multiple(GVariant *parameters, GVariant **reply_body,
                deleted_noti_list = g_variant_new("(a(i)i)", builder, param_uid);
                monitoring_list = (GList *)g_hash_table_lookup(_monitoring_hash, GUINT_TO_POINTER(param_uid));
                ret = send_notify(deleted_noti_list, "delete_multiple_notify", monitoring_list, PROVIDER_NOTI_INTERFACE_NAME);
-
                g_variant_builder_unref(builder);
                g_variant_unref(deleted_noti_list);
-               free(list_deleted);
-
                if (ret != NOTIFICATION_ERROR_NONE) {
                        ErrPrint("failed to send notify:%d\n", ret);
                        return ret;
                }
+
+               for (i = 0; i < num_deleted; i++) {
+                       ret = __delete_sender_info(*(list_deleted + i), param_uid);
+                       if (ret != NOTIFICATION_ERROR_NONE)
+                               return ret;
+               }
+
+               free(list_deleted);
        }
 
        *reply_body = g_variant_new("(i)", num_deleted);
@@ -1525,6 +1677,87 @@ int notification_update_dnd_allow_exception(GVariant *parameters, GVariant **rep
        return ret;
 }
 
+static char *__find_busname_by_priv_id(int priv_id, uid_t uid)
+{
+       char *busname = NULL;
+       event_sender_info_s *event_info;
+       GList *event_list;
+       GList *find_list;
+
+       if (__event_sender_hash == NULL)
+               return NULL;
+
+       event_list = g_hash_table_lookup(__event_sender_hash, GUINT_TO_POINTER(uid));
+       if (event_list == NULL)
+               return NULL;
+
+       event_list = g_list_first(event_list);
+       find_list = g_list_find_custom(event_list, GUINT_TO_POINTER(priv_id),
+                                      (GCompareFunc)__priv_id_compare);
+
+       if (find_list) {
+               event_info = g_list_nth_data(find_list, 0);
+               busname = strdup(event_info->busname);
+       } else {
+               return NULL;
+       }
+
+       return busname;
+}
+
+int notification_send_noti_event(GVariant *parameters, GVariant **reply_body)
+{
+       int ret;
+       int event_type;
+       int priv_id;
+       char *busname = NULL;
+       GVariant *coupled_body = NULL;
+       GVariant *body = NULL;
+       notification_h noti;
+       uid_t noti_uid;
+
+       noti = notification_create(NOTIFICATION_TYPE_NOTI);
+
+       if (noti != NULL) {
+               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);
+               if (ret != NOTIFICATION_ERROR_NONE) {
+                       ErrPrint("failed to make a notification from gvariant");
+                       return ret;
+               }
+
+               g_variant_unref(coupled_body);
+               g_variant_unref(body);
+
+               ret = notification_get_id(noti, NULL, &priv_id);
+               if (ret != NOTIFICATION_ERROR_NONE)
+                       return ret;
+
+               ret = notification_get_uid(noti, &noti_uid);
+               if (ret != NOTIFICATION_ERROR_NONE)
+                       return ret;
+
+               busname = __find_busname_by_priv_id(priv_id, noti_uid);
+               if (busname == NULL)
+                       return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+               ret = send_event_notify_by_busname(parameters, "send_event", busname, PROVIDER_NOTI_EVENT_INTERFACE_NAME);
+               notification_free(noti);
+               free(busname);
+       } else {
+               ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
+       }
+
+       *reply_body = g_variant_new("()");
+       if (*reply_body == NULL) {
+               ErrPrint("cannot make reply body");
+               return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+       }
+       return ret;
+}
+
 static void _notification_data_init(void)
 {
        int property = 0;
@@ -1547,7 +1780,7 @@ static void _notification_data_init(void)
                        notification_get_type(noti, &noti_type);
 
                        if (noti_type == NOTIFICATION_TYPE_ONGOING
-                                       || property & NOTIFICATION_PROP_VOLATILE_DISPLAY) {
+                           || property & NOTIFICATION_PROP_VOLATILE_DISPLAY) {
                                notification_noti_delete_by_priv_id(noti_pkgname, priv_id);
                        }
                }
index e1e044c..63f0ad1 100755 (executable)
@@ -188,6 +188,33 @@ int send_notify(GVariant *body, char *cmd, GList *monitoring_app_list, char *int
        return SERVICE_COMMON_ERROR_NONE;
 }
 
+int send_event_notify_by_busname(GVariant *body, char *cmd, char *busname, char *interface_name)
+{
+       GError *err = NULL;
+
+       if (g_variant_is_floating(body))
+               g_variant_ref(body);
+
+       DbgPrint("emit signal to : %s", busname);
+       if (g_dbus_connection_emit_signal(_gdbus_conn,
+                                         busname,
+                                         PROVIDER_OBJECT_PATH,
+                                         interface_name,
+                                         cmd,
+                                         body,
+                                         &err) == FALSE) {
+               ErrPrint("g_dbus_connection_emit_signal() is failed");
+               if (err != NULL) {
+                       ErrPrint("g_dbus_connection_emit_signal() err : %s",
+                                       err->message);
+                       g_error_free(err);
+               }
+               return SERVICE_COMMON_ERROR_IO_ERROR;
+       }
+       DbgPrint("provider signal send event notify done : busname[%s] cmd[%s]", busname, cmd);
+       return SERVICE_COMMON_ERROR_NONE;
+}
+
 /* register service */
 
 static int _monitoring_app_list_compare_cb(gconstpointer a, gconstpointer b)