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