Update heap-monitor
[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                 /*!
858                  * \note
859                  * Some case requires to update the content of other box from livebox_XXX ABI.
860                  * In that case this function can be used so we have not to filter it from here.
861                  * ex) Setting accessibility.
862                  * Press the assistive light, turned on, need to update other instances too.
863                  * Then the box will use this function from livebox_clicked function.
864                  */
865         }
866
867         EINA_LIST_FOREACH(s_info.item_list, l, item) {
868                 if (!strcmp(item->inst->id, filename)) {
869                         return append_pending_list(item);
870                 }
871         }
872
873         return LB_STATUS_ERROR_NOT_EXIST;
874 }
875
876 int livebox_trigger_update_monitor(const char *filename, int is_pd)
877 {
878         char *fname;
879         int ret;
880
881         if (so_current_op() != LIVEBOX_OP_UNKNOWN) {
882                 ErrPrint("Current operation: %d\n", so_current_op());
883                 return LB_STATUS_ERROR_INVALID;
884         }
885
886         if (is_pd) {
887                 int len;
888                 len = strlen(filename) + strlen(".desc");
889
890                 fname = malloc(len + 1);
891                 if (!fname) {
892                         ErrPrint("Heap: %s\n", strerror(errno));
893                         return LB_STATUS_ERROR_MEMORY;
894                 }
895
896                 snprintf(fname, len, "%s.desc", filename);
897         } else {
898                 fname = strdup(filename);
899                 if (!fname) {
900                         ErrPrint("Heap: %s\n", strerror(errno));
901                         return LB_STATUS_ERROR_MEMORY;
902                 }
903         }
904
905         if (access(fname, R_OK | W_OK) != 0) {
906                 ErrPrint("access: %s (%s)\n", fname, strerror(errno));
907                 ret = LB_STATUS_ERROR_IO;
908         } else {
909                 ret = update_monitor_trigger_update_cb(fname, 0);
910         }
911
912         free(fname);
913         return ret;
914 }
915
916 HAPI int lb_open_pd(const char *pkgname)
917 {
918         Eina_List *l;
919         char *tmp;
920
921         EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
922                 if (!strcmp(pkgname, tmp)) {
923                         return 0;
924                 }
925         }
926
927         tmp = strdup(pkgname);
928         if (!tmp) {
929                 ErrPrint("Heap: %s\n", strerror(errno));
930                 return LB_STATUS_ERROR_MEMORY;
931         }
932
933         if (!s_info.pd_list) {
934                 pending_timer_freeze();
935         }
936
937         s_info.pd_list = eina_list_append(s_info.pd_list, tmp);
938
939         /*!
940          * Find all instances from the pending list.
941          * Move them to pd_open_pending_timer
942          */
943         migrate_to_pd_open_pending_list(pkgname);
944         return LB_STATUS_SUCCESS;
945 }
946
947 HAPI int lb_close_pd(const char *pkgname)
948 {
949         Eina_List *l;
950         Eina_List *n;
951         char *tmp;
952
953         EINA_LIST_FOREACH_SAFE(s_info.pd_list, l, n, tmp) {
954                 if (strcmp(tmp, pkgname)) {
955                         continue;
956                 }
957
958                 s_info.pd_list = eina_list_remove(s_info.pd_list, tmp);
959                 free(tmp);
960
961                 if (!s_info.pd_list) {
962                         pending_timer_thaw();
963                 }
964
965                 /*!
966                  * Move all items in pd_open_pending_list
967                  * to pending_list.
968                  */
969                 migrate_to_pending_list(pkgname);
970                 return LB_STATUS_SUCCESS;
971         }
972
973         return LB_STATUS_ERROR_NOT_EXIST;
974 }
975
976 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)
977 {
978         struct instance *inst;
979         struct item *item;
980         int ret;
981         int create_ret;
982         int need_to_create;
983
984         need_to_create = 0;
985         *out_content = NULL;
986         *out_title = NULL;
987
988         inst = so_find_instance(pkgname, id);
989         if (inst) {
990                 DbgPrint("Instance is already exists [%s - %s] content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
991                 return LB_STATUS_SUCCESS;
992         }
993
994         if (!skip_need_to_create) {
995                 ret = so_create_needed(pkgname, cluster, category, abi);
996                 if (ret != NEED_TO_CREATE) {
997                         return LB_STATUS_ERROR_PERMISSION;
998                 }
999
1000                 need_to_create = 1;
1001         }
1002
1003         item = calloc(1, sizeof(*item));
1004         if (!item) {
1005                 ErrPrint("Heap: %s (%s - %s, content[%s], cluster[%s], category[%s], abi[%s])\n", strerror(errno), pkgname, id, content_info, cluster, category, abi);
1006                 return LB_STATUS_ERROR_MEMORY;
1007         }
1008
1009         ret = update_monitor_add(id, item);
1010         if (ret < 0) {
1011                 free(item);
1012                 return ret;
1013         }
1014
1015         create_ret = so_create(pkgname, id, content_info, timeout, has_livebox_script, cluster, category, abi, &inst);
1016         if (create_ret < 0) {
1017                 update_monitor_del(id,  item);
1018                 free(item);
1019
1020                 *w = 0;
1021                 *h = 0;
1022                 *priority = 0.0f;
1023                 return create_ret;
1024         }
1025
1026         item->inst = inst;
1027
1028         if (period > 0.0f && !s_info.secured) {
1029                 item->timer = util_timer_add(period, updator_cb, item);
1030                 if (!item->timer) {
1031                         ErrPrint("Failed to add timer (%s - %s, content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
1032                         update_monitor_del(id, item);
1033                         (void)so_destroy(inst);
1034                         free(item);
1035                         return LB_STATUS_ERROR_FAULT;
1036                 }
1037
1038                 if (s_info.paused) {
1039                         timer_freeze(item);
1040                 }
1041         } else {
1042                 DbgPrint("Local update timer is disabled: %lf (%d)\n", period, s_info.secured);
1043                 item->timer = NULL;
1044         }
1045
1046         s_info.item_list = eina_list_append(s_info.item_list, item);
1047
1048         if (create_ret & NEED_TO_SCHEDULE) {
1049                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1050                 (void)append_pending_list(item);
1051         }
1052
1053         if (create_ret & OUTPUT_UPDATED) {
1054                 update_monitor_cnt(item);
1055                 /*!
1056                  * \note
1057                  * To send a output info, get the info forcely.
1058                  * but the output file monitor will do this again
1059                  *
1060                  * This function will set the tmp_content and tmp_title
1061                  * even if it has no updates on the content, title,
1062                  * it will set them to NULL.
1063                  */
1064                 if (so_get_output_info(inst, w, h, priority, out_content, out_title) == LB_STATUS_SUCCESS) {
1065                         if (*out_content) {
1066                                 char *tmp;
1067
1068                                 tmp = strdup(*out_content);
1069                                 if (!tmp) {
1070                                         ErrPrint("Memory: %s\n", strerror(errno));
1071                                 }
1072
1073                                 *out_content = tmp;
1074                         }
1075
1076                         if (*out_title) {
1077                                 char *tmp;
1078
1079                                 tmp = strdup(*out_title);
1080                                 if (!tmp) {
1081                                         ErrPrint("Memory: %s\n", strerror(errno));
1082                                 }
1083
1084                                 *out_title = tmp;
1085                         }
1086                 }
1087         }
1088
1089         *w = inst->w;
1090         *h = inst->h;
1091         *priority = inst->priority;
1092         return need_to_create;
1093 }
1094
1095 HAPI int lb_destroy(const char *pkgname, const char *id)
1096 {
1097         Eina_List *l;
1098         struct instance *inst;
1099         struct item *item;
1100
1101         inst = so_find_instance(pkgname, id);
1102         if (!inst) {
1103                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1104                 return LB_STATUS_ERROR_INVALID;
1105         }
1106
1107         l = find_item(inst);
1108         if (!l) {
1109                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1110                 return LB_STATUS_ERROR_NOT_EXIST;
1111         }
1112
1113         item = eina_list_data_get(l);
1114         s_info.item_list = eina_list_remove_list(s_info.item_list, l);
1115
1116         if (s_info.update == item) {
1117                 s_info.update = NULL;
1118         }
1119
1120         if (item->timer) {
1121                 clear_from_pd_open_pending_list(item);
1122                 clear_from_pending_list(item);
1123                 ecore_timer_del(item->timer);
1124                 item->timer = NULL;
1125
1126                 if (item->monitor) {
1127                         item->deleteme = 1;
1128                 } else {
1129                         update_monitor_del(id, item);
1130                 }
1131         }
1132
1133         if (!item->monitor) {
1134                 free(item);
1135                 (void)so_destroy(inst);
1136         }
1137
1138         return LB_STATUS_SUCCESS;
1139 }
1140
1141 HAPI int lb_resize(const char *pkgname, const char *id, int w, int h)
1142 {
1143         Eina_List *l;
1144         struct instance *inst;
1145         struct item *item;
1146         int ret;
1147
1148         inst = so_find_instance(pkgname, id);
1149         if (!inst) {
1150                 ErrPrint("Instance %s - %s is not created (%dx%d)\n", pkgname, id, w, h);
1151                 return LB_STATUS_ERROR_INVALID;
1152         }
1153
1154         l = find_item(inst);
1155         if (!l) {
1156                 ErrPrint("Instance is not found (%s - %s, %dx%d)\n", pkgname, id, w, h);
1157                 return LB_STATUS_ERROR_NOT_EXIST;
1158         }
1159
1160         item = eina_list_data_get(l);
1161
1162         ret = so_resize(inst, w, h);
1163         if (ret < 0) {
1164                 return ret;
1165         }
1166
1167         if (ret & NEED_TO_SCHEDULE) {
1168                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1169                 (void)append_pending_list(item);
1170         }
1171
1172         if (ret & OUTPUT_UPDATED) {
1173                 update_monitor_cnt(item);
1174         }
1175
1176         return LB_STATUS_SUCCESS;
1177 }
1178
1179 HAPI char *lb_pinup(const char *pkgname, const char *id, int pinup)
1180 {
1181         struct instance *inst;
1182         char *ret;
1183
1184         inst = so_find_instance(pkgname, id);
1185         if (!inst) {
1186                 ErrPrint("Instance %s - %s is not found (pinup[%d])\n", pkgname, id, pinup);
1187                 return NULL;
1188         }
1189
1190         ret = so_pinup(inst, pinup);
1191         return ret;
1192 }
1193
1194 HAPI int lb_set_period(const char *pkgname, const char *id, double period)
1195 {
1196         Eina_List *l;
1197         struct instance *inst;
1198         struct item *item;
1199
1200         inst = so_find_instance(pkgname, id);
1201         if (!inst) {
1202                 ErrPrint("Instance %s - %s is not found (period[%lf])\n", pkgname, id, period);
1203                 return LB_STATUS_ERROR_INVALID;
1204         }
1205
1206         l = find_item(inst);
1207         if (!l) {
1208                 ErrPrint("Instance is not found (%s - %s, period[%lf])\n", pkgname, id, period);
1209                 return LB_STATUS_ERROR_NOT_EXIST;
1210         }
1211
1212         item = eina_list_data_get(l);
1213
1214         if (period <= 0.0f) {
1215                 if (item->timer) {
1216                         ecore_timer_del(item->timer);
1217                         item->timer = NULL;
1218                 }
1219         } else {
1220                 if (item->timer) {
1221                         util_timer_interval_set(item->timer, period);
1222                 } else if (!s_info.secured) {
1223                         item->timer = util_timer_add(period, updator_cb, item);
1224                         if (!item->timer) {
1225                                 ErrPrint("Failed to add timer (%s - %s)\n", pkgname, id);
1226                                 return LB_STATUS_ERROR_FAULT;
1227                         }
1228
1229                         if (s_info.paused) {
1230                                 timer_freeze(item);
1231                         }
1232                 }
1233         }
1234
1235         return LB_STATUS_SUCCESS;
1236 }
1237
1238 HAPI int lb_clicked(const char *pkgname, const char *id, const char *event, double timestamp, double x, double y)
1239 {
1240         Eina_List *l;
1241         struct instance *inst;
1242         struct item *item;
1243         int ret;
1244
1245         inst = so_find_instance(pkgname, id);
1246         if (!inst) {
1247                 ErrPrint("Instance %s - %s is not exists (event[%s])\n", pkgname, id, event);
1248                 return LB_STATUS_ERROR_INVALID;
1249         }
1250
1251         l = find_item(inst);
1252         if (!l) {
1253                 ErrPrint("Instance is not found (%s - %s, event[%s])\n", pkgname, id, event);
1254                 return LB_STATUS_ERROR_NOT_EXIST;
1255         }
1256
1257         item = eina_list_data_get(l);
1258
1259         ret = so_clicked(inst, event, timestamp, x, y);
1260         if (ret < 0) {
1261                 return ret;
1262         }
1263
1264         if (ret & NEED_TO_SCHEDULE) {
1265                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1266                 (void)append_pending_list(item);
1267         }
1268
1269         if (ret & OUTPUT_UPDATED) {
1270                 update_monitor_cnt(item);
1271         }
1272
1273         return LB_STATUS_SUCCESS;
1274 }
1275
1276 HAPI int lb_script_event(const char *pkgname, const char *id, const char *emission, const char *source, struct event_info *event_info)
1277 {
1278         Eina_List *l;
1279         struct instance *inst;
1280         struct item *item;
1281         int ret;
1282
1283         inst = so_find_instance(pkgname, id);
1284         if (!inst) {
1285                 ErrPrint("Instance %s - %s is not exists (emission[%s], source[%s])\n", pkgname, id, emission, source);
1286                 return LB_STATUS_ERROR_INVALID;
1287         }
1288
1289         l = find_item(inst);
1290         if (!l) {
1291                 ErrPrint("Instance is not found (%s - %s, emissino[%s], source[%s])\n", pkgname, id, emission, source);
1292                 return LB_STATUS_ERROR_NOT_EXIST;
1293         }
1294
1295         item = eina_list_data_get(l);
1296
1297         if (emission && source && !strcmp(source, id)) {
1298                 if (item->inst->item->has_livebox_script) {
1299                         if (!strcmp(emission, "lb,show")) {
1300                                 item->is_lb_show = 1;
1301
1302                                 if (item->is_lb_updated && !is_pended_item(item)) {
1303                                         reset_lb_updated_flag(item);
1304                                 }
1305
1306                                 source = util_uri_to_path(source);
1307                         } else if (!strcmp(emission, "lb,hide")) {
1308                                 DbgPrint("Livebox(%s) script is hide now\n", id);
1309                                 item->is_lb_show = 0;
1310
1311                                 source = util_uri_to_path(source);
1312                         }
1313                 }
1314
1315                 if (!strcmp(emission, "pd,show")) {
1316                         item->is_pd_show = 1;
1317                         source = util_uri_to_path(source);
1318                 } else if (!strcmp(emission, "pd,hide")) {
1319                         item->is_pd_show = 0;
1320                         source = util_uri_to_path(source);
1321                 }
1322         }
1323
1324         ret = so_script_event(inst, emission, source, event_info);
1325         if (ret < 0) {
1326                 return ret;
1327         }
1328
1329         if (ret & NEED_TO_SCHEDULE) {
1330                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1331                 (void)append_pending_list(item);
1332         }
1333
1334         if (ret & OUTPUT_UPDATED) {
1335                 update_monitor_cnt(item);
1336         }
1337
1338         return LB_STATUS_SUCCESS;
1339 }
1340
1341 HAPI int lb_is_pinned_up(const char *pkgname, const char *id)
1342 {
1343         Eina_List *l;
1344         struct instance *inst;
1345         struct item *item;
1346
1347         inst = so_find_instance(pkgname, id);
1348         if (!inst) {
1349                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1350                 return LB_STATUS_ERROR_INVALID;
1351         }
1352
1353         l = find_item(inst);
1354         if (!l) {
1355                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1356                 return LB_STATUS_ERROR_NOT_EXIST;
1357         }
1358
1359         item = eina_list_data_get(l);
1360         if (!item) {
1361                 ErrPrint("Invalid item(%s - %s)\n", pkgname, id);
1362                 return LB_STATUS_ERROR_FAULT;
1363         }
1364         /*!
1365          * NOTE:
1366          * item is not used.
1367          * Maybe this is not neccessary for this operation
1368          */
1369         return so_is_pinned_up(inst);
1370 }
1371
1372 HAPI int lb_change_group(const char *pkgname, const char *id, const char *cluster, const char *category)
1373 {
1374         Eina_List *l;
1375         struct instance *inst;
1376         struct item *item;
1377         int ret;
1378
1379         inst = so_find_instance(pkgname, id);
1380         if (!inst) {
1381                 ErrPrint("Instance %s - %s is not created (cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1382                 return LB_STATUS_ERROR_INVALID;
1383         }
1384
1385         l = find_item(inst);
1386         if (!l) {
1387                 ErrPrint("Instance is not found(%s - %s, cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1388                 return LB_STATUS_ERROR_NOT_EXIST;
1389         }
1390
1391         item = eina_list_data_get(l);
1392
1393         ret = so_change_group(inst, cluster, category);
1394         if (ret < 0) {
1395                 return ret;
1396         }
1397
1398         if (ret & NEED_TO_SCHEDULE) {
1399                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1400                 (void)append_pending_list(item);
1401         }
1402
1403         if (ret & OUTPUT_UPDATED) {
1404                 update_monitor_cnt(item);
1405         }
1406
1407         return LB_STATUS_SUCCESS;
1408 }
1409
1410 static int lb_sys_event(struct instance *inst, struct item *item, int event)
1411 {
1412         int ret;
1413
1414         ret = so_sys_event(inst, event);
1415         if (ret < 0) {
1416                 return ret;
1417         }
1418
1419         if (ret & NEED_TO_SCHEDULE) {
1420                 (void)append_pending_list(item);
1421         }
1422
1423         if (ret & OUTPUT_UPDATED) {
1424                 update_monitor_cnt(item);
1425         }
1426
1427         return LB_STATUS_SUCCESS;
1428 }
1429
1430 HAPI int lb_system_event(const char *pkgname, const char *id, int event)
1431 {
1432         Eina_List *l;
1433         struct instance *inst;
1434         struct item *item;
1435
1436         inst = so_find_instance(pkgname, id);
1437         if (!inst) {
1438                 ErrPrint("instance %s - %s is not created\n");
1439                 return LB_STATUS_ERROR_INVALID;
1440         }
1441
1442         l = find_item(inst);
1443         if (!l) {
1444                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1445                 return LB_STATUS_ERROR_NOT_EXIST;
1446         }
1447
1448         item = eina_list_data_get(l);
1449         return lb_sys_event(inst, item, event);
1450 }
1451
1452 HAPI int lb_update(const char *pkgname, const char *id)
1453 {
1454         Eina_List *l;
1455         struct instance *inst;
1456         struct item *item;
1457
1458         inst = so_find_instance(pkgname, id);
1459         if (!inst) {
1460                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1461                 return LB_STATUS_ERROR_INVALID;
1462         }
1463
1464         l = find_item(inst);
1465         if (!l) {
1466                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1467                 return LB_STATUS_ERROR_NOT_EXIST;
1468         }
1469
1470         item = eina_list_data_get(l);
1471         (void)append_pending_list(item);
1472         return LB_STATUS_SUCCESS;
1473 }
1474
1475 HAPI int lb_update_all(const char *pkgname, const char *cluster, const char *category)
1476 {
1477         Eina_List *l;
1478         Eina_List *n;
1479         struct item *item;
1480
1481         DbgPrint("Update content for %s\n", pkgname ? pkgname : "(all)");
1482         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1483                 if (item->deleteme) {
1484                         continue;
1485                 }
1486
1487                 if (cluster && strcasecmp(item->inst->cluster, cluster)) {
1488                         continue;
1489                 }
1490
1491                 if (category && strcasecmp(item->inst->category, category)) {
1492                         continue;
1493                 }
1494
1495                 if (pkgname && strlen(pkgname)) {
1496                         if (!strcmp(item->inst->item->pkgname, pkgname)) {
1497                                 (void)append_pending_list(item);
1498                         }
1499                 } else {
1500                         (void)append_pending_list(item);
1501                 }
1502         }
1503
1504         return LB_STATUS_SUCCESS;
1505 }
1506
1507 HAPI int lb_delete_all_deleteme(void)
1508 {
1509         Eina_List *l;
1510         Eina_List *n;
1511         struct item *item;
1512         int cnt = 0;
1513
1514         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1515                 if (!item->deleteme) {
1516                         continue;
1517                 }
1518
1519                 update_monitor_del(item->inst->id, item);
1520                 (void)so_destroy(item->inst);
1521                 free(item);
1522                 cnt++;
1523         }
1524
1525         DbgPrint("Delete all deleteme: %d\n", cnt);
1526         return LB_STATUS_SUCCESS;
1527 }
1528
1529 HAPI int lb_system_event_all(int event)
1530 {
1531         Eina_List *l;
1532         Eina_List *n;
1533         struct item *item;
1534
1535         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1536                 if (item->deleteme) {
1537                         continue;
1538                 }
1539
1540                 DbgPrint("System event for %s (%d)\n", item->inst->id, event);
1541                 lb_sys_event(item->inst, item, event);
1542         }
1543
1544         return LB_STATUS_SUCCESS;
1545 }
1546
1547 HAPI void lb_pause_all(void)
1548 {
1549         Eina_List *l;
1550         struct item *item;
1551
1552         s_info.paused = 1;
1553
1554         pending_timer_freeze();
1555
1556         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1557                 if (item->deleteme) {
1558                         DbgPrint("Instance %s skip timer pause (deleteme)\n", item->inst->item->pkgname);
1559                         continue;
1560                 }
1561
1562                 if (item->is_paused) {
1563                         continue;
1564                 }
1565
1566                 timer_freeze(item);
1567
1568                 lb_sys_event(item->inst, item, LB_SYS_EVENT_PAUSED);
1569         }
1570 }
1571
1572 HAPI void lb_resume_all(void)
1573 {
1574         Eina_List *l;
1575         Eina_List *n;
1576         struct item *item;
1577
1578         s_info.paused = 0;
1579
1580         pending_timer_thaw();
1581
1582         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1583                 if (item->deleteme) {
1584                         DbgPrint("Instance %s skip timer resume (deleteme)\n", item->inst->item->pkgname);
1585                         continue;
1586                 }
1587
1588                 if (item->is_paused) {
1589                         continue;
1590                 }
1591
1592                 lb_sys_event(item->inst, item, LB_SYS_EVENT_RESUMED);
1593
1594                 if (item->updated_in_pause) {
1595                         (void)append_pending_list(item);
1596                         item->updated_in_pause = 0;
1597                 }
1598
1599                 /*!
1600                  * \note
1601                  * After send the resume callback, call this function.
1602                  * Because the timer_thaw can call the update function.
1603                  * Before resumed event is notified to the livebox,
1604                  * Do not call update function
1605                  */
1606                 if (timer_thaw(item) == UPDATE_ITEM_DELETED) {
1607                         /* item is deleted */
1608                 }
1609         }
1610 }
1611
1612 HAPI int lb_pause(const char *pkgname, const char *id)
1613 {
1614         struct instance *inst;
1615         Eina_List *l;
1616         struct item *item;
1617
1618         inst = so_find_instance(pkgname, id);
1619         if (!inst) {
1620                 return LB_STATUS_ERROR_INVALID;
1621         }
1622
1623         l = find_item(inst);
1624         if (!l) {
1625                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1626                 return LB_STATUS_ERROR_NOT_EXIST;
1627         }
1628
1629         item = eina_list_data_get(l);
1630         if (!item) {
1631                 return LB_STATUS_ERROR_FAULT;
1632         }
1633
1634         if (item->deleteme) {
1635                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1636                 return LB_STATUS_ERROR_BUSY;
1637         }
1638
1639         item->is_paused = 1;
1640
1641         if (s_info.paused) {
1642                 return LB_STATUS_SUCCESS;
1643         }
1644
1645         timer_freeze(item);
1646
1647         lb_sys_event(inst, item, LB_SYS_EVENT_PAUSED);
1648
1649         return LB_STATUS_SUCCESS;
1650 }
1651
1652 HAPI int lb_resume(const char *pkgname, const char *id)
1653 {
1654         struct instance *inst;
1655         Eina_List *l;
1656         struct item *item;
1657         int ret;
1658
1659         inst = so_find_instance(pkgname, id);
1660         if (!inst) {
1661                 return LB_STATUS_ERROR_INVALID;
1662         }
1663
1664         l = find_item(inst);
1665         if (!l) {
1666                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1667                 return LB_STATUS_ERROR_NOT_EXIST;
1668         }
1669
1670         item = eina_list_data_get(l);
1671         if (!item) {
1672                 return LB_STATUS_ERROR_FAULT;
1673         }
1674
1675         if (item->deleteme) {
1676                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1677                 return LB_STATUS_ERROR_BUSY;
1678         }
1679
1680         item->is_paused = 0;
1681
1682         if (s_info.paused) {
1683                 return LB_STATUS_SUCCESS;
1684         }
1685
1686         lb_sys_event(inst, item, LB_SYS_EVENT_RESUMED);
1687
1688         ret = timer_thaw(item);
1689         if (ret == UPDATE_ITEM_DELETED) {
1690                 /*!
1691                  * \note
1692                  * ITEM is deleted
1693                  */
1694                 return LB_STATUS_SUCCESS;
1695         } else if (ret == UPDATE_INVOKED) {
1696                 /*!
1697                  * \note
1698                  * if the update is successfully done, the updated_in_pause will be reset'd.
1699                  * or append it to the pending list
1700                  */
1701         }
1702
1703         if (item->updated_in_pause) {
1704                 (void)append_pending_list(item);
1705                 item->updated_in_pause = 0;
1706         }
1707
1708         return LB_STATUS_SUCCESS;
1709 }
1710
1711 HAPI void lb_turn_secured_on(void)
1712 {
1713         s_info.secured = 1;
1714 }
1715
1716 HAPI int lb_is_all_paused(void)
1717 {
1718         return s_info.paused;
1719 }
1720
1721 /* End of a file */