946a0786ac6ca1105f7c15b7b3e5584cfb85d7e0
[apps/native/widget/widget.git] / src / dynamicbox.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 <errno.h>
19 #include <stdlib.h> /* malloc */
20 #include <string.h> /* strdup */
21 #include <libgen.h>
22 #include <unistd.h> /* access */
23 #define __USE_GNU
24 #include <dlfcn.h>
25
26 #include <dlog.h>
27 #include <dynamicbox_errno.h>
28 #include <dynamicbox_service.h>
29 #include <dynamicbox_provider.h>
30 #include <dynamicbox_provider_buffer.h>
31 #include <dynamicbox_conf.h>
32 #include <dynamicbox_buffer.h>
33 #include <Evas.h>
34 #include <Ecore.h>
35
36 #include "debug.h"
37 #include "dlist.h"
38 #include "util.h"
39 #include "dynamicbox.h"
40
41 #define PUBLIC __attribute__((visibility("default")))
42
43 #define FILE_SCHEMA    "file://"
44
45 /**
46  * @note
47  * This value is configurable value.
48  */
49 #define FRAME_WAIT_INTERVAL (1.0f/6.0f)
50
51 struct block {
52     unsigned int idx;
53
54     char *type;
55     char *part;
56     char *data;
57     char *option;
58     char *id;
59     char *file;
60     char *target_id;
61 };
62
63 struct dynamicbox_desc {
64     FILE *fp;
65     int for_pd;
66
67     unsigned int last_idx;
68
69     struct dlist *block_list;
70 };
71
72 struct dynamicbox_buffer_data {
73     int is_gbar;
74     int accelerated;
75
76     /* for Buffer event wrapper */
77     int (*handler)(dynamicbox_buffer_h , dynamicbox_buffer_event_data_t, void *);
78     void *cbdata;
79
80     char *content;
81     char *title;
82     char *icon;
83     char *name;
84
85     Ecore_Timer *frame_wait_timer;
86 };
87
88 /**
89  * @brief These functions are defined in the data-provider-slave
90  */
91 static struct info {
92     const char *(*find_pkgname)(const char *filename);
93     int (*request_update_by_id)(const char *uri);
94     int (*trigger_update_monitor)(const char *id, int is_gbar);
95     int (*update_extra_info)(const char *id, const char *content, const char *title, const char *icon, const char *name);
96
97     enum load_type {
98         LOAD_TYPE_UNKNOWN = -1,
99         LOAD_TYPE_SLAVE   = 0,
100         LOAD_TYPE_APP     = 1
101     } type;
102
103     union _updated {
104         struct _slave {
105             int (*send)(const char *pkgname, const char *id, dynamicbox_buffer_h handle, int idx, int x, int y, int w, int h, int gbar, const char *descfile);
106         } slave;
107
108         struct _app {
109             int (*send)(dynamicbox_buffer_h handle, int idx, int x, int y, int w, int h, int gbar);
110         } app;
111     } updated;
112 } s_info = {
113     .find_pkgname = NULL,
114     .request_update_by_id = NULL,
115     .trigger_update_monitor = NULL,
116     .update_extra_info = NULL,
117     .type = LOAD_TYPE_UNKNOWN,    /* Not initialized */
118 };
119
120 #define FUNC_PREFIX                               "dynamicbox_"
121 #define FUNC_DYNAMICBOX_SEND_UPDATED              FUNC_PREFIX "send_buffer_updated"
122 #define FUNC_DYNAMICBOX_PROVIDER_APP_UPDATED      FUNC_PREFIX "provider_app_buffer_updated"
123 #define FUNC_DYNAMICBOX_FIND_PKGNAME              FUNC_PREFIX "find_pkgname"
124 #define FUNC_DYNAMICBOX_REQUEST_UPDATE_BY_ID      FUNC_PREFIX "request_update_by_id"
125 #define FUNC_DYNAMICBOX_TRIGGER_UPDATE_MONITOR    FUNC_PREFIX "trigger_update_monitor"
126 #define FUNC_DYNAMICBOX_UPDATE_EXTRA_INFO         FUNC_PREFIX "update_extra_info"
127
128 static inline void load_update_function(void)
129 {
130     /* Must to be checked the slave function first. */
131     s_info.updated.slave.send = dlsym(RTLD_DEFAULT, FUNC_DYNAMICBOX_SEND_UPDATED);
132     if (s_info.updated.slave.send) {
133         s_info.type = LOAD_TYPE_SLAVE;
134         DbgPrint("Slave detected\n");
135     } else {
136         s_info.updated.app.send = dlsym(RTLD_DEFAULT, FUNC_DYNAMICBOX_PROVIDER_APP_UPDATED);
137         if (s_info.updated.app.send) {
138             s_info.type = LOAD_TYPE_APP;
139             DbgPrint("App detected\n");
140         }
141     }
142 }
143
144 static int send_updated(const char *pkgname, const char *id, dynamicbox_buffer_h handle, int idx, int x, int y, int w, int h, int gbar, const char *descfile)
145 {
146     int ret = DBOX_STATUS_ERROR_INVALID_PARAMETER;
147
148     if (s_info.type == LOAD_TYPE_UNKNOWN) {
149         load_update_function();
150     }
151
152     if (s_info.type == LOAD_TYPE_APP) {
153         ret = s_info.updated.app.send(handle, idx, x, y, w, h, gbar);
154     } else if (s_info.type == LOAD_TYPE_SLAVE) {
155         /**
156          * pkgname, id are used for finding handle of direct connection.
157          */
158         ret = s_info.updated.slave.send(pkgname, id, handle, idx, x, y, w, h, gbar, descfile);
159     } else {
160         dynamicbox_damage_region_t region = {
161             .x = x,
162             .y = y,
163             .w = w,
164             .h = h,
165         };
166         ret = dynamicbox_provider_send_buffer_updated(handle, idx, &region, gbar, descfile);
167     }
168
169     return ret;
170 }
171
172 static char *id_to_uri(const char *id)
173 {
174     char *uri;
175     int uri_len;
176
177     uri_len = strlen(id) + strlen(FILE_SCHEMA) + 1;
178
179     uri = malloc(uri_len);
180     if (!uri) {
181         return NULL;
182     }
183
184     snprintf(uri, uri_len, FILE_SCHEMA "%s", id);
185     return uri;
186 }
187
188 static inline int event_handler_wrapper(dynamicbox_buffer_h buffer, dynamicbox_buffer_event_data_t event_info, void *data)
189 {
190     const char *pkgname;
191     const char *id;
192     struct dynamicbox_buffer_data *cbdata = data;
193     int ret;
194
195     pkgname = dynamicbox_provider_buffer_pkgname(buffer);
196     if (!pkgname) {
197         ErrPrint("pkgname is not valid\n");
198         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
199     }
200
201     id = dynamicbox_provider_buffer_id(buffer);
202     if (!id) {
203         ErrPrint("id is not valid[%s]\n", pkgname);
204         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
205     }
206
207     if (cbdata->handler) {
208         ret = cbdata->handler(buffer, event_info, cbdata->cbdata);
209     } else {
210         ret = DBOX_STATUS_ERROR_FAULT;
211     }
212
213     switch (event_info->type) {
214         case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT:
215         case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT_NEXT:
216         case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT_PREV:
217         case DBOX_BUFFER_EVENT_ACCESS_ACTIVATE:
218         case DBOX_BUFFER_EVENT_ACCESS_ACTION_UP:
219         case DBOX_BUFFER_EVENT_ACCESS_ACTION_DOWN:
220         case DBOX_BUFFER_EVENT_ACCESS_SCROLL_UP:
221         case DBOX_BUFFER_EVENT_ACCESS_SCROLL_MOVE:
222         case DBOX_BUFFER_EVENT_ACCESS_SCROLL_DOWN:
223         case DBOX_BUFFER_EVENT_ACCESS_UNHIGHLIGHT:
224         case DBOX_BUFFER_EVENT_ACCESS_VALUE_CHANGE:
225         case DBOX_BUFFER_EVENT_ACCESS_MOUSE:
226         case DBOX_BUFFER_EVENT_ACCESS_BACK:
227         case DBOX_BUFFER_EVENT_ACCESS_OVER:
228         case DBOX_BUFFER_EVENT_ACCESS_READ:
229         case DBOX_BUFFER_EVENT_ACCESS_ENABLE:
230         case DBOX_BUFFER_EVENT_ACCESS_DISABLE:
231             DbgPrint("Accessibility event: %d\n", event_info->type);
232             if (ret < 0) {
233                 (void)dynamicbox_provider_send_access_status(pkgname, id, DBOX_ACCESS_STATUS_ERROR);
234             } else {
235                 (void)dynamicbox_provider_send_access_status(pkgname, id, ret);
236             }
237             break;
238         case DBOX_BUFFER_EVENT_KEY_UP:
239         case DBOX_BUFFER_EVENT_KEY_DOWN:
240         case DBOX_BUFFER_EVENT_KEY_FOCUS_IN:
241         case DBOX_BUFFER_EVENT_KEY_FOCUS_OUT:
242             DbgPrint("Key event: %d\n", event_info->type);
243             if (ret < 0) {
244                 (void)dynamicbox_provider_send_key_status(pkgname, id, DBOX_KEY_STATUS_ERROR);
245             } else {
246                 (void)dynamicbox_provider_send_key_status(pkgname, id, ret);
247             }
248             break;
249         default:
250             break;
251     }
252
253     return ret;
254 }
255
256 static inline int default_event_handler(dynamicbox_buffer_h buffer, dynamicbox_buffer_event_data_t event_info, void *data)
257 {
258     /* NOP */
259     return 0;
260 }
261
262 PUBLIC const int DBOX_DONE = 0x00;
263 PUBLIC const int DBOX_OUTPUT_UPDATED = 0x02;
264 PUBLIC const int DBOX_USE_NET = 0x04;
265
266 PUBLIC const int DBOX_NEED_TO_SCHEDULE = 0x01;
267 PUBLIC const int DBOX_NEED_TO_CREATE = 0x01;
268 PUBLIC const int DBOX_NEED_TO_DESTROY = 0x01;
269 PUBLIC const int DBOX_FORCE_TO_SCHEDULE = 0x08;
270
271 PUBLIC const int DBOX_SYS_EVENT_FONT_CHANGED = 0x01;
272 PUBLIC const int DBOX_SYS_EVENT_LANG_CHANGED = 0x02;
273 PUBLIC const int DBOX_SYS_EVENT_TIME_CHANGED = 0x04;
274 PUBLIC const int DBOX_SYS_EVENT_REGION_CHANGED = 0x08;
275 PUBLIC const int DBOX_SYS_EVENT_TTS_CHANGED = 0x10;
276 PUBLIC const int DBOX_SYS_EVENT_PAUSED = 0x0100;
277 PUBLIC const int DBOX_SYS_EVENT_RESUMED = 0x0200;
278 PUBLIC const int DBOX_SYS_EVENT_MMC_STATUS_CHANGED = 0x0400;
279 PUBLIC const int DBOX_SYS_EVENT_DELETED = 0x0800;
280
281 PUBLIC struct dynamicbox_desc *dynamicbox_desc_open(const char *filename, int for_pd)
282 {
283     struct dynamicbox_desc *handle;
284     char *new_fname;
285
286     handle = calloc(1, sizeof(*handle));
287     if (!handle) {
288         ErrPrint("Error: %s\n", strerror(errno));
289         return NULL;
290     }
291
292     if (for_pd) {
293         int len;
294         len = strlen(filename) + strlen(".desc") + 1;
295         new_fname = malloc(len);
296         if (!new_fname) {
297             ErrPrint("Error: %s\n", strerror(errno));
298             free(handle);
299             return NULL;
300         }
301         snprintf(new_fname, len, "%s.desc", filename);
302     } else {
303         new_fname = strdup(filename);
304         if (!new_fname) {
305             ErrPrint("Error: %s\n", strerror(errno));
306             free(handle);
307             return NULL;
308         }
309     }
310
311     DbgPrint("Open a file %s with merge mode %s\n",
312             new_fname,
313             access(new_fname, F_OK) == 0 ? "enabled" : "disabled");
314
315     handle->fp = fopen(new_fname, "at");
316     free(new_fname);
317     if (!handle->fp) {
318         ErrPrint("Failed to open a file: %s\n", strerror(errno));
319         free(handle);
320         return NULL;
321     }
322
323     return handle;
324 }
325
326 PUBLIC int dynamicbox_desc_close(struct dynamicbox_desc *handle)
327 {
328     struct dlist *l;
329     struct dlist *n;
330     struct block *block;
331
332     if (!handle) {
333         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
334     }
335
336     dlist_foreach_safe(handle->block_list, l, n, block) {
337         handle->block_list = dlist_remove(handle->block_list, l);
338
339         fprintf(handle->fp, "{\n");
340         if (block->type) {
341             fprintf(handle->fp, "type=%s\n", block->type);
342         }
343
344         if (block->part) {
345             fprintf(handle->fp, "part=%s\n", block->part);
346         }
347
348         if (block->data) {
349             fprintf(handle->fp, "data=%s\n", block->data);
350         }
351
352         if (block->option) {
353             fprintf(handle->fp, "option=%s\n", block->option);
354         }
355
356         if (block->id) {
357             fprintf(handle->fp, "id=%s\n", block->id);
358         }
359
360         if (block->target_id) {
361             fprintf(handle->fp, "target=%s\n", block->target_id);
362         }
363         fprintf(handle->fp, "}\n");
364
365         free(block->type);
366         free(block->part);
367         free(block->data);
368         free(block->option);
369         free(block->id);
370         free(block->target_id);
371         free(block);
372     }
373
374     if (fclose(handle->fp) != 0) {
375         ErrPrint("fclose: %s\n", strerror(errno));
376     }
377     free(handle);
378     return DBOX_STATUS_ERROR_NONE;
379 }
380
381 PUBLIC int dynamicbox_desc_set_category(struct dynamicbox_desc *handle, const char *id, const char *category)
382 {
383     struct block *block;
384
385     if (!handle || !category) {
386         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
387     }
388
389     block = calloc(1, sizeof(*block));
390     if (!block) {
391         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
392     }
393
394     block->type = strdup(DBOX_DESC_TYPE_INFO);
395     if (!block->type) {
396         free(block);
397         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
398     }
399
400     block->part = strdup("category");
401     if (!block->part) {
402         free(block->type);
403         free(block);
404         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
405     }
406
407     block->data = strdup(category);
408     if (!block->data) {
409         free(block->type);
410         free(block->part);
411         free(block);
412         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
413     }
414
415     if (id) {
416         block->id = strdup(id);
417         if (!block->id) {
418             free(block->data);
419             free(block->type);
420             free(block->part);
421             free(block);
422             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
423         }
424     }
425
426     block->idx = handle->last_idx++;
427     handle->block_list = dlist_append(handle->block_list, block);
428     return block->idx;
429 }
430
431 PUBLIC int dynamicbox_desc_set_size(struct dynamicbox_desc *handle, const char *id, int w, int h)
432 {
433     struct block *block;
434     char buffer[BUFSIZ];
435
436     if (!handle) {
437         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
438     }
439
440     block = calloc(1, sizeof(*block));
441     if (!block) {
442         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
443     }
444
445     block->type = strdup(DBOX_DESC_TYPE_INFO);
446     if (!block->type) {
447         free(block);
448         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
449     }
450
451     block->part = strdup("size");
452     if (!block->part) {
453         free(block->type);
454         free(block);
455         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
456     }
457
458     if (id) {
459         block->id = strdup(id);
460         if (!block->id) {
461             free(block->part);
462             free(block->type);
463             free(block);
464             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
465         }
466     }
467
468     snprintf(buffer, sizeof(buffer), "%dx%d", w, h);
469     block->data = strdup(buffer);
470     if (!block->data) {
471         free(block->part);
472         free(block->type);
473         free(block);
474         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
475     }
476
477     block->idx = handle->last_idx++;
478     handle->block_list = dlist_append(handle->block_list, block);
479     return block->idx;
480 }
481
482 PUBLIC int dynamicbox_desc_set_id(struct dynamicbox_desc *handle, int idx, const char *id)
483 {
484     struct dlist *l;
485     struct block *block;
486
487     dlist_foreach(handle->block_list, l, block) {
488         if (block->idx == idx) {
489             if (strcasecmp(block->type, DBOX_DESC_TYPE_SCRIPT)) {
490                 ErrPrint("Invalid block is used\n");
491                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
492             }
493
494             free(block->target_id);
495             block->target_id = NULL;
496
497             if (!id || !strlen(id)) {
498                 return DBOX_STATUS_ERROR_NONE;
499             }
500
501             block->target_id = strdup(id);
502             if (!block->target_id) {
503                 ErrPrint("Heap: %s\n", strerror(errno));
504                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
505             }
506
507             return DBOX_STATUS_ERROR_NONE;
508         }
509     }
510
511     return DBOX_STATUS_ERROR_NOT_EXIST;
512 }
513
514 /*!
515  * \return idx
516  */
517 PUBLIC int dynamicbox_desc_add_block(struct dynamicbox_desc *handle, const char *id, const char *type, const char *part, const char *data, const char *option)
518 {
519     struct block *block;
520
521     if (!handle || !type) {
522         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
523     }
524
525     if (!part) {
526         part = "";
527     }
528
529     if (!data) {
530         data = "";
531     }
532
533     block = calloc(1, sizeof(*block));
534     if (!block) {
535         ErrPrint("Heap: %s\n", strerror(errno));
536         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
537     }
538
539     block->type = strdup(type);
540     if (!block->type) {
541         ErrPrint("Heap: %s\n", strerror(errno));
542         free(block);
543         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
544     }
545
546     block->part = strdup(part);
547     if (!block->part) {
548         ErrPrint("Heap: %s\n", strerror(errno));
549         free(block->type);
550         free(block);
551         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
552     }
553
554     block->data = strdup(data);
555     if (!block->data) {
556         ErrPrint("Heap: %s\n", strerror(errno));
557         free(block->type);
558         free(block->part);
559         free(block);
560         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
561     }
562
563     if (option) {
564         block->option = strdup(option);
565         if (!block->option) {
566             ErrPrint("Heap: %s\n", strerror(errno));
567             free(block->data);
568             free(block->type);
569             free(block->part);
570             free(block);
571             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
572         }
573     }
574
575     if (id) {
576         block->id = strdup(id);
577         if (!block->id) {
578             ErrPrint("Heap: %s\n", strerror(errno));
579             free(block->option);
580             free(block->data);
581             free(block->type);
582             free(block->part);
583             free(block);
584             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
585         }
586     }
587
588     block->idx = handle->last_idx++;
589     handle->block_list = dlist_append(handle->block_list, block);
590     return block->idx;
591 }
592
593 PUBLIC int dynamicbox_desc_del_block(struct dynamicbox_desc *handle, int idx)
594 {
595     struct dlist *l;
596     struct block *block;
597
598     if (!handle || idx < 0) {
599         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
600     }
601
602     dlist_foreach(handle->block_list, l, block) {
603         if (block->idx == idx) {
604             handle->block_list = dlist_remove(handle->block_list, l);
605             free(block->type);
606             free(block->part);
607             free(block->data);
608             free(block->option);
609             free(block->id);
610             free(block->target_id);
611             free(block);
612             return DBOX_STATUS_ERROR_NONE;
613         }
614     }
615
616     return DBOX_STATUS_ERROR_NOT_EXIST;
617 }
618
619 PUBLIC int dynamicbox_acquire_buffer(dynamicbox_buffer_h handle, int idx, int width, int height, int pixel_size)
620 {
621     int ret;
622
623     if (!handle || width <= 0 || height <= 0 || pixel_size <= 0 || idx > DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT) {
624         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
625     }
626
627     if (idx >= 0) {
628         int _width = 0;
629         int _height = 0;
630         int _pixel_size = 0;
631         /* To validate the buffer */
632         if (dynamicbox_provider_buffer_get_size(handle, &_width, &_height, &_pixel_size) < 0) {
633             ErrPrint("Failed to get buffer size\n");
634         }
635
636         if (_width != width || _height != height || pixel_size != _pixel_size) {
637             DbgPrint("Extra buffer's geometry is not matched with primary one\n");
638         }
639
640         ret = dynamicbox_provider_buffer_extra_acquire(handle, idx, width, height, pixel_size);
641     } else {
642         ret = dynamicbox_provider_buffer_acquire(handle, width, height, pixel_size);
643     }
644
645     return ret;
646 }
647
648 PUBLIC dynamicbox_buffer_h dynamicbox_create_buffer(const char *filename, int is_gbar, int auto_align, int (*handler)(dynamicbox_buffer_h , dynamicbox_buffer_event_data_t, void *), void *data)
649 {
650     struct dynamicbox_buffer_data *user_data;
651     const char *pkgname;
652     dynamicbox_buffer_h handle;
653     char *uri;
654
655     if (!filename) {
656         ErrPrint("Invalid argument: %p(%dx%d)\n", filename);
657         return NULL;
658     }
659
660     user_data = calloc(1, sizeof(*user_data));
661     if (!user_data) {
662         ErrPrint("Heap: %s\n", strerror(errno));
663         return NULL;
664     }
665
666     user_data->is_gbar = is_gbar;
667     user_data->handler = handler ? handler : default_event_handler;
668     user_data->cbdata = data;
669
670     uri = id_to_uri(filename);
671     if (!uri) {
672         ErrPrint("Heap: %s\n", strerror(errno));
673         free(user_data);
674         return NULL;
675     }
676
677     if (!s_info.find_pkgname) {
678         s_info.find_pkgname = dlsym(RTLD_DEFAULT, FUNC_DYNAMICBOX_FIND_PKGNAME);
679         if (!s_info.find_pkgname) {
680             ErrPrint("Failed to find a \"dynamicbox_find_pkgname\"\n");
681             free(user_data);
682             free(uri);
683             return NULL;
684         }
685     }
686
687     pkgname = s_info.find_pkgname(uri);
688     if (!pkgname) {
689         ErrPrint("Invalid Request\n");
690         free(user_data);
691         free(uri);
692         return NULL;
693     }
694
695     handle = dynamicbox_provider_buffer_create((!!is_gbar) ? DBOX_TYPE_GBAR : DBOX_TYPE_DBOX, pkgname, uri, auto_align, event_handler_wrapper, user_data);
696     free(uri);
697     if (!handle) {
698         free(user_data);
699         return NULL;
700     }
701
702     (void)dynamicbox_provider_buffer_set_user_data(handle, user_data);
703     return handle;
704 }
705
706 PUBLIC int dynamicbox_request_update(const char *filename)
707 {
708     char *uri;
709     int ret;
710
711     if (!filename) {
712         ErrPrint("Invalid argument\n");
713         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
714     }
715
716     uri = id_to_uri(filename);
717     if (!uri) {
718         ErrPrint("Heap: %s\n", strerror(errno));
719         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
720     }
721
722     if (!s_info.request_update_by_id) {
723         s_info.request_update_by_id = dlsym(RTLD_DEFAULT, FUNC_DYNAMICBOX_REQUEST_UPDATE_BY_ID);
724         if (!s_info.request_update_by_id) {
725             ErrPrint("\"dynamicbox_request_update_by_id\" is not exists\n");
726             free(uri);
727             return DBOX_STATUS_ERROR_FAULT;
728         }
729     }
730
731     ret = s_info.request_update_by_id(uri);
732     free(uri);
733     return ret;
734 }
735
736 PUBLIC unsigned int dynamicbox_resource_id(dynamicbox_buffer_h handle, int idx)
737 {
738     int ret;
739
740     if (!handle || idx > DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT) {
741         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
742     }
743
744     if (idx >= 0) {
745         ret = dynamicbox_provider_buffer_extra_resource_id(handle, idx);
746     } else {
747         ret = dynamicbox_provider_buffer_resource_id(handle);
748     }
749
750     return ret;
751 }
752
753 PUBLIC int dynamicbox_release_buffer(dynamicbox_buffer_h handle, int idx)
754 {
755     int ret;
756
757     if (!handle || idx > DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT) {
758         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
759     }
760
761     if (idx >= 0) {
762         ret = dynamicbox_provider_buffer_extra_release(handle, idx);
763     } else {
764         ret = dynamicbox_provider_buffer_release(handle);
765     }
766
767     DbgPrint("Release buffer: %d (%d)\n", idx, ret);
768     return ret;
769 }
770
771 PUBLIC int dynamicbox_destroy_buffer(dynamicbox_buffer_h handle)
772 {
773     struct dynamicbox_buffer_data *user_data;
774
775     if (!handle) {
776         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
777     }
778
779     user_data = dynamicbox_provider_buffer_user_data(handle);
780     if (user_data) {
781         if (user_data->frame_wait_timer) {
782             ecore_timer_del(user_data->frame_wait_timer);
783             user_data->frame_wait_timer = NULL;
784         }
785         free(user_data->content);
786         free(user_data->title);
787         free(user_data->icon);
788         free(user_data->name);
789         free(user_data);
790         dynamicbox_provider_buffer_set_user_data(handle, NULL);
791     }
792
793     DbgPrint("Destroy buffer\n");
794     return dynamicbox_provider_buffer_destroy(handle);
795 }
796
797 PUBLIC void *dynamicbox_ref_buffer(dynamicbox_buffer_h handle)
798 {
799     struct dynamicbox_buffer_data *user_data;
800     void *data;
801     int w, h, size;
802     int ret;
803
804     if (!handle) {
805         return NULL;
806     }
807
808     user_data = dynamicbox_provider_buffer_user_data(handle);
809     if (!user_data) {
810         return NULL;
811     }
812
813     if (user_data->accelerated) {
814         DbgPrint("H/W accelerated buffer is allocated\n");
815         return NULL;
816     }
817
818     ret = dynamicbox_provider_buffer_get_size(handle, &w, &h, &size);
819
820     data = dynamicbox_provider_buffer_ref(handle);
821     if (data && !ret && w > 0 && h > 0 && size > 0) {
822         memset(data, 0, w * h * size);
823         (void)dynamicbox_provider_buffer_sync(handle);
824     }
825
826     DbgPrint("Ref buffer %ds%d(%d)\n", w, h, size);
827     return data;
828 }
829
830 PUBLIC int dynamicbox_unref_buffer(void *buffer)
831 {
832     if (!buffer) {
833         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
834     }
835
836     DbgPrint("Unref buffer\n");
837     return dynamicbox_provider_buffer_unref(buffer);
838 }
839
840 PUBLIC int dynamicbox_sync_buffer(dynamicbox_buffer_h handle)
841 {
842     struct dynamicbox_buffer_data *user_data;
843     const char *pkgname;
844     const char *id;
845     int w;
846     int h;
847     int pixel_size;
848     int ret;
849
850     if (!handle) {
851         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
852     }
853
854     user_data = dynamicbox_provider_buffer_user_data(handle);
855     if (!user_data) {
856         ErrPrint("Invalid buffer\n");
857         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
858     }
859
860     if (user_data->accelerated) {
861         DbgPrint("H/W Buffer allocated. skip the sync buffer\n");
862         return DBOX_STATUS_ERROR_NONE;
863     }
864
865     pkgname = dynamicbox_provider_buffer_pkgname(handle);
866     if (!pkgname) {
867         ErrPrint("Invalid buffer handler\n");
868         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
869     }
870
871     id = dynamicbox_provider_buffer_id(handle);
872     if (!id) {
873         ErrPrint("Invalid buffer handler\n");
874         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
875     }
876
877     (void)dynamicbox_provider_buffer_sync(handle);
878
879     if (dynamicbox_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
880         ErrPrint("Failed to get size (%s)\n", id);
881     }
882
883     /**
884      * @todo
885      * manipulate the damaged region, so send update event only for the damaged region.
886      * to make more efficient updates
887      */
888     ret = send_updated(pkgname, id, handle, DBOX_PRIMARY_BUFFER, 0, 0, w, h, user_data->is_gbar, NULL);
889     if (ret < 0) {
890         ErrPrint("Failed to send%supdated (%s)\n", user_data->is_gbar ? " GBAR " : " ", id);
891     }
892
893     return ret;
894 }
895
896 PUBLIC int dynamicbox_send_updated_by_idx(dynamicbox_buffer_h handle, int idx)
897 {
898     struct dynamicbox_buffer_data *user_data;
899     const char *pkgname;
900     const char *id;
901     int w;
902     int h;
903     int pixel_size;
904     int ret;
905
906     user_data = dynamicbox_provider_buffer_user_data(handle);
907     if (!user_data) {
908         ErrPrint("Invalid buffer\n");
909         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
910     }
911
912     pkgname = dynamicbox_provider_buffer_pkgname(handle);
913     if (!pkgname) {
914         ErrPrint("Invalid buffer handler\n");
915         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
916     }
917
918     id = dynamicbox_provider_buffer_id(handle);
919     if (!id) {
920         ErrPrint("Invalid buffer handler\n");
921         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
922     }
923
924     if (dynamicbox_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
925         ErrPrint("Failed to get size (%s)\n", id);
926     }
927
928     ret = send_updated(pkgname, id, handle, idx, 0, 0, w, h, user_data->is_gbar, NULL);
929     if (ret < 0) {
930         ErrPrint("Failed to send%supdated (%s) %d\n", user_data->is_gbar ? " GBAR " : " ", id, idx);
931     }
932
933     return ret;
934 }
935
936 PUBLIC int dynamicbox_support_hw_buffer(dynamicbox_buffer_h handle)
937 {
938     if (!handle) {
939         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
940     }
941
942     return dynamicbox_provider_buffer_is_support_hw(handle);
943 }
944
945 PUBLIC int dynamicbox_create_hw_buffer(dynamicbox_buffer_h handle)
946 {
947     struct dynamicbox_buffer_data *user_data;
948     int ret;
949
950     if (!handle) {
951         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
952     }
953
954     user_data = dynamicbox_provider_buffer_user_data(handle);
955     if (!user_data) {
956         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
957     }
958
959     if (user_data->accelerated) {
960         return DBOX_STATUS_ERROR_ALREADY;
961     }
962
963     ret = dynamicbox_provider_buffer_create_hw(handle);
964     user_data->accelerated = (ret == 0);
965     return ret;
966 }
967
968 PUBLIC int dynamicbox_destroy_hw_buffer(dynamicbox_buffer_h handle)
969 {
970     struct dynamicbox_buffer_data *user_data;
971
972     if (!handle) {
973         LOGD("handle is NULL\n");
974         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
975     }
976
977     user_data = dynamicbox_provider_buffer_user_data(handle);
978     if (!user_data || !user_data->accelerated) {
979         LOGD("user_data is NULL\n");
980         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
981     }
982
983     user_data->accelerated = 0;
984
985     return dynamicbox_provider_buffer_destroy_hw(handle);
986 }
987
988 PUBLIC void *dynamicbox_buffer_hw_buffer(dynamicbox_buffer_h handle)
989 {
990     struct dynamicbox_buffer_data *user_data;
991
992     if (!handle) {
993         return NULL;
994     }
995
996     user_data = dynamicbox_provider_buffer_user_data(handle);
997     if (!user_data || !user_data->accelerated) {
998         return NULL;
999     }
1000
1001     return dynamicbox_provider_buffer_hw_addr(handle);
1002 }
1003
1004 PUBLIC int dynamicbox_buffer_pre_render(dynamicbox_buffer_h handle)
1005 {
1006     struct dynamicbox_buffer_data *user_data;
1007
1008     if (!handle) {
1009         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1010     }
1011
1012     user_data = dynamicbox_provider_buffer_user_data(handle);
1013     if (!user_data) {
1014         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1015     }
1016
1017     if (!user_data->accelerated) {
1018         return DBOX_STATUS_ERROR_NONE;
1019     }
1020
1021     /*!
1022      * \note
1023      * Do preprocessing for accessing the H/W render buffer
1024      */
1025     return dynamicbox_provider_buffer_pre_render(handle);
1026 }
1027
1028 static Eina_Bool frame_wait_cb(void *data)
1029 {
1030     dynamicbox_buffer_h handle = data;
1031     struct dynamicbox_buffer_data *user_data;
1032     const char *pkgname;
1033     const char *id;
1034     int pixel_size;
1035     int ret;
1036     int w;
1037     int h;
1038
1039     user_data = dynamicbox_provider_buffer_user_data(handle);
1040     if (!user_data) {
1041         ErrPrint("Failed to get a user data\n");
1042         return ECORE_CALLBACK_CANCEL;
1043     }
1044
1045     pkgname = dynamicbox_provider_buffer_pkgname(handle);
1046     id = dynamicbox_provider_buffer_id(handle);
1047
1048     if (!pkgname || !id) {
1049         ErrPrint("Failed to get instance information (%s), (%s)\n", pkgname, id);
1050         user_data->frame_wait_timer = NULL;
1051         return ECORE_CALLBACK_CANCEL;
1052     }
1053
1054     if (dynamicbox_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
1055         ErrPrint("Failed to get size (%s)\n", id);
1056         w = 0;
1057         h = 0;
1058         pixel_size = sizeof(int);
1059     }
1060
1061     DbgPrint("Frame skip waiting timer is fired (%s)\n", id);
1062
1063     /**
1064      * @todo
1065      * manipulate the damaged region, so send update event only for the damaged region.
1066      * to make more efficient updates
1067      */
1068     ret = send_updated(pkgname, id, handle, DBOX_PRIMARY_BUFFER, 0, 0, w, h, user_data->is_gbar, NULL);
1069     if (ret < 0) {
1070         ErrPrint("Failed to send%supdated (%s)\n", user_data->is_gbar ? " GBAR " : " ", id);
1071     }
1072
1073     (void)dynamicbox_provider_buffer_clear_frame_skip(handle);
1074
1075     user_data->frame_wait_timer = NULL;
1076     return ECORE_CALLBACK_CANCEL;
1077 }
1078
1079 PUBLIC int dynamicbox_buffer_post_render(dynamicbox_buffer_h handle)
1080 {
1081     int ret;
1082     const char *pkgname;
1083     const char *id;
1084     struct dynamicbox_buffer_data *user_data;
1085     int w;
1086     int h;
1087     int pixel_size;
1088     PERF_INIT();
1089     PERF_BEGIN();
1090
1091     if (!handle) {
1092         PERF_MARK("post_render");
1093         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1094     }
1095
1096     user_data = dynamicbox_provider_buffer_user_data(handle);
1097     if (!user_data) {
1098         PERF_MARK("post_render");
1099         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1100     }
1101
1102     if (!user_data->accelerated) {
1103         PERF_MARK("post_render");
1104         return DBOX_STATUS_ERROR_NONE;
1105     }
1106
1107     pkgname = dynamicbox_provider_buffer_pkgname(handle);
1108     if (!pkgname) {
1109         ErrPrint("Invalid buffer handle\n");
1110         PERF_MARK("post_render");
1111         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1112     }
1113
1114     id = dynamicbox_provider_buffer_id(handle);
1115     if (!id) {
1116         ErrPrint("Invalid buffer handler\n");
1117         PERF_MARK("post_render");
1118         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1119     }
1120
1121     ret = dynamicbox_provider_buffer_post_render(handle);
1122     if (ret < 0) {
1123         ErrPrint("Failed to post render processing\n");
1124         PERF_MARK("post_render");
1125         return ret;
1126     }
1127
1128     if (dynamicbox_provider_buffer_frame_skip(handle) == 0) {
1129         if (dynamicbox_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
1130             ErrPrint("Failed to get size (%s)\n", id);
1131         }
1132
1133         /**
1134          * @todo
1135          * manipulate the damaged region, so send update event only for the damaged region.
1136          * to make more efficient updates
1137          */
1138         ret = send_updated(pkgname, id, handle, DBOX_PRIMARY_BUFFER, 0, 0, w, h, user_data->is_gbar, NULL);
1139         if (ret < 0) {
1140             ErrPrint("Failed to send%supdated (%s)\n", user_data->is_gbar ? " GBAR " : " ", id);
1141         }
1142
1143         if (user_data->frame_wait_timer) {
1144             ecore_timer_del(user_data->frame_wait_timer);
1145             user_data->frame_wait_timer = NULL;
1146         }
1147     } else {
1148         if (user_data->frame_wait_timer) {
1149             ecore_timer_reset(user_data->frame_wait_timer);
1150         } else {
1151             user_data->frame_wait_timer = ecore_timer_add(FRAME_WAIT_INTERVAL, frame_wait_cb, handle);
1152             if (!user_data->frame_wait_timer) {
1153                 ErrPrint("Failed to add waiting timer for next frame\n");
1154             }
1155         }
1156     }
1157
1158     PERF_MARK("post_render");
1159     return ret;
1160 }
1161
1162 PUBLIC int dynamicbox_buffer_stride(dynamicbox_buffer_h handle)
1163 {
1164     if (!handle) {
1165         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1166     }
1167
1168     return dynamicbox_provider_buffer_stride(handle);
1169 }
1170
1171 PUBLIC int dynamicbox_content_is_updated(const char *filename, int is_gbar)
1172 {
1173     if (!s_info.trigger_update_monitor) {
1174         s_info.trigger_update_monitor = dlsym(RTLD_DEFAULT, FUNC_DYNAMICBOX_TRIGGER_UPDATE_MONITOR);
1175         if (!s_info.trigger_update_monitor) {
1176             ErrPrint("Trigger update monitor function is not exists\n");
1177             return DBOX_STATUS_ERROR_FAULT;
1178         }
1179     }
1180
1181     return s_info.trigger_update_monitor(filename, is_gbar);
1182 }
1183
1184 PUBLIC int dynamicbox_request_close_glance_bar(const char *pkgname, const char *id, int reason)
1185 {
1186     char *uri;
1187     int schema_len = strlen(FILE_SCHEMA);
1188     int ret;
1189
1190     if (!pkgname || !id) {
1191         ErrPrint("Invalid parameters (%s) (%s)\n", pkgname, id);
1192         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1193     }
1194
1195     if (strncmp(id, FILE_SCHEMA, schema_len)) {
1196         uri = id_to_uri(id);
1197         if (!uri) {
1198             ErrPrint("Heap: %s\n", strerror(errno));
1199             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1200         }
1201     } else {
1202         uri = strdup(id);
1203         if (!uri) {
1204             ErrPrint("Heap: %s\n", strerror(errno));
1205             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1206         }
1207     }
1208
1209     ret = dynamicbox_provider_send_request_close_gbar(pkgname, uri, reason);
1210     free(uri);
1211     return ret;
1212 }
1213
1214 PUBLIC int dynamicbox_freeze_scroller(const char *pkgname, const char *id)
1215 {
1216     char *uri;
1217     int ret;
1218
1219     uri = id_to_uri(id);
1220     if (!uri) {
1221         ErrPrint("Heap: %s\n", strerror(errno));
1222         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1223     }
1224
1225     ret = dynamicbox_provider_send_hold_scroll(pkgname, uri, 1);
1226     free(uri);
1227     return ret;
1228 }
1229
1230 PUBLIC int dynamicbox_thaw_scroller(const char *pkgname, const char *id)
1231 {
1232     char *uri;
1233     int ret;
1234
1235     uri = id_to_uri(id);
1236     if (!uri) {
1237         ErrPrint("Heap: %s\n", strerror(errno));
1238         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1239     }
1240
1241     ret = dynamicbox_provider_send_hold_scroll(pkgname, uri, 0);
1242     free(uri);
1243     return ret;
1244 }
1245
1246 PUBLIC int dynamicbox_set_extra_info(const char *id, const char *content, const char *title, const char *icon, const char *name)
1247 {
1248     dynamicbox_buffer_h handle;
1249     const char *pkgname;
1250     char *uri;
1251
1252     uri = id_to_uri(id);
1253     if (!uri) {
1254         ErrPrint("Heap: %s\n", strerror(errno));
1255         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1256     }
1257
1258     if (!s_info.find_pkgname) {
1259         s_info.find_pkgname = dlsym(RTLD_DEFAULT, FUNC_DYNAMICBOX_FIND_PKGNAME);
1260         if (!s_info.find_pkgname) {
1261             ErrPrint("Failed to find a \"dynamicbox_find_pkgname\"\n");
1262             free(uri);
1263             return DBOX_STATUS_ERROR_FAULT;
1264         }
1265     }
1266
1267     pkgname = s_info.find_pkgname(uri);
1268     if (!pkgname) {
1269         ErrPrint("Failed to find a package (%s)\n", uri);
1270         free(uri);
1271         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1272     }
1273
1274     handle = dynamicbox_provider_buffer_find_buffer(DBOX_TYPE_DBOX, pkgname, uri);
1275     if (handle) {
1276         struct dynamicbox_buffer_data *user_data;
1277
1278         user_data = dynamicbox_provider_buffer_user_data(handle);
1279         if (!user_data) {
1280             ErrPrint("User data is not available\n");
1281             free(uri);
1282             return DBOX_STATUS_ERROR_FAULT;
1283         }
1284
1285         if (content && strlen(content)) {
1286             char *_content;
1287
1288             _content = strdup(content);
1289             if (_content) {
1290                 if (user_data->content) {
1291                     free(user_data->content);
1292                 }
1293
1294                 user_data->content = _content;
1295             } else {
1296                 ErrPrint("Heap: %s\n", strerror(errno));
1297             }
1298         }
1299
1300         if (title && strlen(title)) {
1301             char *_title;
1302
1303             _title = strdup(title);
1304             if (_title) {
1305                 if (user_data->title) {
1306                     free(user_data->title);
1307                 }
1308
1309                 user_data->title = _title;
1310             } else {
1311                 ErrPrint("Heap: %s\n", strerror(errno));
1312             }
1313         }
1314
1315         if (icon && strlen(icon)) {
1316             char *_icon;
1317
1318             _icon = strdup(icon);
1319             if (_icon) {
1320                 if (user_data->icon) {
1321                     free(user_data->icon);
1322                 }
1323
1324                 user_data->icon = _icon;
1325             } else {
1326                 ErrPrint("Heap: %s\n", strerror(errno));
1327             }
1328         }
1329
1330         if (name && strlen(name)) {
1331             char *_name;
1332
1333             _name = strdup(name);
1334             if (_name) {
1335                 if (user_data->name) {
1336                     free(user_data->name);
1337                 }
1338
1339                 user_data->name = _name;
1340             } else {
1341                 ErrPrint("Heap: %s\n", strerror(errno));
1342             }
1343         }
1344
1345         if (dynamicbox_provider_send_extra_info(pkgname, uri, -1.0f, user_data->content, user_data->title, user_data->icon, user_data->name) < 0) {
1346             ErrPrint("Failed to send extra info (%s)\n", id);
1347         }
1348
1349         free(uri);
1350         return DBOX_STATUS_ERROR_NONE;
1351     }
1352     free(uri);
1353
1354     if (!s_info.update_extra_info) {
1355         s_info.update_extra_info = dlsym(RTLD_DEFAULT, FUNC_DYNAMICBOX_UPDATE_EXTRA_INFO);
1356         if (!s_info.update_extra_info) {
1357             ErrPrint("Failed to find a \"dynamicbox_update_extra_info\"\n");
1358             return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1359         }
1360     }
1361
1362     return s_info.update_extra_info(id, content, title, icon, name);
1363 }
1364
1365 /* End of a file */