Updated notification service routine
authoryoungsub ko <ys4610.ko@samsung.com>
Tue, 23 Apr 2013 06:22:25 +0000 (15:22 +0900)
committeryoungsub ko <ys4610.ko@samsung.com>
Tue, 23 Apr 2013 08:19:04 +0000 (17:19 +0900)
Change-Id: If1823adcf695328ab9d5e1e00d22599f0d4d59a0

CMakeLists.txt [changed mode: 0644->0755]
data-provider-master.manifest [changed mode: 0644->0755]
include/notification_service.h [changed mode: 0644->0755]
packaging/data-provider-master.spec [changed mode: 0644->0755]
src/main.c [changed mode: 0644->0755]
src/notification_service.c [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 660cb1b..4e70d9b
@@ -28,6 +28,7 @@ pkg_check_modules(pkg REQUIRED
        xdamage
        pkgmgr
        livebox-service
+       notification
 )
 
 SET(PACKAGE "${PROJECT_NAME}")
old mode 100644 (file)
new mode 100755 (executable)
index b3b7af7..1955ab7
@@ -13,6 +13,7 @@
                </request>
                <permit>
                        <smack permit="dbus" type="rx" />
+                       <smack permit="notification::db" type="rw" />
                </permit>
        </define>
        <request>
old mode 100644 (file)
new mode 100755 (executable)
index 94fb941..366fc4a
@@ -14,3 +14,7 @@
  * limitations under the License.
  */
 
+extern int notification_service_init(void);
+extern int notification_service_fini(void);
+
+/* End of a file */
old mode 100644 (file)
new mode 100755 (executable)
index e935e48..c35379d
@@ -32,6 +32,7 @@ BuildRequires: pkgconfig(xext)
 BuildRequires: pkgconfig(xdamage)
 BuildRequires: pkgconfig(pkgmgr)
 BuildRequires: pkgconfig(livebox-service)
+BuildRequires: pkgconfig(notification)
 BuildRequires: sec-product-features
 
 %description
old mode 100644 (file)
new mode 100755 (executable)
index ac78525..250d0fc
@@ -52,6 +52,7 @@
 #include "critical_log.h"
 #include "event.h"
 #include "shortcut_service.h"
+#include "notification_service.h"
 
 #if defined(FLOG)
 FILE *__file_log_fp;
@@ -241,6 +242,7 @@ int main(int argc, char *argv[])
        (void)util_unlink_files(SLAVE_LOG_PATH);
 
        shortcut_service_init();
+       notification_service_init();
        script_init();
 
        app_create();
@@ -253,6 +255,7 @@ int main(int argc, char *argv[])
 
        script_fini();
        shortcut_service_fini();
+       notification_service_fini();
 
        ecore_evas_shutdown();
        evas_shutdown();
old mode 100644 (file)
new mode 100755 (executable)
index 94fb941..29fd8d5
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include <stdio.h>
 
+#include <Eina.h>
+
+#include <dlog.h>
+#include <livebox-errno.h>
+#include <packet.h>
+
+#include <notification_ipc.h>
+#include <notification_noti.h>
+#include <notification_error.h>
+
+#include "service_common.h"
+#include "debug.h"
+#include "util.h"
+#include "conf.h"
+
+#ifndef NOTIFICATION_ADDR
+#define NOTIFICATION_ADDR "/tmp/.notification.service"
+#endif
+
+#ifndef NOTIFICATION_DEL_PACKET_UNIT
+#define NOTIFICATION_DEL_PACKET_UNIT 10
+#endif
+
+static struct info {
+       Eina_List *context_list;
+       struct service_context *svc_ctx;
+} s_info = {
+       .context_list = NULL, /*!< \WARN: This is only used for SERVICE THREAD */
+       .svc_ctx = NULL, /*!< \WARN: This is only used for MAIN THREAD */
+};
+
+struct context {
+       struct tcb *tcb;
+       double seq;
+};
+
+struct noti_service {
+       const char *cmd;
+       void (*handler)(struct tcb *tcb, struct packet *packet, void *data);
+};
+
+/*!
+ * FUNCTIONS to handle notifcation
+ */
+static inline int get_priv_id(int num_deleted, int *list_deleted, int index) {
+       if (index < num_deleted) {
+               return *(list_deleted + index);
+       } else {
+               return -1;
+       }
+}
+
+static inline char *get_string(char *string)
+{
+       if (string == NULL) {
+               return NULL;
+       }
+       if (string[0] == '\0') {
+               return NULL;
+       }
+
+       return string;
+}
+
+static inline struct packet *create_packet_from_deleted_list(int op_num, int *list, int start_index) {
+       return packet_create(
+               "del_noti_multiple",
+               "iiiiiiiiiii",
+               ((op_num - start_index) > NOTIFICATION_DEL_PACKET_UNIT) ? NOTIFICATION_DEL_PACKET_UNIT : op_num - start_index,
+               get_priv_id(op_num, list, start_index),
+               get_priv_id(op_num, list, start_index + 1),
+               get_priv_id(op_num, list, start_index + 2),
+               get_priv_id(op_num, list, start_index + 3),
+               get_priv_id(op_num, list, start_index + 4),
+               get_priv_id(op_num, list, start_index + 5),
+               get_priv_id(op_num, list, start_index + 6),
+               get_priv_id(op_num, list, start_index + 7),
+               get_priv_id(op_num, list, start_index + 8),
+               get_priv_id(op_num, list, start_index + 9)
+               );
+}
+
+/*!
+ * SERVICE HANDLER
+ */
+static void _handler_insert(struct tcb *tcb, struct packet *packet, void *data)
+{
+       int ret = 0;
+       int priv_id = 0;
+       struct packet *packet_reply = NULL;
+       struct packet *packet_service = NULL;
+       notification_h noti = NULL;
+
+       noti = notification_create(NOTIFICATION_TYPE_NOTI);
+       if (noti != NULL) {
+               if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
+                       ret = notification_noti_insert(noti);
+                       if (ret != NOTIFICATION_ERROR_NONE) {
+                               ErrPrint("failed to insert a notification\n");
+                               notification_free(noti);
+                               return ;
+                       }
+
+                       notification_get_id(noti, NULL, &priv_id);
+                       DbgPrint("priv_id: [%d]\n", priv_id);
+                       packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
+                       if (packet_reply) {
+                               service_common_unicast_packet(tcb, packet_reply);
+                               packet_destroy(packet_reply);
+                       }
+
+                       packet_service = notification_ipc_make_packet_from_noti(noti, "add_noti", 3);
+                       if (packet_service != NULL) {
+                               service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
+                               packet_destroy(packet_service);
+                       }
+               } else {
+                       ErrPrint("Failed to create the packet");
+               }
+               notification_free(noti);
+       }
+}
+
+static void _handler_update(struct tcb *tcb, struct packet *packet, void *data)
+{
+       int ret = 0;
+       int priv_id = 0;
+       struct packet *packet_reply = NULL;
+       struct packet *packet_service = NULL;
+       notification_h noti = NULL;
+
+       noti = notification_create(NOTIFICATION_TYPE_NOTI);
+       if (noti != NULL) {
+               if (notification_ipc_make_noti_from_packet(noti, packet) == NOTIFICATION_ERROR_NONE) {
+                       ret = notification_noti_update(noti);
+                       if (ret != NOTIFICATION_ERROR_NONE) {
+                               ErrPrint("failed to update a notification\n");
+                               notification_free(noti);
+                               return ;
+                       }
+
+                       notification_get_id(noti, NULL, &priv_id);
+                       DbgPrint("priv_id: [%d]\n", priv_id);
+                       packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
+                       if (packet_reply) {
+                               service_common_unicast_packet(tcb, packet_reply);
+                               packet_destroy(packet_reply);
+                       }
+
+                       packet_service = notification_ipc_make_packet_from_noti(noti, "update_noti", 3);
+                       if (packet_service != NULL) {
+                               service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
+                               packet_destroy(packet_service);
+                       }
+               } else {
+                       ErrPrint("Failed to create the packet");
+               }
+               notification_free(noti);
+       }
+}
+
+static void _handler_refresh(struct tcb *tcb, struct packet *packet, void *data)
+{
+       int ret = NOTIFICATION_ERROR_NONE;
+       struct packet *packet_reply = NULL;
+
+       packet_reply = packet_create_reply(packet, "i", ret);
+       if (packet_reply) {
+               service_common_unicast_packet(tcb, packet_reply);
+               packet_destroy(packet_reply);
+       }
+
+       service_common_multicast_packet(tcb, packet, TCB_CLIENT_TYPE_SERVICE);
+}
+
+static void _handler_delete_single(struct tcb *tcb, struct packet *packet, void *data)
+{
+       int ret = 0;
+       int priv_id = 0;
+       struct packet *packet_reply = NULL;
+       struct packet *packet_service = NULL;
+       char *pkgname = NULL;
+
+       if (packet_get(packet, "si", &pkgname, &priv_id) == 2) {
+               pkgname = get_string(pkgname);
+
+               ret = notification_noti_delete_by_priv_id(pkgname, priv_id);
+
+               DbgPrint("priv_id: [%d]\n", priv_id);
+               packet_reply = packet_create_reply(packet, "ii", ret, priv_id);
+               if (packet_reply) {
+                       service_common_unicast_packet(tcb, packet_reply);
+                       packet_destroy(packet_reply);
+               }
+
+               packet_service = packet_create("del_noti_single", "ii", 1, priv_id);
+               if (packet_service != NULL) {
+                       service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
+                       packet_destroy(packet_service);
+               }
+       } else {
+               ErrPrint("Failed to get data from the packet");
+       }
+}
+
+static void _handler_delete_multiple(struct tcb *tcb, struct packet *packet, void *data)
+{
+       int ret = 0;
+       struct packet *packet_reply = NULL;
+       struct packet *packet_service = NULL;
+       char *pkgname = NULL;
+       notification_type_e type = 0;
+       int num_deleted = 0;
+       int *list_deleted = NULL;
+
+       if (packet_get(packet, "si", &pkgname, &type) == 2) {
+               pkgname = get_string(pkgname);
+               DbgPrint("pkgname: [%s] type: [%d]\n", pkgname, type);
+
+               ret = notification_noti_delete_all(type, pkgname, &num_deleted, &list_deleted);
+               DbgPrint("ret: [%d] num_deleted: [%d]\n", ret, num_deleted);
+
+               packet_reply = packet_create_reply(packet, "ii", ret, num_deleted);
+               if (packet_reply) {
+                       service_common_unicast_packet(tcb, packet_reply);
+                       packet_destroy(packet_reply);
+               }
+
+               if (num_deleted > 0) {
+                       if (num_deleted <= NOTIFICATION_DEL_PACKET_UNIT) {
+                               packet_service = create_packet_from_deleted_list(num_deleted, list_deleted, 0);
+
+                               if (packet_service) {
+                                       service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
+                                       packet_destroy(packet_service);
+                               }
+                       } else {
+                               int set = 0;
+                               int set_total = num_deleted / NOTIFICATION_DEL_PACKET_UNIT;
+
+                               for (set = 0; set <= set_total; set++) {
+                                       packet_service = create_packet_from_deleted_list(num_deleted,
+                                                       list_deleted, set * NOTIFICATION_DEL_PACKET_UNIT);
+
+                                       if (packet_service) {
+                                               service_common_multicast_packet(tcb, packet_service, TCB_CLIENT_TYPE_SERVICE);
+                                               packet_destroy(packet_service);
+                                       }
+                               }
+                       }
+               }
+       } else {
+               ErrPrint("Failed to get data from the packet");
+       }
+}
+
+/*!
+ * SERVICE THREAD
+ */
+static int service_thread_main(struct tcb *tcb, struct packet *packet, void *data)
+{
+       int i = 0;
+       const char *command;
+       static struct noti_service service_req_table[] = {
+               {
+                       .cmd = "add_noti",
+                       .handler = _handler_insert,
+               },
+               {
+                       .cmd = "update_noti",
+                       .handler = _handler_update,
+               },
+               {
+                       .cmd = "refresh_noti",
+                       .handler = _handler_refresh,
+               },
+               {
+                       .cmd = "del_noti_single",
+                       .handler = _handler_delete_single,
+               },
+               {
+                       .cmd = "del_noti_multiple",
+                       .handler = _handler_delete_multiple,
+               },
+               {
+                       .cmd = NULL,
+                       .handler = NULL,
+               },
+       };
+
+       DbgPrint("TCB: %p, Packet: %p\n", tcb, packet);
+
+       command = packet_command(packet);
+       if (!command) {
+               ErrPrint("Invalid command\n");
+               return -EINVAL;
+       }
+       DbgPrint("Command: %s, Packet type[%d]\n", command, packet_type(packet));
+
+       switch (packet_type(packet)) {
+       case PACKET_REQ:
+               /* Need to send reply packet */
+               DbgPrint("REQ: Command: [%s]\n", command);
+
+               for (i = 0; service_req_table[i].cmd; i++) {
+                       if (strcmp(service_req_table[i].cmd, command))
+                               continue;
+
+                       service_req_table[i].handler(tcb, packet, data);
+               }
+               break;
+       case PACKET_REQ_NOACK:
+               DbgPrint("REQ_NOACK: Command: [%s]\n", command);
+               if (!strcmp(command, "service_register")) {
+                       tcb_client_type_set(tcb, TCB_CLIENT_TYPE_SERVICE);
+               }
+               break;
+       case PACKET_ACK:
+               break;
+       default:
+               ErrPrint("Packet type is not valid[%s]\n", command);
+               return -EINVAL;
+       }
+
+       /*!
+        * return value has no meanning,
+        * it will be printed by dlogutil.
+        */
+       return 0;
+}
+
+
+/*!
+ * MAIN THREAD
+ * Do not try to do anyother operation in these functions
+ */
+HAPI int notification_service_init(void)
+{
+       if (s_info.svc_ctx) {
+               ErrPrint("Already initialized\n");
+               return LB_STATUS_ERROR_ALREADY;
+       }
+
+       s_info.svc_ctx = service_common_create(NOTIFICATION_ADDR, service_thread_main, NULL);
+       if (!s_info.svc_ctx) {
+               ErrPrint("Unable to activate service thread\n");
+               return LB_STATUS_ERROR_FAULT;
+       }
+
+       DbgPrint("Successfully initiated\n");
+       return LB_STATUS_SUCCESS;
+}
+
+HAPI int notification_service_fini(void)
+{
+       if (!s_info.svc_ctx)
+               return LB_STATUS_ERROR_INVALID;
+
+       service_common_destroy(s_info.svc_ctx);
+       DbgPrint("Successfully Finalized\n");
+       return LB_STATUS_SUCCESS;
+}
+
+/* End of a file */