Update Coding conention.
[platform/framework/web/data-provider-slave.git] / src / lb.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h> /* exit */
19 #include <errno.h>
20 #include <unistd.h> /* access */
21
22 #include <Ecore.h>
23 #include <Eina.h>
24
25 #include <dlog.h>
26 #include <provider.h>
27 #include <livebox.h>
28 #include <livebox-errno.h>
29
30 #include "critical_log.h"
31 #include "debug.h"
32 #include "conf.h"
33 #include "so_handler.h"
34 #include "lb.h"
35 #include "update_monitor.h"
36 #include "fault.h"
37 #include "util.h"
38
39 #define IS_LB_SHOWN(itm) (!(itm)->inst->item->has_livebox_script || ((itm)->inst->item->has_livebox_script && (itm)->is_lb_show))
40
41 int errno;
42
43 #define UPDATE_ITEM_DELETED     (-1)
44 #define UPDATE_INVOKED          (-2)
45 #define UPDATE_NOT_INVOKED      (0)
46
47 struct item {
48         Ecore_Timer *timer;
49         struct instance *inst;
50         int monitor_cnt;
51         Ecore_Timer *monitor;
52         int deleteme;
53         double update_interval;
54         int heavy_updating; /* Only for debugging message */
55         int is_paused; /* 1 is paused, 0 is resumed */
56         double sleep_at;
57
58         unsigned int updated_in_pause;
59
60         int is_lb_show;
61         int is_pd_show;
62         int is_lb_updated;
63 };
64
65 static struct info {
66         Eina_List *item_list;
67         struct item *update;
68         Eina_List *pending_list;
69         Ecore_Timer *pending_timer;
70         Eina_List *pd_open_pending_list;
71         Ecore_Timer *pd_open_pending_timer;
72         int paused;
73         Eina_List *pd_list;
74         int secured;
75         int pending_timer_freezed;
76 } s_info  = {
77         .item_list = NULL,
78         .update = NULL,
79         .pending_list = NULL,
80         .pending_timer = NULL,
81         .pd_open_pending_list = NULL,
82         .pd_open_pending_timer = NULL,
83         .paused = 0,
84         .pd_list = NULL,
85         .secured = 0,
86         .pending_timer_freezed = 0,
87 };
88
89 static Eina_Bool updator_cb(void *data);
90
91 static void pending_timer_freeze(void)
92 {
93         DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
94         if (s_info.pending_timer && !s_info.pending_timer_freezed) {
95                 DbgPrint("Freeze the pending timer\n");
96                 ecore_timer_freeze(s_info.pending_timer);
97         }
98
99         s_info.pending_timer_freezed++;
100 }
101
102 static void pending_timer_thaw(void)
103 {
104         DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
105         if (!s_info.pending_timer_freezed) {
106                 return;
107         }
108
109         s_info.pending_timer_freezed--;
110         if (s_info.pending_timer && !s_info.pending_timer_freezed) {
111                 DbgPrint("Thaw the pending timer\n");
112                 ecore_timer_thaw(s_info.pending_timer);
113         }
114 }
115
116 /*
117  * -1 : PD is opened, but not mine
118  *  0 : PD is not opened
119  *  1 : my PD is opened
120  */
121 static inline int pd_is_opened(const char *pkgname)
122 {
123         int i;
124         Eina_List *l;
125         char *tmp;
126
127         i = 0;
128         EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
129                 if (pkgname && !strcmp(pkgname, tmp)) {
130                         return 1;
131                 }
132
133                 i++;
134         }
135
136         return i > 0 ? -1 : 0;
137 }
138
139 static Eina_Bool pd_open_pended_cmd_consumer_cb(void *data)
140 {
141         struct item *item;
142
143         item = eina_list_nth(s_info.pd_open_pending_list, 0);
144         if (!item) {
145                 goto cleanout;
146         }
147
148         if (s_info.update) {
149                 return ECORE_CALLBACK_RENEW;
150         }
151
152         s_info.pd_open_pending_list = eina_list_remove(s_info.pd_open_pending_list, item);
153         /*!
154          * \note
155          * To prevent from checking the is_updated function
156          */
157         if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
158                 /* Item is destroyed */
159         }
160
161         if (s_info.pd_open_pending_list) {
162                 return ECORE_CALLBACK_RENEW;
163         }
164
165 cleanout:
166         s_info.pd_open_pending_timer = NULL;
167         return ECORE_CALLBACK_CANCEL;
168 }
169
170 static Eina_Bool pended_cmd_consumer_cb(void *data)
171 {
172         struct item *item;
173
174         item = eina_list_nth(s_info.pending_list, 0);
175         if (!item) {
176                 goto cleanout;
177         }
178
179         if (s_info.update || pd_is_opened(item->inst->item->pkgname) < 0) {
180                 return ECORE_CALLBACK_RENEW;
181         }
182
183         s_info.pending_list = eina_list_remove(s_info.pending_list, item);
184         /*!
185          * \note
186          * To prevent from checking the is_updated function
187          */
188         if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
189                 /* item is destroyed */
190         }
191
192         if (s_info.pending_list) {
193                 return ECORE_CALLBACK_RENEW;
194         }
195
196 cleanout:
197         s_info.pending_timer = NULL;
198         s_info.pending_timer_freezed = 0;
199         return ECORE_CALLBACK_CANCEL;
200 }
201
202 static inline __attribute__((always_inline)) int activate_pending_consumer(void)
203 {
204         if (s_info.pending_timer) {
205                 return 0;
206         }
207
208         s_info.pending_timer = ecore_timer_add(0.000001f, pended_cmd_consumer_cb, NULL);
209         if (!s_info.pending_timer) {
210                 ErrPrint("Failed to add a new pended command consumer\n");
211                 return LB_STATUS_ERROR_FAULT;
212         }
213
214         /*!
215          * Do not increase the freezed counter.
216          * Just freeze the timer.
217          */
218         if (s_info.pending_timer_freezed) {
219                 ecore_timer_freeze(s_info.pending_timer);
220         }
221
222         return 0;
223 }
224
225 static inline void deactivate_pending_consumer(void)
226 {
227         if (!s_info.pending_timer) {
228                 return;
229         }
230
231         ecore_timer_del(s_info.pending_timer);
232         s_info.pending_timer = NULL;
233         s_info.pending_timer_freezed = 0;
234 }
235
236 static inline void deactivate_pd_open_pending_consumer(void)
237 {
238         if (!s_info.pd_open_pending_timer) {
239                 return;
240         }
241
242         ecore_timer_del(s_info.pd_open_pending_timer);
243         s_info.pd_open_pending_timer = NULL;
244 }
245
246 static inline int __attribute__((always_inline)) activate_pd_open_pending_consumer(void)
247 {
248         if (s_info.pd_open_pending_timer) {
249                 return 0;
250         }
251
252         s_info.pd_open_pending_timer = ecore_timer_add(0.000001f, pd_open_pended_cmd_consumer_cb, NULL);
253         if (!s_info.pd_open_pending_timer) {
254                 ErrPrint("Failed to add a new pended command consumer\n");
255                 return LB_STATUS_ERROR_FAULT;
256         }
257
258         return 0;
259 }
260
261 static inline void migrate_to_pd_open_pending_list(const char *pkgname)
262 {
263         Eina_List *l;
264         Eina_List *n;
265         struct item *item;
266         int cnt = 0;
267
268         EINA_LIST_FOREACH_SAFE(s_info.pending_list, l, n, item) {
269                 if (strcmp(pkgname, item->inst->item->pkgname)) {
270                         continue;
271                 }
272
273                 s_info.pending_list = eina_list_remove(s_info.pending_list, item);
274                 s_info.pd_open_pending_list = eina_list_append(s_info.pd_open_pending_list, item);
275                 cnt++;
276         }
277
278         if (s_info.pd_open_pending_list) {
279                 activate_pd_open_pending_consumer();
280         }
281
282         if (!s_info.pending_list) {
283                 deactivate_pending_consumer();
284         }
285 }
286
287 static inline void migrate_to_pending_list(const char *pkgname)
288 {
289         Eina_List *l;
290         Eina_List *n;
291         struct item *item;
292         int cnt = 0;
293
294         EINA_LIST_FOREACH_SAFE(s_info.pd_open_pending_list, l, n, item) {
295                 if (strcmp(pkgname, item->inst->item->pkgname)) {
296                         continue;
297                 }
298
299                 s_info.pd_open_pending_list = eina_list_remove(s_info.pd_open_pending_list, item);
300                 s_info.pending_list = eina_list_append(s_info.pending_list, item);
301                 cnt++;
302         }
303
304         if (s_info.pending_list) {
305                 activate_pending_consumer();
306         }
307
308         if (!s_info.pd_open_pending_list) {
309                 deactivate_pd_open_pending_consumer();
310         }
311 }
312
313 static inline int is_pended_item(struct item *item)
314 {
315         struct item *in_item;
316         if (pd_is_opened(item->inst->item->pkgname) == 1) {
317                 in_item = eina_list_data_find(s_info.pd_open_pending_list, item);
318         } else {
319                 in_item = eina_list_data_find(s_info.pending_list, item);
320         }
321
322         return (in_item == item);
323 }
324
325 static int append_pending_list(struct item *item)
326 {
327         if (pd_is_opened(item->inst->item->pkgname) == 1) {
328                 if (eina_list_data_find(s_info.pd_open_pending_list, item) == item) {
329                         DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
330                         return LB_STATUS_ERROR_EXIST;
331                 }
332
333                 if (activate_pd_open_pending_consumer() < 0) {
334                         ErrPrint("Failed to activate PD open pending consumer\n");
335                         return LB_STATUS_ERROR_FAULT;
336                 }
337
338                 s_info.pd_open_pending_list = eina_list_append(s_info.pd_open_pending_list, item);
339         } else {
340                 if (eina_list_data_find(s_info.pending_list, item) == item) {
341                         DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
342                         return LB_STATUS_ERROR_EXIST;
343                 }
344
345                 if (activate_pending_consumer() < 0) {
346                         return LB_STATUS_ERROR_FAULT;
347                 }
348
349                 s_info.pending_list = eina_list_append(s_info.pending_list, item);
350         }
351         return 0;
352 }
353
354 /*!
355  * \brief
356  *   This function can call the update callback
357  * return 0 if there is no changes
358  * return -1 the item is deleted
359  */
360 static inline int timer_thaw(struct item *item)
361 {
362         double pending;
363         double period;
364         double delay;
365         double sleep_time;
366
367         if (!item->timer) {
368                 return 0;
369         }
370
371         ecore_timer_thaw(item->timer);
372         period = ecore_timer_interval_get(item->timer);
373         pending = ecore_timer_pending_get(item->timer);
374         delay = util_time_delay_for_compensation(period) - pending;
375         ecore_timer_delay(item->timer, delay);
376
377         if (item->sleep_at == 0.0f) {
378                 return 0;
379         }
380
381         sleep_time = util_timestamp() - item->sleep_at;
382         item->sleep_at = 0.0f;
383
384         if (sleep_time > pending) {
385                 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
386                         /* item is destroyed */
387                         return UPDATE_ITEM_DELETED;
388                 } else {
389                         return UPDATE_INVOKED;
390                 }
391         }
392
393         return UPDATE_NOT_INVOKED;
394 }
395
396 static void timer_freeze(struct item *item)
397 {
398         struct timeval tv;
399
400         if (!item->timer) {
401                 return;
402         }
403
404         ecore_timer_freeze(item->timer);
405
406         if (ecore_timer_interval_get(item->timer) <= 1.0f) {
407                 return;
408         }
409
410         if (gettimeofday(&tv, NULL) < 0) {
411                 ErrPrint("gettimeofday: %s\n", strerror(errno));
412                 tv.tv_sec = 0;
413                 tv.tv_usec = 0;
414         }
415
416         item->sleep_at = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
417 }
418
419 static inline void update_monitor_cnt(struct item *item)
420 {
421         double now;
422         double interval;
423
424         now = util_timestamp();
425         interval = now - item->update_interval;
426
427         /*!
428          * \note
429          * If the content update is processed in too short time,
430          * don't increase the monitor counter, instead of it
431          * set the heavy updating flag.
432          * And handling this heavy updating from the
433          * file update callback.
434          */
435         if (interval >= MINIMUM_UPDATE_INTERVAL) {
436                 if (s_info.update == item) {
437                         /*!
438                          * \note
439                          * If already in updating mode,
440                          * reset the monitor_cnt to 1,
441                          * all updated event will be merged into A inotify event
442                          */
443                         DbgPrint("While waiting updated event, content is updated [%s]\n", item->inst->id);
444                         item->monitor_cnt = 1;
445                 } else {
446                         item->monitor_cnt++;
447                 }
448         } else {
449                 item->heavy_updating = 1;
450         }
451
452         item->update_interval = now;
453 }
454
455 static inline Eina_List *find_item(struct instance *inst)
456 {
457         Eina_List *l;
458         struct item *item;
459         
460         EINA_LIST_FOREACH(s_info.item_list, l, item) {
461                 if (item->inst == inst) {
462                         return l;
463                 }
464         }
465
466         return NULL;
467 }
468
469 static inline int output_handler(struct item *item)
470 {
471         int invalid = 0;
472
473         item->monitor_cnt--;
474         if (item->monitor_cnt < 0 || item->heavy_updating) {
475                 if (!item->heavy_updating) {
476                         WarnPrint("%s has invalid monitor_cnt\n", item->inst->id);
477                         invalid = 1;
478                 } else {
479                         item->heavy_updating = 0;       /* Reset flag */
480                 }
481
482                 item->monitor_cnt = 0;
483         }
484
485         if (item->monitor_cnt == 0) {
486                 if (!invalid) {
487                         fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
488                 }
489
490                 if (item->monitor) {
491                         ecore_timer_del(item->monitor);
492                         item->monitor = NULL;
493                 }
494
495                 if (s_info.update == item) {
496                         s_info.update = NULL;
497                 }
498
499                 if (item->deleteme) {
500                         provider_send_deleted(item->inst->item->pkgname, item->inst->id);
501                         (void)so_destroy(item->inst);
502                         free(item);
503                         return EXIT_FAILURE;
504                 }
505         }
506
507         return EXIT_SUCCESS;
508 }
509
510 static int desc_updated_cb(const char *filename, void *data, int over)
511 {
512         struct item *item;
513
514         if (over) {
515                 WarnPrint("Event Q overflow\n");
516         }
517
518         item = data;
519
520         DbgPrint("DESC %s is updated\n", filename);
521         if (item->is_pd_show) {
522                 provider_send_desc_updated(item->inst->item->pkgname, item->inst->id, filename);
523         } else {
524                 ErrPrint("But PD is not opened, Ignore this update (%s)\n", item->inst->id);
525         }
526         return EXIT_SUCCESS;
527 }
528
529 static int file_updated_cb(const char *filename, void *data, int over)
530 {
531         struct item *item;
532         int w;
533         int h;
534         double priority;
535         char *content = NULL;
536         char *title = NULL;
537         int ret;
538
539         if (over) {
540                 WarnPrint("Event Q overflow\n");
541         }
542
543         item = data;
544
545         ret = util_get_filesize(filename);
546         if (ret <= 0) {
547                 ErrPrint("Content is updated. but invalid. ret = %d (Update is ignored)\n", ret);
548                 return EXIT_SUCCESS; /*!< To keep the callback */
549         }
550
551         ret = so_get_output_info(item->inst, &w, &h, &priority, &content, &title);
552         if (ret < 0) {
553                 ErrPrint("livebox_get_info returns %d\n", ret);
554                 return EXIT_SUCCESS; /*!< To keep the callback */
555         }
556
557         if (IS_LB_SHOWN(item)) {
558                 provider_send_updated(item->inst->item->pkgname, item->inst->id,
559                                         item->inst->w, item->inst->h, item->inst->priority,
560                                         content, title);
561         } else {
562                 item->is_lb_updated++;
563         }
564
565         return output_handler(item);
566 }
567
568 static void reset_lb_updated_flag(struct item *item)
569 {
570         if (!item->is_lb_updated) {
571                 return;
572         }
573
574         DbgPrint("[%s] Updated %d times, (content: %s), (title: %s)\n",
575                         item->inst->id, item->is_lb_updated,
576                         item->inst->content, item->inst->title);
577
578         provider_send_updated(item->inst->item->pkgname, item->inst->id,
579                         item->inst->w, item->inst->h, item->inst->priority,
580                         item->inst->content, item->inst->title);
581
582         item->is_lb_updated = 0;
583 }
584
585 static inline int clear_from_pd_open_pending_list(struct item *item)
586 {
587         Eina_List *l;
588         struct item *tmp;
589
590         EINA_LIST_FOREACH(s_info.pd_open_pending_list, l, tmp) {
591                 if (tmp != item) {
592                         continue;
593                 }
594
595                 s_info.pd_open_pending_list = eina_list_remove_list(s_info.pd_open_pending_list, l);
596                 if (!s_info.pd_open_pending_list) {
597                         deactivate_pd_open_pending_consumer();
598                 }
599                 return LB_STATUS_SUCCESS;
600         }
601
602         return LB_STATUS_ERROR_NOT_EXIST;
603 }
604
605 static inline int clear_from_pending_list(struct item *item)
606 {
607         Eina_List *l;
608         struct item *tmp;
609
610         EINA_LIST_FOREACH(s_info.pending_list, l, tmp) {
611                 if (tmp != item) {
612                         continue;
613                 }
614
615                 s_info.pending_list = eina_list_remove_list(s_info.pending_list, l);
616                 if (!s_info.pending_list) {
617                         deactivate_pending_consumer();
618                 }
619                 return LB_STATUS_SUCCESS;
620         }
621
622         return LB_STATUS_ERROR_NOT_EXIST;
623 }
624
625 static Eina_Bool update_timeout_cb(void *data)
626 {
627         struct item *item;
628
629         item = data;
630
631         ErrPrint("UPDATE TIMEOUT ========> %s - %s\n", item->inst->item->pkgname, item->inst->id);
632
633         if (s_info.update != item) {
634                 ErrPrint("Updating item is not matched\n");
635         }
636
637         fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
638         fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,timeout", NO_ALARM, DEFAULT_LIFE_TIMER);
639         s_info.update = NULL;
640
641         exit(ETIME);
642         return ECORE_CALLBACK_CANCEL;
643 }
644
645 /*!
646  * \note
647  * This must has to return ECORE_CALLBACK_CANCEL, only if the item is deleted.
648  * So every caller, should manage the deleted item correctly.
649  */
650 static Eina_Bool updator_cb(void *data)
651 {
652         struct item *item;
653         int ret;
654
655         item = data;
656
657         if (item->monitor) { /*!< If this item is already in update process */
658                 return ECORE_CALLBACK_RENEW;
659         }
660
661         if (!IS_LB_SHOWN(item)) {
662                 DbgPrint("%s is not shown yet. make delay for updates\n", item->inst->item->pkgname);
663                 (void)append_pending_list(item);
664                 return ECORE_CALLBACK_RENEW;
665         }
666
667         if (item->is_paused) {
668                 item->updated_in_pause++;
669                 DbgPrint("%s is paused[%d]. make delay for updating\n", item->inst->item->pkgname, item->updated_in_pause);
670                 return ECORE_CALLBACK_RENEW;
671         }
672
673         item->updated_in_pause = 0;
674
675         ret = so_is_updated(item->inst);
676         if (ret <= 0) {
677                 if (so_need_to_destroy(item->inst) == NEED_TO_DESTROY) {
678                         provider_send_deleted(item->inst->item->pkgname, item->inst->id);
679                         lb_destroy(item->inst->item->pkgname, item->inst->id);
680                         /*!
681                          * \CRITICAL
682                          * Every caller of this, must not access the item from now.
683                          */
684                         return ECORE_CALLBACK_CANCEL;
685                 }
686
687                 reset_lb_updated_flag(item);
688                 return ECORE_CALLBACK_RENEW;
689         }
690
691         if (s_info.update || pd_is_opened(item->inst->item->pkgname) < 0) {
692                 DbgPrint("%s is busy\n", s_info.update ? s_info.update->inst->id : item->inst->id);
693                 (void)append_pending_list(item);
694                 return ECORE_CALLBACK_RENEW;
695         }
696
697         item->monitor = ecore_timer_add(item->inst->item->timeout, update_timeout_cb, item);
698         if (!item->monitor) {
699                 ErrPrint("Failed to add update monitor %s(%s):%d\n",
700                                         item->inst->item->pkgname, item->inst->id, item->inst->item->timeout);
701                 return ECORE_CALLBACK_RENEW;
702         }
703
704         ret = so_update(item->inst);
705         if (ret < 0) {
706                 ecore_timer_del(item->monitor);
707                 item->monitor = NULL;
708                 reset_lb_updated_flag(item);
709                 return ECORE_CALLBACK_RENEW;
710         }
711
712         /*!
713          * \note
714          * Counter of the event monitor is only used for asynchronous content updating,
715          * So reset it to 1 from here because the async updating is started now,
716          * even if it is accumulated by other event function before this.
717          */
718         item->monitor_cnt = 1;
719
720         /*!
721          * \note
722          * While waiting the Callback function call,
723          * Add this for finding the crash
724          */
725         fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM, DEFAULT_LIFE_TIMER);
726
727         if (ret & NEED_TO_SCHEDULE) {
728                 (void)append_pending_list(item);
729         }
730
731         if (ret & OUTPUT_UPDATED) {
732                 /*!
733                  * \NOTE 
734                  * In this case, there is potential issue
735                  * 1. User added update CALLBACK -> Inotify event (Only once)
736                  *    > We have to detect this case. Is it possible to be a user callback called faster than inotify event handler?
737                  * 2. Inotify event -> User added update CALLBACK -> Inotify event
738                  *    > Okay. What we want is this.
739                  */
740                 update_monitor_cnt(item);
741         }
742
743         /*
744          * \NOTE
745          * This should be updated after "update_monitor_cnt" function call,
746          * because the update_monitor_cnt function will see the s_info.update variable,
747          */
748         s_info.update = item;
749
750         return ECORE_CALLBACK_RENEW;
751 }
752
753 static inline void update_monitor_del(const char *id, struct item *item)
754 {
755         char *tmp;
756         int len;
757
758         update_monitor_del_update_cb(util_uri_to_path(id), file_updated_cb);
759
760         len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
761         tmp = malloc(len);
762         if (!tmp) {
763                 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
764                 return;
765         }
766
767         snprintf(tmp, len, "%s.desc", util_uri_to_path(id));
768         update_monitor_del_update_cb(tmp, desc_updated_cb);
769         free(tmp);
770 }
771
772 static inline int add_desc_update_monitor(const char *id, struct item *item)
773 {
774         char *filename;
775         int len;
776         int ret;
777
778         len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
779         filename = malloc(len);
780         if (!filename) {
781                 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
782                 return LB_STATUS_ERROR_MEMORY;
783         }
784
785         snprintf(filename, len, "%s.desc", util_uri_to_path(id));
786         ret = update_monitor_add_update_cb(filename, desc_updated_cb, item);
787         free(filename);
788         return ret;
789 }
790
791 static inline int add_file_update_monitor(const char *id, struct item *item)
792 {
793         return update_monitor_add_update_cb(util_uri_to_path(id), file_updated_cb, item);
794 }
795
796 static inline int update_monitor_add(const char *id, struct item *item)
797 {
798         /*!
799          * \NOTE
800          * item->inst is not available yet.
801          */
802         add_file_update_monitor(id, item);
803         add_desc_update_monitor(id, item);
804         return LB_STATUS_SUCCESS;
805 }
806
807 HAPI int lb_init(void)
808 {
809         return LB_STATUS_SUCCESS;
810 }
811
812 HAPI int lb_fini(void)
813 {
814         Eina_List *l;
815         Eina_List *n;
816         struct item *item;
817
818         deactivate_pending_consumer();
819         deactivate_pd_open_pending_consumer();
820
821         EINA_LIST_FREE(s_info.pd_open_pending_list, item);
822         EINA_LIST_FREE(s_info.pending_list, item);
823
824         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
825                 provider_send_deleted(item->inst->item->pkgname, item->inst->id);
826                 lb_destroy(item->inst->item->pkgname, item->inst->id);
827         }
828
829         return LB_STATUS_SUCCESS;
830 }
831
832 /*!
833  * \note
834  * Exported API for each liveboxes.
835  */
836 const char *livebox_find_pkgname(const char *filename)
837 {
838         Eina_List *l;
839         struct item *item;
840
841         EINA_LIST_FOREACH(s_info.item_list, l, item) {
842                 if (!strcmp(item->inst->id, filename)) {
843                         return item->inst->item->pkgname;
844                 }
845         }
846
847         return NULL;
848 }
849
850 int livebox_request_update_by_id(const char *filename)
851 {
852         Eina_List *l;
853         struct item *item;
854
855         if (so_current_op() != LIVEBOX_OP_UNKNOWN) {
856                 ErrPrint("Current operation: %d\n", so_current_op());
857                 return LB_STATUS_ERROR_INVALID;
858         }
859
860         EINA_LIST_FOREACH(s_info.item_list, l, item) {
861                 if (!strcmp(item->inst->id, filename)) {
862                         return append_pending_list(item);
863                 }
864         }
865
866         return LB_STATUS_ERROR_NOT_EXIST;
867 }
868
869 int livebox_trigger_update_monitor(const char *filename, int is_pd)
870 {
871         char *fname;
872         int ret;
873
874         if (so_current_op() != LIVEBOX_OP_UNKNOWN) {
875                 ErrPrint("Current operation: %d\n", so_current_op());
876                 return LB_STATUS_ERROR_INVALID;
877         }
878
879         if (is_pd) {
880                 int len;
881                 len = strlen(filename) + strlen(".desc");
882
883                 fname = malloc(len + 1);
884                 if (!fname) {
885                         ErrPrint("Heap: %s\n", strerror(errno));
886                         return LB_STATUS_ERROR_MEMORY;
887                 }
888
889                 snprintf(fname, len, "%s.desc", filename);
890         } else {
891                 fname = strdup(filename);
892                 if (!fname) {
893                         ErrPrint("Heap: %s\n", strerror(errno));
894                         return LB_STATUS_ERROR_MEMORY;
895                 }
896         }
897
898         if (access(fname, R_OK | W_OK) != 0) {
899                 ErrPrint("access: %s (%s)\n", fname, strerror(errno));
900                 ret = LB_STATUS_ERROR_IO;
901         } else {
902                 ret = update_monitor_trigger_update_cb(fname, 0);
903         }
904
905         free(fname);
906         return ret;
907 }
908
909 HAPI int lb_open_pd(const char *pkgname)
910 {
911         Eina_List *l;
912         char *tmp;
913
914         EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
915                 if (!strcmp(pkgname, tmp)) {
916                         return 0;
917                 }
918         }
919
920         tmp = strdup(pkgname);
921         if (!tmp) {
922                 ErrPrint("Heap: %s\n", strerror(errno));
923                 return LB_STATUS_ERROR_MEMORY;
924         }
925
926         if (!s_info.pd_list) {
927                 pending_timer_freeze();
928         }
929
930         s_info.pd_list = eina_list_append(s_info.pd_list, tmp);
931
932         /*!
933          * Find all instances from the pending list.
934          * Move them to pd_open_pending_timer
935          */
936         migrate_to_pd_open_pending_list(pkgname);
937         return LB_STATUS_SUCCESS;
938 }
939
940 HAPI int lb_close_pd(const char *pkgname)
941 {
942         Eina_List *l;
943         Eina_List *n;
944         char *tmp;
945
946         EINA_LIST_FOREACH_SAFE(s_info.pd_list, l, n, tmp) {
947                 if (strcmp(tmp, pkgname)) {
948                         continue;
949                 }
950
951                 s_info.pd_list = eina_list_remove(s_info.pd_list, tmp);
952                 free(tmp);
953
954                 if (!s_info.pd_list) {
955                         pending_timer_thaw();
956                 }
957
958                 /*!
959                  * Move all items in pd_open_pending_list
960                  * to pending_list.
961                  */
962                 migrate_to_pending_list(pkgname);
963                 return LB_STATUS_SUCCESS;
964         }
965
966         return LB_STATUS_ERROR_NOT_EXIST;
967 }
968
969 HAPI int lb_create(const char *pkgname, const char *id, const char *content_info, int timeout, int has_livebox_script, double period, const char *cluster, const char *category, int *w, int *h, double *priority, int skip_need_to_create, const char *abi, char **out_content, char **out_title)
970 {
971         struct instance *inst;
972         struct item *item;
973         int ret;
974         int create_ret;
975         int need_to_create;
976
977         need_to_create = 0;
978         *out_content = NULL;
979         *out_title = NULL;
980
981         inst = so_find_instance(pkgname, id);
982         if (inst) {
983                 DbgPrint("Instance is already exists [%s - %s] content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
984                 return LB_STATUS_SUCCESS;
985         }
986
987         if (!skip_need_to_create) {
988                 ret = so_create_needed(pkgname, cluster, category, abi);
989                 if (ret != NEED_TO_CREATE) {
990                         return LB_STATUS_ERROR_PERMISSION;
991                 }
992
993                 need_to_create = 1;
994         }
995
996         item = calloc(1, sizeof(*item));
997         if (!item) {
998                 ErrPrint("Heap: %s (%s - %s, content[%s], cluster[%s], category[%s], abi[%s])\n", strerror(errno), pkgname, id, content_info, cluster, category, abi);
999                 return LB_STATUS_ERROR_MEMORY;
1000         }
1001
1002         ret = update_monitor_add(id, item);
1003         if (ret < 0) {
1004                 free(item);
1005                 return ret;
1006         }
1007
1008         create_ret = so_create(pkgname, id, content_info, timeout, has_livebox_script, cluster, category, abi, &inst);
1009         if (create_ret < 0) {
1010                 update_monitor_del(id,  item);
1011                 free(item);
1012
1013                 *w = 0;
1014                 *h = 0;
1015                 *priority = 0.0f;
1016                 return create_ret;
1017         }
1018
1019         item->inst = inst;
1020
1021         if (period > 0.0f && !s_info.secured) {
1022                 item->timer = util_timer_add(period, updator_cb, item);
1023                 if (!item->timer) {
1024                         ErrPrint("Failed to add timer (%s - %s, content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
1025                         update_monitor_del(id, item);
1026                         (void)so_destroy(inst);
1027                         free(item);
1028                         return LB_STATUS_ERROR_FAULT;
1029                 }
1030
1031                 if (s_info.paused) {
1032                         timer_freeze(item);
1033                 }
1034         } else {
1035                 DbgPrint("Local update timer is disabled: %lf (%d)\n", period, s_info.secured);
1036                 item->timer = NULL;
1037         }
1038
1039         s_info.item_list = eina_list_append(s_info.item_list, item);
1040
1041         if (create_ret & NEED_TO_SCHEDULE) {
1042                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1043                 (void)append_pending_list(item);
1044         }
1045
1046         if (create_ret & OUTPUT_UPDATED) {
1047                 update_monitor_cnt(item);
1048                 /*!
1049                  * \note
1050                  * To send a output info, get the info forcely.
1051                  * but the output file monitor will do this again
1052                  *
1053                  * This function will set the tmp_content and tmp_title
1054                  * even if it has no updates on the content, title,
1055                  * it will set them to NULL.
1056                  */
1057                 if (so_get_output_info(inst, w, h, priority, out_content, out_title) == LB_STATUS_SUCCESS) {
1058                         if (*out_content) {
1059                                 char *tmp;
1060
1061                                 tmp = strdup(*out_content);
1062                                 if (!tmp) {
1063                                         ErrPrint("Memory: %s\n", strerror(errno));
1064                                 }
1065
1066                                 *out_content = tmp;
1067                         }
1068
1069                         if (*out_title) {
1070                                 char *tmp;
1071
1072                                 tmp = strdup(*out_title);
1073                                 if (!tmp) {
1074                                         ErrPrint("Memory: %s\n", strerror(errno));
1075                                 }
1076
1077                                 *out_title = tmp;
1078                         }
1079                 }
1080         }
1081
1082         *w = inst->w;
1083         *h = inst->h;
1084         *priority = inst->priority;
1085         return need_to_create;
1086 }
1087
1088 HAPI int lb_destroy(const char *pkgname, const char *id)
1089 {
1090         Eina_List *l;
1091         struct instance *inst;
1092         struct item *item;
1093
1094         inst = so_find_instance(pkgname, id);
1095         if (!inst) {
1096                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1097                 return LB_STATUS_ERROR_INVALID;
1098         }
1099
1100         l = find_item(inst);
1101         if (!l) {
1102                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1103                 return LB_STATUS_ERROR_NOT_EXIST;
1104         }
1105
1106         item = eina_list_data_get(l);
1107         s_info.item_list = eina_list_remove_list(s_info.item_list, l);
1108
1109         if (s_info.update == item) {
1110                 s_info.update = NULL;
1111         }
1112
1113         if (item->timer) {
1114                 clear_from_pd_open_pending_list(item);
1115                 clear_from_pending_list(item);
1116                 ecore_timer_del(item->timer);
1117                 item->timer = NULL;
1118
1119                 if (item->monitor) {
1120                         item->deleteme = 1;
1121                 } else {
1122                         update_monitor_del(id, item);
1123                 }
1124         }
1125
1126         if (!item->monitor) {
1127                 free(item);
1128                 (void)so_destroy(inst);
1129         }
1130
1131         return LB_STATUS_SUCCESS;
1132 }
1133
1134 HAPI int lb_resize(const char *pkgname, const char *id, int w, int h)
1135 {
1136         Eina_List *l;
1137         struct instance *inst;
1138         struct item *item;
1139         int ret;
1140
1141         inst = so_find_instance(pkgname, id);
1142         if (!inst) {
1143                 ErrPrint("Instance %s - %s is not created (%dx%d)\n", pkgname, id, w, h);
1144                 return LB_STATUS_ERROR_INVALID;
1145         }
1146
1147         l = find_item(inst);
1148         if (!l) {
1149                 ErrPrint("Instance is not found (%s - %s, %dx%d)\n", pkgname, id, w, h);
1150                 return LB_STATUS_ERROR_NOT_EXIST;
1151         }
1152
1153         item = eina_list_data_get(l);
1154
1155         ret = so_resize(inst, w, h);
1156         if (ret < 0) {
1157                 return ret;
1158         }
1159
1160         if (ret & NEED_TO_SCHEDULE) {
1161                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1162                 (void)append_pending_list(item);
1163         }
1164
1165         if (ret & OUTPUT_UPDATED) {
1166                 update_monitor_cnt(item);
1167         }
1168
1169         return LB_STATUS_SUCCESS;
1170 }
1171
1172 HAPI char *lb_pinup(const char *pkgname, const char *id, int pinup)
1173 {
1174         struct instance *inst;
1175         char *ret;
1176
1177         inst = so_find_instance(pkgname, id);
1178         if (!inst) {
1179                 ErrPrint("Instance %s - %s is not found (pinup[%d])\n", pkgname, id, pinup);
1180                 return NULL;
1181         }
1182
1183         ret = so_pinup(inst, pinup);
1184         return ret;
1185 }
1186
1187 HAPI int lb_set_period(const char *pkgname, const char *id, double period)
1188 {
1189         Eina_List *l;
1190         struct instance *inst;
1191         struct item *item;
1192
1193         inst = so_find_instance(pkgname, id);
1194         if (!inst) {
1195                 ErrPrint("Instance %s - %s is not found (period[%lf])\n", pkgname, id, period);
1196                 return LB_STATUS_ERROR_INVALID;
1197         }
1198
1199         l = find_item(inst);
1200         if (!l) {
1201                 ErrPrint("Instance is not found (%s - %s, period[%lf])\n", pkgname, id, period);
1202                 return LB_STATUS_ERROR_NOT_EXIST;
1203         }
1204
1205         item = eina_list_data_get(l);
1206
1207         if (period <= 0.0f) {
1208                 if (item->timer) {
1209                         ecore_timer_del(item->timer);
1210                         item->timer = NULL;
1211                 }
1212         } else {
1213                 if (item->timer) {
1214                         util_timer_interval_set(item->timer, period);
1215                 } else if (!s_info.secured) {
1216                         item->timer = util_timer_add(period, updator_cb, item);
1217                         if (!item->timer) {
1218                                 ErrPrint("Failed to add timer (%s - %s)\n", pkgname, id);
1219                                 return LB_STATUS_ERROR_FAULT;
1220                         }
1221
1222                         if (s_info.paused) {
1223                                 timer_freeze(item);
1224                         }
1225                 }
1226         }
1227
1228         return LB_STATUS_SUCCESS;
1229 }
1230
1231 HAPI int lb_clicked(const char *pkgname, const char *id, const char *event, double timestamp, double x, double y)
1232 {
1233         Eina_List *l;
1234         struct instance *inst;
1235         struct item *item;
1236         int ret;
1237
1238         inst = so_find_instance(pkgname, id);
1239         if (!inst) {
1240                 ErrPrint("Instance %s - %s is not exists (event[%s])\n", pkgname, id, event);
1241                 return LB_STATUS_ERROR_INVALID;
1242         }
1243
1244         l = find_item(inst);
1245         if (!l) {
1246                 ErrPrint("Instance is not found (%s - %s, event[%s])\n", pkgname, id, event);
1247                 return LB_STATUS_ERROR_NOT_EXIST;
1248         }
1249
1250         item = eina_list_data_get(l);
1251
1252         ret = so_clicked(inst, event, timestamp, x, y);
1253         if (ret < 0) {
1254                 return ret;
1255         }
1256
1257         if (ret & NEED_TO_SCHEDULE) {
1258                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1259                 (void)append_pending_list(item);
1260         }
1261
1262         if (ret & OUTPUT_UPDATED) {
1263                 update_monitor_cnt(item);
1264         }
1265
1266         return LB_STATUS_SUCCESS;
1267 }
1268
1269 HAPI int lb_script_event(const char *pkgname, const char *id, const char *emission, const char *source, struct event_info *event_info)
1270 {
1271         Eina_List *l;
1272         struct instance *inst;
1273         struct item *item;
1274         int ret;
1275
1276         inst = so_find_instance(pkgname, id);
1277         if (!inst) {
1278                 ErrPrint("Instance %s - %s is not exists (emission[%s], source[%s])\n", pkgname, id, emission, source);
1279                 return LB_STATUS_ERROR_INVALID;
1280         }
1281
1282         l = find_item(inst);
1283         if (!l) {
1284                 ErrPrint("Instance is not found (%s - %s, emissino[%s], source[%s])\n", pkgname, id, emission, source);
1285                 return LB_STATUS_ERROR_NOT_EXIST;
1286         }
1287
1288         item = eina_list_data_get(l);
1289
1290         if (emission && source && !strcmp(source, id)) {
1291                 if (item->inst->item->has_livebox_script) {
1292                         if (!strcmp(emission, "lb,show")) {
1293                                 item->is_lb_show = 1;
1294
1295                                 if (item->is_lb_updated && !is_pended_item(item)) {
1296                                         reset_lb_updated_flag(item);
1297                                 }
1298
1299                                 source = util_uri_to_path(source);
1300                         } else if (!strcmp(emission, "lb,hide")) {
1301                                 DbgPrint("Livebox(%s) script is hide now\n", id);
1302                                 item->is_lb_show = 0;
1303
1304                                 source = util_uri_to_path(source);
1305                         }
1306                 }
1307
1308                 if (!strcmp(emission, "pd,show")) {
1309                         item->is_pd_show = 1;
1310                         source = util_uri_to_path(source);
1311                 } else if (!strcmp(emission, "pd,hide")) {
1312                         item->is_pd_show = 0;
1313                         source = util_uri_to_path(source);
1314                 }
1315         }
1316
1317         ret = so_script_event(inst, emission, source, event_info);
1318         if (ret < 0) {
1319                 return ret;
1320         }
1321
1322         if (ret & NEED_TO_SCHEDULE) {
1323                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1324                 (void)append_pending_list(item);
1325         }
1326
1327         if (ret & OUTPUT_UPDATED) {
1328                 update_monitor_cnt(item);
1329         }
1330
1331         return LB_STATUS_SUCCESS;
1332 }
1333
1334 HAPI int lb_is_pinned_up(const char *pkgname, const char *id)
1335 {
1336         Eina_List *l;
1337         struct instance *inst;
1338         struct item *item;
1339
1340         inst = so_find_instance(pkgname, id);
1341         if (!inst) {
1342                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1343                 return LB_STATUS_ERROR_INVALID;
1344         }
1345
1346         l = find_item(inst);
1347         if (!l) {
1348                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1349                 return LB_STATUS_ERROR_NOT_EXIST;
1350         }
1351
1352         item = eina_list_data_get(l);
1353         if (!item) {
1354                 ErrPrint("Invalid item(%s - %s)\n", pkgname, id);
1355                 return LB_STATUS_ERROR_FAULT;
1356         }
1357         /*!
1358          * NOTE:
1359          * item is not used.
1360          * Maybe this is not neccessary for this operation
1361          */
1362         return so_is_pinned_up(inst);
1363 }
1364
1365 HAPI int lb_change_group(const char *pkgname, const char *id, const char *cluster, const char *category)
1366 {
1367         Eina_List *l;
1368         struct instance *inst;
1369         struct item *item;
1370         int ret;
1371
1372         inst = so_find_instance(pkgname, id);
1373         if (!inst) {
1374                 ErrPrint("Instance %s - %s is not created (cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1375                 return LB_STATUS_ERROR_INVALID;
1376         }
1377
1378         l = find_item(inst);
1379         if (!l) {
1380                 ErrPrint("Instance is not found(%s - %s, cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1381                 return LB_STATUS_ERROR_NOT_EXIST;
1382         }
1383
1384         item = eina_list_data_get(l);
1385
1386         ret = so_change_group(inst, cluster, category);
1387         if (ret < 0) {
1388                 return ret;
1389         }
1390
1391         if (ret & NEED_TO_SCHEDULE) {
1392                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1393                 (void)append_pending_list(item);
1394         }
1395
1396         if (ret & OUTPUT_UPDATED) {
1397                 update_monitor_cnt(item);
1398         }
1399
1400         return LB_STATUS_SUCCESS;
1401 }
1402
1403 static int lb_sys_event(struct instance *inst, struct item *item, int event)
1404 {
1405         int ret;
1406
1407         ret = so_sys_event(inst, event);
1408         if (ret < 0) {
1409                 return ret;
1410         }
1411
1412         if (ret & NEED_TO_SCHEDULE) {
1413                 (void)append_pending_list(item);
1414         }
1415
1416         if (ret & OUTPUT_UPDATED) {
1417                 update_monitor_cnt(item);
1418         }
1419
1420         return LB_STATUS_SUCCESS;
1421 }
1422
1423 HAPI int lb_system_event(const char *pkgname, const char *id, int event)
1424 {
1425         Eina_List *l;
1426         struct instance *inst;
1427         struct item *item;
1428
1429         inst = so_find_instance(pkgname, id);
1430         if (!inst) {
1431                 ErrPrint("instance %s - %s is not created\n");
1432                 return LB_STATUS_ERROR_INVALID;
1433         }
1434
1435         l = find_item(inst);
1436         if (!l) {
1437                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1438                 return LB_STATUS_ERROR_NOT_EXIST;
1439         }
1440
1441         item = eina_list_data_get(l);
1442         return lb_sys_event(inst, item, event);
1443 }
1444
1445 HAPI int lb_update(const char *pkgname, const char *id)
1446 {
1447         Eina_List *l;
1448         struct instance *inst;
1449         struct item *item;
1450
1451         inst = so_find_instance(pkgname, id);
1452         if (!inst) {
1453                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1454                 return LB_STATUS_ERROR_INVALID;
1455         }
1456
1457         l = find_item(inst);
1458         if (!l) {
1459                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1460                 return LB_STATUS_ERROR_NOT_EXIST;
1461         }
1462
1463         item = eina_list_data_get(l);
1464         (void)append_pending_list(item);
1465         return LB_STATUS_SUCCESS;
1466 }
1467
1468 HAPI int lb_update_all(const char *pkgname, const char *cluster, const char *category)
1469 {
1470         Eina_List *l;
1471         Eina_List *n;
1472         struct item *item;
1473
1474         DbgPrint("Update content for %s\n", pkgname ? pkgname : "(all)");
1475         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1476                 if (item->deleteme) {
1477                         continue;
1478                 }
1479
1480                 if (cluster && strcasecmp(item->inst->cluster, cluster)) {
1481                         continue;
1482                 }
1483
1484                 if (category && strcasecmp(item->inst->category, category)) {
1485                         continue;
1486                 }
1487
1488                 if (pkgname && strlen(pkgname)) {
1489                         if (!strcmp(item->inst->item->pkgname, pkgname)) {
1490                                 (void)append_pending_list(item);
1491                         }
1492                 } else {
1493                         (void)append_pending_list(item);
1494                 }
1495         }
1496
1497         return LB_STATUS_SUCCESS;
1498 }
1499
1500 HAPI int lb_delete_all_deleteme(void)
1501 {
1502         Eina_List *l;
1503         Eina_List *n;
1504         struct item *item;
1505         int cnt = 0;
1506
1507         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1508                 if (!item->deleteme) {
1509                         continue;
1510                 }
1511
1512                 update_monitor_del(item->inst->id, item);
1513                 (void)so_destroy(item->inst);
1514                 free(item);
1515                 cnt++;
1516         }
1517
1518         DbgPrint("Delete all deleteme: %d\n", cnt);
1519         return LB_STATUS_SUCCESS;
1520 }
1521
1522 HAPI int lb_system_event_all(int event)
1523 {
1524         Eina_List *l;
1525         Eina_List *n;
1526         struct item *item;
1527
1528         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1529                 if (item->deleteme) {
1530                         continue;
1531                 }
1532
1533                 DbgPrint("System event for %s (%d)\n", item->inst->id, event);
1534                 lb_sys_event(item->inst, item, event);
1535         }
1536
1537         return LB_STATUS_SUCCESS;
1538 }
1539
1540 HAPI void lb_pause_all(void)
1541 {
1542         Eina_List *l;
1543         struct item *item;
1544
1545         s_info.paused = 1;
1546
1547         pending_timer_freeze();
1548
1549         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1550                 if (item->deleteme) {
1551                         DbgPrint("Instance %s skip timer pause (deleteme)\n", item->inst->item->pkgname);
1552                         continue;
1553                 }
1554
1555                 if (item->is_paused) {
1556                         continue;
1557                 }
1558
1559                 timer_freeze(item);
1560
1561                 lb_sys_event(item->inst, item, LB_SYS_EVENT_PAUSED);
1562         }
1563 }
1564
1565 HAPI void lb_resume_all(void)
1566 {
1567         Eina_List *l;
1568         Eina_List *n;
1569         struct item *item;
1570
1571         s_info.paused = 0;
1572
1573         pending_timer_thaw();
1574
1575         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1576                 if (item->deleteme) {
1577                         DbgPrint("Instance %s skip timer resume (deleteme)\n", item->inst->item->pkgname);
1578                         continue;
1579                 }
1580
1581                 if (item->is_paused) {
1582                         continue;
1583                 }
1584
1585                 lb_sys_event(item->inst, item, LB_SYS_EVENT_RESUMED);
1586
1587                 if (item->updated_in_pause) {
1588                         (void)append_pending_list(item);
1589                         item->updated_in_pause = 0;
1590                 }
1591
1592                 /*!
1593                  * \note
1594                  * After send the resume callback, call this function.
1595                  * Because the timer_thaw can call the update function.
1596                  * Before resumed event is notified to the livebox,
1597                  * Do not call update function
1598                  */
1599                 if (timer_thaw(item) == UPDATE_ITEM_DELETED) {
1600                         /* item is deleted */
1601                 }
1602         }
1603 }
1604
1605 HAPI int lb_pause(const char *pkgname, const char *id)
1606 {
1607         struct instance *inst;
1608         Eina_List *l;
1609         struct item *item;
1610
1611         inst = so_find_instance(pkgname, id);
1612         if (!inst) {
1613                 return LB_STATUS_ERROR_INVALID;
1614         }
1615
1616         l = find_item(inst);
1617         if (!l) {
1618                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1619                 return LB_STATUS_ERROR_NOT_EXIST;
1620         }
1621
1622         item = eina_list_data_get(l);
1623         if (!item) {
1624                 return LB_STATUS_ERROR_FAULT;
1625         }
1626
1627         if (item->deleteme) {
1628                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1629                 return LB_STATUS_ERROR_BUSY;
1630         }
1631
1632         item->is_paused = 1;
1633
1634         if (s_info.paused) {
1635                 return LB_STATUS_SUCCESS;
1636         }
1637
1638         timer_freeze(item);
1639
1640         lb_sys_event(inst, item, LB_SYS_EVENT_PAUSED);
1641
1642         return LB_STATUS_SUCCESS;
1643 }
1644
1645 HAPI int lb_resume(const char *pkgname, const char *id)
1646 {
1647         struct instance *inst;
1648         Eina_List *l;
1649         struct item *item;
1650         int ret;
1651
1652         inst = so_find_instance(pkgname, id);
1653         if (!inst) {
1654                 return LB_STATUS_ERROR_INVALID;
1655         }
1656
1657         l = find_item(inst);
1658         if (!l) {
1659                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1660                 return LB_STATUS_ERROR_NOT_EXIST;
1661         }
1662
1663         item = eina_list_data_get(l);
1664         if (!item) {
1665                 return LB_STATUS_ERROR_FAULT;
1666         }
1667
1668         if (item->deleteme) {
1669                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1670                 return LB_STATUS_ERROR_BUSY;
1671         }
1672
1673         item->is_paused = 0;
1674
1675         if (s_info.paused) {
1676                 return LB_STATUS_SUCCESS;
1677         }
1678
1679         lb_sys_event(inst, item, LB_SYS_EVENT_RESUMED);
1680
1681         ret = timer_thaw(item);
1682         if (ret == UPDATE_ITEM_DELETED) {
1683                 /*!
1684                  * \note
1685                  * ITEM is deleted
1686                  */
1687                 return LB_STATUS_SUCCESS;
1688         } else if (ret == UPDATE_INVOKED) {
1689                 /*!
1690                  * \note
1691                  * if the update is successfully done, the updated_in_pause will be reset'd.
1692                  * or append it to the pending list
1693                  */
1694         }
1695
1696         if (item->updated_in_pause) {
1697                 (void)append_pending_list(item);
1698                 item->updated_in_pause = 0;
1699         }
1700
1701         return LB_STATUS_SUCCESS;
1702 }
1703
1704 HAPI void lb_turn_secured_on(void)
1705 {
1706         s_info.secured = 1;
1707 }
1708
1709 HAPI int lb_is_all_paused(void)
1710 {
1711         return s_info.paused;
1712 }
1713
1714 /* End of a file */