Sync with the latest code of phone profile
[platform/framework/web/data-provider-master.git] / src / utility_service.c
index 0b01608..e3d9837 100644 (file)
 #include "conf.h"
 
 #ifndef SVC_PKG
-#define SVC_PKG                "org.tizen.data-provider-slave.icon"
+#define SVC_PKG                "com.samsung.data-provider-slave.icon"
 #endif
 
 #ifndef LAUNCH_TIMEOUT
 #define LAUNCH_TIMEOUT 10.0f
 #endif
 
+#ifndef TTL_TIMEOUT
+#define TTL_TIMEOUT    30.0f
+#endif
+
 static struct info {
        Eina_List *pending_list;
        Eina_List *context_list;
@@ -47,9 +51,11 @@ static struct info {
 
        struct tcb *svc_daemon;
        int svc_daemon_is_launched;
+       int svc_daemon_pid;
 
        struct service_event_item *launch_timer; 
        struct service_event_item *delay_launcher;
+       struct service_event_item *ttl_timer;
 } s_info = {
        .pending_list = NULL,
        .context_list = NULL, /*!< \WARN: This is only used for SERVICE THREAD */
@@ -57,9 +63,11 @@ static struct info {
 
        .svc_daemon = NULL,
        .svc_daemon_is_launched = 0,
+       .svc_daemon_pid = -1,
 
        .launch_timer = NULL,
        .delay_launcher = NULL,
+       .ttl_timer = NULL,
 };
 
 struct pending_item {
@@ -74,7 +82,7 @@ struct context {
 
 static int lazy_launcher_cb(struct service_context *svc_ctx, void *data);
 
-static inline int put_reply_tcb(struct tcb *tcb, double seq)
+static int put_reply_tcb(struct tcb *tcb, double seq)
 {
        struct context *ctx;
 
@@ -88,6 +96,7 @@ static inline int put_reply_tcb(struct tcb *tcb, double seq)
        ctx->seq = seq;
 
        s_info.context_list = eina_list_append(s_info.context_list, ctx);
+
        return LB_STATUS_SUCCESS;
 }
 
@@ -99,12 +108,13 @@ static inline struct tcb *get_reply_tcb(double seq)
        struct tcb *tcb;
 
        EINA_LIST_FOREACH_SAFE(s_info.context_list, l, n, ctx) {
-               if (ctx->seq != seq)
+               if (ctx->seq != seq) {
                        continue;
+               }
 
                s_info.context_list = eina_list_remove(s_info.context_list, ctx);
                tcb = ctx->tcb;
-               free(ctx);
+               DbgFree(ctx);
                return tcb;
        }
 
@@ -120,18 +130,26 @@ static inline int flush_pended_request(void)
        int ret;
 
        EINA_LIST_FREE(s_info.pending_list, item) {
-               ret = service_common_unicast_packet(s_info.svc_daemon, item->packet);
+               if (tcb_is_valid(s_info.svc_ctx, s_info.svc_daemon) >= 0) {
+                       ret = service_common_unicast_packet(s_info.svc_daemon, item->packet);
+               } else {
+                       ret = -EFAULT;
+               }
+
                if (ret < 0) {
-                       struct packet *reply;
-                       reply = packet_create_reply(item->packet, "i", ret);
-                       if (service_common_unicast_packet(item->tcb, reply) < 0)
-                               ErrPrint("Unable to send packet\n");
-                       packet_destroy(reply);
+                       if (tcb_is_valid(s_info.svc_ctx, item->tcb) >= 0) {
+                               struct packet *reply;
+                               reply = packet_create_reply(item->packet, "i", ret);
+                               if (service_common_unicast_packet(item->tcb, reply) < 0) {
+                                       ErrPrint("Unable to send packet\n");
+                               }
+                               packet_destroy(reply);
+                       }
                } else {
                        put_reply_tcb(item->tcb, packet_seq(item->packet));
                }
                packet_unref(item->packet);
-               free(item);
+               DbgFree(item);
        }
 
        return 0;
@@ -150,7 +168,7 @@ static inline int put_pended_request(struct tcb *tcb, struct packet *packet)
        item->tcb = tcb;
        item->packet = packet_ref(packet);
        if (!item->packet) {
-               free(item);
+               DbgFree(item);
                ErrPrint("Unable to ref packet\n");
                return LB_STATUS_ERROR_FAULT;
        }
@@ -165,57 +183,73 @@ static int launch_timeout_cb(struct service_context *svc_ctx, void *data)
        struct packet *reply;
 
        EINA_LIST_FREE(s_info.pending_list, item) {
-               reply = packet_create_reply(item->packet, "i", -EFAULT);
-               if (!reply) {
-                       ErrPrint("Unable to create a packet\n");
+               if (tcb_is_valid(s_info.svc_ctx, item->tcb) >= 0) {
+                       reply = packet_create_reply(item->packet, "i", -EFAULT);
+                       if (!reply) {
+                               ErrPrint("Unable to create a packet\n");
+                       } else {
+                               int ret;
+
+                               ret = service_common_unicast_packet(item->tcb, reply);
+                               if (ret < 0) {
+                                       ErrPrint("Failed to send reply packet: %d\n", ret);
+                               }
+
+                               packet_destroy(reply);
+                       }
                } else {
-                       int ret;
-
-                       ret = service_common_unicast_packet(item->tcb, reply);
-                       if (ret < 0)
-                               ErrPrint("Failed to send reply packet: %d\n", ret);
-
-                       packet_destroy(reply);
+                       ErrPrint("TCB is already terminated\n");
                }
 
                packet_unref(item->packet);
-               free(item);
+               DbgFree(item);
        }
 
        s_info.launch_timer = NULL;
        s_info.svc_daemon_is_launched = 0;
+       s_info.svc_daemon_pid = -1;
        return -ECANCELED; /* Delete this timer */
 }
 
-static inline int launch_svc(struct service_context *svc_ctx)
+static int launch_svc(struct service_context *svc_ctx)
 {
        pid_t pid;
        int ret = LB_STATUS_SUCCESS;
 
        pid = aul_launch_app(SVC_PKG, NULL);
-       if (pid > 0) {
-               s_info.svc_daemon_is_launched = 1;
-               s_info.launch_timer = service_common_add_timer(svc_ctx, LAUNCH_TIMEOUT, launch_timeout_cb, NULL);
-               if (!s_info.launch_timer)
-                       ErrPrint("Unable to create launch timer\n");
-       } else if (pid == AUL_R_ETIMEOUT || pid == AUL_R_ECOMM) {
-               s_info.svc_daemon_is_launched = 1;
-               CRITICAL_LOG("SVC launch failed with timeout(%d), But waiting response\n", pid);
-               s_info.launch_timer = service_common_add_timer(svc_ctx, LAUNCH_TIMEOUT, launch_timeout_cb, NULL);
-               if (!s_info.launch_timer)
-                       ErrPrint("Unable to create launch timer\n");
-       } else if (pid == AUL_R_ETERMINATING) {
+       switch (pid) {
+       //case AUL_R_EHIDDENFORGUEST:   /**< App hidden for guest mode */
+       case AUL_R_ENOLAUNCHPAD:        /**< no launchpad */
+       case AUL_R_EILLACC:             /**< Illegal Access */
+       case AUL_R_EINVAL:              /**< Invalid argument */
+       case AUL_R_ENOINIT:             /**< AUL handler NOT initialized */
+       case AUL_R_ERROR:               /**< General error */
+               ErrPrint("Failed to launch an app: %s(%d)\n", SVC_PKG, pid);
+               ret = LB_STATUS_ERROR_FAULT;
+               break;
+       case AUL_R_ETIMEOUT:            /**< Timeout */
+       case AUL_R_ECOMM:               /**< Comunication Error */
+       case AUL_R_ETERMINATING:        /**< application terminating */
+       case AUL_R_ECANCELED:           /**< Operation canceled */
                /* Need time to launch app again */
-               ErrPrint("Terminating now, try to launch this after few sec later\n");
+               ErrPrint("Terminating now, try to launch this after few sec later: %s(%d)\n", SVC_PKG, pid);
                s_info.svc_daemon_is_launched = 1;
                s_info.delay_launcher = service_common_add_timer(svc_ctx, LAUNCH_TIMEOUT, lazy_launcher_cb, NULL);
                if (!s_info.delay_launcher) {
                        ErrPrint("Unable to add delay launcher\n");
                        ret = LB_STATUS_ERROR_FAULT;
                }
-       } else {
-               ErrPrint("Failed to launch an app: %s(%d)\n", SVC_PKG, pid);
-               ret = LB_STATUS_ERROR_FAULT;
+               break;
+       case AUL_R_LOCAL:               /**< Launch by himself */
+       case AUL_R_OK:                  /**< General success */
+       default:
+               DbgPrint("Launched: %s(%d)\n", SVC_PKG, pid);
+               s_info.svc_daemon_is_launched = 1;
+               s_info.svc_daemon_pid = pid;
+               s_info.launch_timer = service_common_add_timer(svc_ctx, LAUNCH_TIMEOUT, launch_timeout_cb, NULL);
+               if (!s_info.launch_timer) {
+                       ErrPrint("Unable to create launch timer\n");
+               }
        }
 
        return ret;
@@ -223,8 +257,21 @@ static inline int launch_svc(struct service_context *svc_ctx)
 
 static int lazy_launcher_cb(struct service_context *svc_ctx, void *data)
 {
-       s_info.svc_daemon_is_launched = launch_svc(svc_ctx) == LB_STATUS_SUCCESS;
        s_info.delay_launcher = NULL;
+
+       (void)launch_svc(svc_ctx);
+       return -ECANCELED;
+}
+
+static int ttl_timer_cb(struct service_context *svc_ctx, void *data)
+{
+       DbgPrint("TTL Timer is expired: PID(%d)\n", s_info.svc_daemon_pid);
+       (void)aul_terminate_pid(s_info.svc_daemon_pid);
+
+       s_info.ttl_timer = NULL;
+       s_info.svc_daemon_is_launched = 0;
+       s_info.svc_daemon_pid = -1;
+       s_info.svc_daemon = NULL;
        return -ECANCELED;
 }
 
@@ -235,14 +282,20 @@ static int service_thread_main(struct tcb *tcb, struct packet *packet, void *dat
        int ret;
 
        if (!packet) {
-               DbgPrint("TCB %p is terminated (NIL packet)\n", tcb);
+               DbgPrint("TCB %p is terminated (NIL packet), %d\n", tcb, s_info.svc_daemon_pid);
 
                if (tcb == s_info.svc_daemon) {
                        s_info.svc_daemon = NULL;
                        s_info.svc_daemon_is_launched = 0;
+                       s_info.svc_daemon_pid = -1;
+
+                       if (s_info.ttl_timer) {
+                               service_common_del_timer(tcb_svc_ctx(tcb), s_info.ttl_timer);
+                               s_info.ttl_timer = NULL;
+                       }
                }
 
-               return 0;
+               return LB_STATUS_SUCCESS;
        }
 
        cmd = packet_command(packet);
@@ -255,20 +308,27 @@ static int service_thread_main(struct tcb *tcb, struct packet *packet, void *dat
        case PACKET_REQ:
                if (!s_info.svc_daemon_is_launched) {
                        ret = launch_svc(tcb_svc_ctx(tcb));
-                       if (ret != LB_STATUS_SUCCESS)
+                       if (ret != LB_STATUS_SUCCESS) {
                                goto reply_out;
+                       }
                }
 
                if (!s_info.svc_daemon) {
                        ret = put_pended_request(tcb, packet);
-                       if (ret < 0)
+                       if (ret < 0) {
                                goto reply_out;
-               } else {
+                       }
+               } else if (tcb_is_valid(s_info.svc_ctx, s_info.svc_daemon) >= 0) { 
                        ret = service_common_unicast_packet(s_info.svc_daemon, packet);
-                       if (ret <0)
+                       if (ret <0) {
                                goto reply_out;
+                       }
 
                        put_reply_tcb(tcb, packet_seq(packet));
+
+                       if (s_info.ttl_timer && service_common_update_timer(s_info.ttl_timer, TTL_TIMEOUT) < 0) {
+                               ErrPrint("Failed to update timer\n");
+                       }
                }
 
                break;
@@ -289,6 +349,19 @@ static int service_thread_main(struct tcb *tcb, struct packet *packet, void *dat
                                s_info.launch_timer = NULL;
                        }
 
+                       s_info.ttl_timer = service_common_add_timer(tcb_svc_ctx(tcb), TTL_TIMEOUT, ttl_timer_cb, NULL);
+                       if (!s_info.ttl_timer) {
+                               ErrPrint("Failed to add TTL timer\n");
+                               if (s_info.svc_daemon_pid > 0) {
+                                       ret = aul_terminate_pid(s_info.svc_daemon_pid);
+                                       ErrPrint("Terminate: %d\n", ret);
+                                       s_info.svc_daemon_pid = -1;
+                               }
+                               s_info.svc_daemon_is_launched = 0;
+                               return LB_STATUS_ERROR_FAULT;
+                       }
+                       DbgPrint("TTL Timer is added: %p\n", s_info.ttl_timer);
+
                        s_info.svc_daemon = tcb;
                        flush_pended_request();
                }
@@ -297,10 +370,17 @@ static int service_thread_main(struct tcb *tcb, struct packet *packet, void *dat
                tcb = get_reply_tcb(packet_seq(packet));
                if (!tcb) {
                        ErrPrint("Unable to find reply tcb\n");
-               } else {
-                       ret = service_common_unicast_packet(tcb, packet);
-                       if (ret < 0)
-                               ErrPrint("Unable to forward the reply packet\n");
+                       break;
+               }
+
+               if (tcb_is_valid(s_info.svc_ctx, tcb) < 0) {
+                       ErrPrint("TCB is not valid\n");
+                       break;
+               }
+
+               ret = service_common_unicast_packet(tcb, packet);
+               if (ret < 0) {
+                       ErrPrint("Unable to forward the reply packet\n");
                }
                break;
        default:
@@ -313,8 +393,9 @@ static int service_thread_main(struct tcb *tcb, struct packet *packet, void *dat
 reply_out:
        ErrPrint("Error: %d\n", ret);
        reply = packet_create_reply(packet, "i", ret);
-       if (service_common_unicast_packet(tcb, reply) < 0)
+       if (service_common_unicast_packet(tcb, reply) < 0) {
                ErrPrint("Unable to send reply packet\n");
+       }
        packet_destroy(reply);
        return ret;
 }
@@ -356,8 +437,9 @@ int utility_service_init(void)
 
 int utility_service_fini(void)
 {
-       if (!s_info.svc_ctx)
+       if (!s_info.svc_ctx) {
                return LB_STATUS_ERROR_INVALID;
+       }
 
        service_common_destroy(s_info.svc_ctx);
        s_info.svc_ctx = NULL;