Fix build warning based on GCC-9
[platform/core/appfw/widget-service.git] / src / widget_instance.c
1 /*
2  * Copyright 2015  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 "widget_instance.h"
18 #include <dlog.h>
19 #include "debug.h"
20 #include <uuid/uuid.h>
21 #include <unistd.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdbool.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <glib.h>
29 #include <aul.h>
30 #include <aul_svc.h>
31 #include <aul_app_com.h>
32 #include <aul_widget.h>
33 #include <aul_debug_info.h>
34 #include <widget_service.h>
35 #include <widget_service_internal.h>
36 #include <bundle_internal.h>
37 #include "widget_errno.h"
38
39 #define USER_UID_MIN 5000
40 #define MAX_INSTANCE_ID_LEN 256
41 #define WIDGET_CLASS_DELIMITER "@"
42 #define QUERY_MAX_LEN 8192
43
44 #define DLP_K_DEBUG_ARG "__DLP_DEBUG_ARG__"
45 #define DLP_K_GDBSERVER_PATH "__DLP_GDBSERVER_PATH__"
46 #define DLP_K_VALGRIND_ARG "__DLP_VALGRIND_ARG__"
47 #define DLP_K_VALGRIND_PATH "__DLP_VALGRIND_PATH__"
48 #define SDK_DEBUG "DEBUG"
49 #define SDK_VALGRIND "VALGRIND"
50
51 #ifndef TIZEN_PATH_MAX
52 #define TIZEN_PATH_MAX 1024
53 #endif
54
55 enum {
56         WIDGET_INSTANCE_CREATED,
57         WIDGET_INSTANCE_RUNNING,
58         WIDGET_INSTANCE_TERMINATED,
59         WIDGET_INSTANCE_DELETED
60 };
61
62 struct _widget_instance {
63         char *id;
64         pid_t pid;
65         char *widget_id;
66         int w;
67         int h;
68         double period;
69         char *content_info;
70         int status;
71         int stored;
72         int ref;
73         int err;
74 };
75
76 struct widget_app {
77         char *viewer_id;
78         char *widget_id;
79         GList *instances;
80 };
81
82 struct _sdk_util {
83         bool initialized;
84         bundle *b;
85 };
86
87 static GList *_widget_instances = NULL;
88 static GList *_widget_apps = NULL;
89
90 static char *viewer_appid = NULL;
91 static aul_app_com_connection_h conn_viewer;
92 static aul_app_com_connection_h conn_status;
93
94 static GHashTable *lifecycle_tbl;
95 static int is_status_handler_connected;
96
97 static struct _sdk_util sdk_util;
98
99 static char *package_id;
100
101 struct lifecycle_local_s {
102         char *widget_id;
103         widget_instance_event_cb cb;
104         void *data;
105 };
106
107 static GList *event_cbs;
108 struct event_cb_s {
109         widget_instance_event_cb cb;
110         void *data;
111 };
112
113 static int __fault_handler(int pid);
114
115 extern int widget_service_get_update_period(const char *widget_id, double *period);
116
117 static struct _widget_instance *__pick_instance(const char *instance_id)
118 {
119         GList *instances = _widget_instances;
120         struct _widget_instance *instance = NULL;
121
122         while (instances) {
123                 instance = (struct _widget_instance *)instances->data;
124                 if (instance && g_strcmp0(instance_id, instance->id) == 0)
125                         return instance;
126
127                 instances = instances->next;
128         }
129
130         return NULL;
131 }
132
133 static struct widget_app *__pick_app(const char *widget_id)
134 {
135         GList *apps = _widget_apps;
136         struct widget_app *app = NULL;
137
138         while (apps) {
139                 app = apps->data;
140                 if (app && app->widget_id && g_strcmp0(widget_id, app->widget_id) == 0)
141                         return app;
142
143                 apps = apps->next;
144         }
145
146         return NULL;
147 }
148
149 static struct widget_app *__add_app(const char *widget_id, const char *viewer_id)
150 {
151         struct widget_app *app = NULL;
152
153         app = (struct widget_app *)malloc(sizeof(struct widget_app));
154         if (app == NULL) {
155                 _E("out of memory");
156                 return NULL;
157         }
158
159         app->viewer_id = strdup(viewer_id);
160         app->widget_id = strdup(widget_id);
161         app->instances = NULL;
162
163         _widget_apps = g_list_append(_widget_apps, app);
164
165         return app;
166 }
167
168 static char *__create_instance_id(const char *widget_id)
169 {
170         char uuid[37];
171         char instance_id[MAX_INSTANCE_ID_LEN];
172         uuid_t u;
173         struct widget_app *app = NULL;
174
175         if (widget_id == NULL)
176                 return NULL;
177
178         app = __pick_app(widget_id);
179
180         if (app == NULL) {
181                 app = __add_app(widget_id, viewer_appid);
182                 if (app == NULL)
183                         return NULL;
184         }
185
186         uuid_generate(u);
187         uuid_unparse(u, uuid);
188
189         snprintf(instance_id, MAX_INSTANCE_ID_LEN, "%s:%s", uuid, widget_id);
190
191         _D("new instance: %s", instance_id);
192
193         return strdup(instance_id);
194 }
195
196 static struct _widget_instance *__add_instance(const char *id, const char *widget_id)
197 {
198         struct _widget_instance *instance = NULL;
199         struct widget_app *app = NULL;
200         double period = 0;
201
202         if (widget_service_get_update_period(widget_id, &period) != WIDGET_ERROR_NONE) {
203                 _E("Can't get update-period");
204                 return NULL;
205         }
206
207         instance = (struct _widget_instance *)malloc(sizeof(struct _widget_instance));
208         if (instance == NULL) {
209                 _E("out of memory");
210                 return NULL;
211         }
212
213         instance->status = WIDGET_INSTANCE_CREATED;
214         instance->id = strdup(id);
215         instance->pid = 0;
216         instance->stored = 0;
217         instance->widget_id = strdup(widget_id);
218         instance->content_info = NULL;
219         instance->ref = 0;
220         instance->period = period;
221         instance->err = 0;
222
223         _widget_instances = g_list_append(_widget_instances, instance);
224
225         app = __pick_app(widget_id);
226         if (!app)
227                 app = __add_app(widget_id, viewer_appid);
228
229         if (app)
230                 app->instances = g_list_append(app->instances, instance);
231         else
232                 _E("failed to find app: %s", widget_id);
233
234         return instance;
235 }
236
237 static void __remove_instance(struct _widget_instance *instance)
238 {
239         struct widget_app *app = NULL;
240
241         if (instance == NULL) {
242                 _E("invalid argument");
243                 return;
244         }
245
246         if (instance->widget_id)
247                 app = __pick_app(instance->widget_id);
248
249         if (app) {
250                 app->instances = g_list_remove(app->instances, instance);
251                 if (app->instances == NULL) {
252                         _widget_apps = g_list_remove(_widget_apps, app);
253                         if (app->widget_id)
254                                 free(app->widget_id);
255                         if (app->viewer_id)
256                                 free(app->viewer_id);
257                         free(app);
258                 }
259         }
260
261         _widget_instances = g_list_remove(_widget_instances, instance);
262
263         if (instance->widget_id) {
264                 free(instance->widget_id);
265                 instance->widget_id = NULL;
266         }
267
268         if (instance->id) {
269                 free(instance->id);
270                 instance->id = NULL;
271         }
272
273         if (instance->content_info) {
274                 free(instance->content_info);
275                 instance->content_info = NULL;
276         }
277
278         free(instance);
279 }
280
281 EAPI int widget_instance_create(const char *widget_id, char **instance_id)
282 {
283         char *id = NULL;
284         struct _widget_instance *instance = NULL;
285
286         _D("create: %s", widget_id);
287
288         id = __create_instance_id(widget_id);
289         if (!id) {
290                 _E("failed to get instance id for %s", widget_id);
291                 return -1;
292         }
293
294         instance = __add_instance(id, widget_id);
295
296         free((gpointer)id);
297
298         if (instance) {
299                 *instance_id = instance->id;
300                 _D("create done");
301                 return 0;
302         }
303
304         *instance_id = NULL;
305
306         return -1;
307 }
308
309 static int __convert_aul_error(int res)
310 {
311         int ret;
312
313         switch (res) {
314         case AUL_R_EREJECTED:
315         case AUL_R_ENOAPP:
316                 ret = WIDGET_ERROR_NOT_EXIST;
317                 break;
318         case AUL_R_EILLACC:
319                 ret = WIDGET_ERROR_PERMISSION_DENIED;
320                 break;
321         case AUL_R_ETIMEOUT:
322                 ret = WIDGET_ERROR_TIMED_OUT;
323                 break;
324         case AUL_R_ECANCELED:
325                 ret = WIDGET_ERROR_CANCELED;
326                 break;
327         case AUL_R_EINVAL:
328                 ret = WIDGET_ERROR_INVALID_PARAMETER;
329                 break;
330         default:
331                 ret = WIDGET_ERROR_FAULT;
332                 break;
333         }
334
335         return ret;
336 }
337
338 static int __launch(const char *widget_id, const char *instance_id, bundle *extra)
339 {
340         int ret = 0;
341         const char *appid;
342         const char *classid = widget_id;
343         bundle *b = extra;
344
345         appid = g_strstr_len(widget_id, strlen(widget_id), WIDGET_CLASS_DELIMITER) + 1;
346         if (appid != (const char *)1) { /* move pointer next to delimiter */
347                 if (appid > widget_id + (sizeof(char) * strlen(widget_id)))
348                         return -1; /* bad ptr */
349         } else {
350                 appid = widget_id;
351         }
352
353         if (b == NULL)
354                 b = bundle_create();
355
356         if (instance_id)
357                 bundle_add_str(b, AUL_K_WIDGET_INSTANCE_ID, instance_id);
358
359         bundle_add_str(b, WIDGET_K_CLASS, classid);
360         bundle_add_str(b, AUL_K_WIDGET_VIEWER, viewer_appid);
361
362         aul_svc_set_operation(b, AUL_SVC_OPERATION_LAUNCH_WIDGET);
363
364         ret = aul_launch_app_async(appid, b);
365         if (ret < 0)
366                 ret = __convert_aul_error(ret);
367
368         if (!extra) {
369                 bundle_free(b);
370                 b = NULL;
371         }
372
373         return ret;
374 }
375
376 static int __send_aul_cmd(widget_instance_h instance, const char *command, bundle *extra)
377 {
378         int ret = 0;
379         bundle *b = extra;
380
381         if (!instance || !command) {
382                 _E("inavlid parameter");
383                 return -1;
384         }
385
386         if (b == NULL) {
387                 b = bundle_create();
388                 if (!b) {
389                         _E("out of memory");
390                         return -1;
391                 }
392         }
393
394         bundle_del(b, WIDGET_K_OPERATION);
395         bundle_add_str(b, WIDGET_K_OPERATION, command);
396
397         ret = __launch(instance->widget_id, instance->id, b);
398
399         if (!extra) {
400                 bundle_free(b);
401                 b = NULL;
402         }
403
404         if (ret < 0) {
405                 _E("failed to launch %s (%s:%d)", instance->id, command, ret);
406                 instance->pid = -1;
407         } else if (ret != instance->pid) {
408                 _E("pid has been changed. new process detected. %s (%d to %d)",
409                         instance->id, instance->pid, ret);
410                 instance->pid = ret;
411         }
412
413         return ret;
414 }
415
416 static int __set_width(bundle *content_info, int w)
417 {
418         char wbuf[11];
419         if (content_info == NULL || w < 0)
420                 return -1;
421
422         snprintf(wbuf, 11, "%d", w);
423         bundle_add_str(content_info, WIDGET_K_WIDTH, wbuf);
424
425         return 0;
426 }
427
428 static int __set_height(bundle *content_info, int h)
429 {
430         char hbuf[11];
431         if (content_info == NULL || h < 0)
432                 return -1;
433
434         snprintf(hbuf, 11, "%d", h);
435         bundle_add_str(content_info, WIDGET_K_HEIGHT, hbuf);
436
437         return 0;
438 }
439
440 EAPI int widget_instance_launch(const char *instance_id, char *content_info, int w, int h)
441 {
442         int ret = 0;
443         char pid_buf[11];
444         bundle *b;
445         widget_instance_h instance;
446
447         _D("launch: %s", instance_id);
448
449         if (instance_id == NULL) {
450                 _E("wrong arguments");
451                 return -1;
452         }
453
454         instance = __pick_instance(instance_id);
455
456         if (instance == NULL) {
457                 _E("unknown instance: %s", instance_id);
458                 return -1;
459         }
460
461         if (sdk_util.b) {
462                 b = sdk_util.b;
463                 sdk_util.b = NULL;
464         } else {
465                 b = bundle_create();
466                 if (b == NULL) {
467                         _E("out of memory");
468                         return -1;
469                 }
470         }
471
472         snprintf(pid_buf, sizeof(pid_buf), "%d", getpid());
473         bundle_add_str(b, WIDGET_K_CALLER, pid_buf);
474         bundle_add_str(b, WIDGET_K_OPERATION, "create");
475         bundle_add_byte(b, WIDGET_K_PERIOD, &(instance->period), sizeof(double));
476
477         if (content_info) {
478                 bundle_add_str(b, WIDGET_K_CONTENT_INFO, content_info);
479                 instance->content_info = strdup(content_info);
480         }
481
482         __set_width(b, w);
483         __set_height(b, h);
484
485         ret = __launch(instance->widget_id, instance_id, b);
486         aul_widget_write_log(LOG_TAG, "[%s:%d]  %s, launched : %d",
487                         __FUNCTION__, __LINE__, instance_id, ret);
488
489         if (ret > 0)
490                 instance->pid = ret;
491
492         bundle_free(b);
493
494         return ret;
495 }
496
497 EAPI int widget_instance_terminate(const char *instance_id)
498 {
499         int ret = 0;
500         struct _widget_instance *instance;
501
502         if (instance_id == NULL)
503                 return -1;
504
505         instance = __pick_instance(instance_id);
506         if (!instance) {
507                 _E("illegal operation: termiante (instance not yet initialized: %s)", instance_id);
508                 return -1;
509         }
510
511         ret = __send_aul_cmd(instance, "terminate", NULL);
512
513         return ret;
514 }
515
516 EAPI int widget_instance_destroy(const char *instance_id)
517 {
518         int ret = 0;
519         struct _widget_instance *instance;
520
521         if (instance_id == NULL)
522                 return -1;
523
524         instance = __pick_instance(instance_id);
525         if (!instance) {
526                 _E("illegal operation: destroy (instance not yet initialized: %s)", instance_id);
527                 return -1;
528         }
529
530         if (instance->pid > 0) {
531                 ret = __send_aul_cmd(instance, "destroy", NULL);
532         } else { /* uninitialized */
533                 __remove_instance(instance);
534         }
535
536         return ret;
537 }
538
539 EAPI int widget_instance_resume(const char *instance_id)
540 {
541         int ret = 0;
542         struct _widget_instance *instance;
543
544         if (instance_id == NULL)
545                 return -1;
546
547         instance = __pick_instance(instance_id);
548         if (!instance) {
549                 _E("illegal operation: resume (instance not yet initialized: %s)", instance_id);
550                 return -1;
551         }
552
553         ret = __send_aul_cmd(instance, "resume", NULL);
554
555         return ret;
556 }
557
558 EAPI int widget_instance_pause(const char *instance_id)
559 {
560         int ret = 0;
561         struct _widget_instance *instance;
562
563         if (instance_id == NULL)
564                 return -1;
565
566         instance = __pick_instance(instance_id);
567         if (!instance) {
568                 _E("illegal operation: pause (instance not yet initialized: %s)", instance_id);
569                 return -1;
570         }
571
572         ret = __send_aul_cmd(instance, "pause", NULL);
573
574         return ret;
575 }
576
577 EAPI int widget_instance_resize(const char *instance_id, int w, int h)
578 {
579         int ret = 0;
580         bundle *b;
581         struct _widget_instance *instance;
582
583         if (instance_id == NULL)
584                 return -1;
585
586         instance = __pick_instance(instance_id);
587         if (!instance) {
588                 _E("illegal operation: resize (instance not yet initialized: %s)", instance_id);
589                 return -1;
590         }
591
592         b = bundle_create();
593         if (b == NULL)
594                 return -1;
595
596         __set_width(b, w);
597         __set_height(b, h);
598
599         ret = __send_aul_cmd(instance, "resize", b);
600
601         bundle_free(b);
602
603         return ret;
604 }
605
606 EAPI int widget_instance_foreach(const char *widget_id, widget_instance_foreach_cb cb, void *data)
607 {
608         GList *apps = _widget_apps;
609         GList *instances = NULL;
610         struct widget_app *app = NULL;
611         struct _widget_instance *instance = NULL;
612
613         if (widget_id == NULL || cb == NULL)
614                 return -1;
615
616         while (apps) {
617                 app = apps->data;
618                 if (app && g_strcmp0(app->widget_id, widget_id) == 0) {
619                         instances = app->instances;
620                         while (instances) {
621                                 instance = instances->data;
622                                 if (instance && cb(instance, data) < 0)
623                                         break;
624
625                                 instances = instances->next;
626                         }
627                 }
628                 apps = apps->next;
629         }
630
631         return 0;
632 }
633
634 static void __notify_event(int event, const char *widget_id, const char *instance_id)
635 {
636         struct event_cb_s *cb_info;
637         GList *iter = event_cbs;
638
639         while (iter) {
640                 cb_info = (struct event_cb_s *)iter->data;
641                 if (cb_info && cb_info->cb)
642                         cb_info->cb(widget_id, instance_id, event, cb_info->data);
643
644                 iter = iter->next;
645         }
646 }
647
648 static int __check_valid_sender(char *widget_id, int pid)
649 {
650         struct widget_app *app = NULL;
651         widget_instance_h instance;
652         GList *head = NULL;
653
654         app = __pick_app(widget_id);
655         if (app) {
656                 head = app->instances;
657                 if (head) {
658                         instance = (widget_instance_h)head->data;
659                         if (instance->pid == -1 || instance->pid == pid)
660                                 return 0;
661                         _E("instance->pid (%d), pid (%d)", instance->pid, pid);
662                 }
663         }
664         return -1;
665 }
666
667 /* LCOV_EXCL_START */
668 static int __check_valid_sender_v2(const char *sender_pkgid)
669 {
670         char pkgid[256] = {0, };
671         int ret;
672
673         if (sender_pkgid == NULL)
674                 return -1;
675
676         if (package_id == NULL) {
677                 ret = aul_app_get_pkgid_bypid(getpid(), pkgid, sizeof(pkgid));
678                 if (ret != AUL_R_OK) {
679                         _E("Failed to get pkgid");
680                         return -1;
681                 }
682
683                 package_id = strdup(pkgid);
684                 if (package_id == NULL) {
685                         _E("out of memory");
686                         return -1;
687                 }
688         }
689
690         _D("sender_pkgid: %s, pkgid: %s", sender_pkgid, package_id);
691         if (strcmp(package_id, sender_pkgid) == 0)
692                 return 0;
693
694         return -1;
695 }
696 /* LCOV_EXCL_STOP */
697
698 static int __status_handler(const char *endpoint, aul_app_com_result_e e, bundle *envelope, void *user_data)
699 {
700         char *widget_id = NULL;
701         char *instance_id = NULL;
702         char *sender_pkgid = NULL;
703         char *is_faulted = NULL;
704         int *status;
705         size_t status_sz = 0;
706         struct lifecycle_local_s *cb_info;
707         char *sender_pid_str;
708         int sender_pid;
709
710         bundle_get_str(envelope, AUL_K_WIDGET_ID, &widget_id);
711         bundle_get_str(envelope, AUL_K_WIDGET_INSTANCE_ID, &instance_id);
712         bundle_get_byte(envelope, AUL_K_WIDGET_STATUS, (void **)&status, &status_sz);
713         bundle_get_str(envelope, AUL_K_COM_SENDER_PID, &sender_pid_str);
714         bundle_get_str(envelope, AUL_K_PKGID, &sender_pkgid);
715         bundle_get_str(envelope, AUL_K_IS_FAULT, &is_faulted);
716
717         if (widget_id == NULL || status == NULL) {
718                 _E("undefined class or instance %s of %s", instance_id, widget_id);
719                 if (status != NULL)
720                         _E("status: %d", *status);
721
722                 return 0;
723         }
724
725         sender_pid = atoi(sender_pid_str);
726         if (__check_valid_sender(widget_id, sender_pid) == -1) {
727                 bundle_get_str(envelope, AUL_K_PKGID, &sender_pkgid);
728                 LOGW("It's not my widget(%s), let's check package", widget_id);
729                 if (__check_valid_sender_v2(sender_pkgid) < 0) {
730                         LOGW("My package do not have widget_id %s", widget_id);
731                         return 0;
732                 }
733         }
734
735         if (*status == AUL_WIDGET_LIFE_CYCLE_EVENT_APP_DEAD &&
736                         is_faulted && !strcmp(is_faulted, "true")) {
737                 LOGW("handle dead widget instances, %s", instance_id);
738                 aul_widget_write_log(LOG_TAG, "[%s:%d] %s sender(%d)",
739                         __FUNCTION__, __LINE__, instance_id, sender_pid);
740                 __fault_handler(sender_pid);
741         }
742
743         cb_info = (struct lifecycle_local_s *)g_hash_table_lookup(lifecycle_tbl, "NULL");
744         if (cb_info)
745                 cb_info->cb(widget_id, instance_id, *status, cb_info->data);
746
747         cb_info = (struct lifecycle_local_s *)g_hash_table_lookup(lifecycle_tbl, widget_id);
748         if (cb_info)
749                 cb_info->cb(widget_id, instance_id, *status, cb_info->data);
750
751         return 0;
752 }
753
754 static int __connect_status_handler()
755 {
756         if (is_status_handler_connected)
757                 return 0;
758
759         if (aul_app_com_create("widget.status", NULL, __status_handler, NULL, &conn_status) < 0) {
760                 _E("failed to create status");
761                 return -1;
762         }
763
764         is_status_handler_connected = 1;
765
766         return 0;
767 }
768
769 static int __widget_instance_handler(int status, char *widget_id,
770                 char *instance_id, char *content_info, int err)
771 {
772
773         struct _widget_instance *instance;
774
775         if (instance_id == NULL) {
776                 _E("undefined class or instance of %s", widget_id);
777                 return 0;
778         }
779
780         _D("update status %s on %d", instance_id, status);
781
782         instance = __pick_instance(instance_id);
783
784         if (instance == NULL) {
785                 _E("undefined instance id: %s of %s", instance_id, widget_id);
786                 return 0;
787         }
788
789         switch (status) {
790         case WIDGET_INSTANCE_EVENT_CREATE:
791                 instance->status = WIDGET_INSTANCE_RUNNING;
792                 break;
793         case WIDGET_INSTANCE_EVENT_TERMINATE:
794                 instance->status = WIDGET_INSTANCE_TERMINATED;
795                 break;
796         case WIDGET_INSTANCE_EVENT_DESTROY:
797                 instance->status = WIDGET_INSTANCE_DELETED;
798                 break;
799         case WIDGET_INSTANCE_EVENT_PAUSE:
800                 break;
801         case WIDGET_INSTANCE_EVENT_RESUME:
802                 break;
803         case WIDGET_INSTANCE_EVENT_UPDATE:
804                 break;
805         case WIDGET_INSTANCE_EVENT_EXTRA_UPDATED:
806                 if (content_info) {
807                         if (instance->content_info)
808                                 free(instance->content_info);
809
810                         instance->content_info = strdup(content_info);
811                 }
812                 break;
813         case WIDGET_INSTANCE_EVENT_FAULT:
814                 break;
815         case WIDGET_INSTANCE_EVENT_CREATE_ABORTED:
816                 instance->pid = -1;
817                 instance->err = err;
818                 break;
819         default:
820                 _E("unknown status: %d", status);
821                 break;
822         }
823
824         __notify_event(status, widget_id, instance_id);
825
826         if (instance->status == WIDGET_INSTANCE_DELETED)
827                 widget_instance_unref(instance);
828
829         return 0;
830 }
831
832 static int __widget_handler(const char *viewer_id, aul_app_com_result_e e, bundle *envelope, void *user_data)
833 {
834         char *widget_id = NULL;
835         char *instance_id = NULL;
836         char *error_code = NULL;
837         int *status = NULL;
838         size_t status_sz = 0;
839         char *content_info = NULL;
840         char *sender_pid_str = NULL;
841         int sender_pid;
842         int ret;
843         int err = 0;
844
845         bundle_get_str(envelope, AUL_K_WIDGET_ID, &widget_id);
846         bundle_get_byte(envelope, AUL_K_WIDGET_STATUS, (void **)&status, &status_sz);
847
848         if (widget_id == NULL) {
849                 LOGE("undefined widget_id");
850                 return 0;
851         }
852
853         if (*status == WIDGET_INSTANCE_EVENT_APP_RESTART_REQUEST) {
854                 LOGW("WIDGET_INSTANCE_EVENT_APP_RESTART_REQUEST notify");
855                 bundle_get_str(envelope, AUL_K_COM_SENDER_PID, &sender_pid_str);
856                 if (sender_pid_str == NULL) {
857                         LOGE("Failed to get sender pid of %s", widget_id);
858                         return 0;
859                 }
860                 sender_pid = atoi(sender_pid_str);
861                 ret = __check_valid_sender(widget_id, sender_pid);
862                 if (ret == 0)
863                         __notify_event(*status, widget_id, "");
864         } else {
865                 bundle_get_str(envelope, AUL_K_WIDGET_INSTANCE_ID, &instance_id);
866                 bundle_get_str(envelope, WIDGET_K_CONTENT_INFO, &content_info);
867                 bundle_get_str(envelope, AUL_K_WIDGET_ERROR_CODE, &error_code);
868                 if (error_code)
869                         err = atoi(error_code);
870
871                 __widget_instance_handler(*status, widget_id, instance_id,
872                                 content_info, err);
873         }
874
875         return 0;
876 }
877
878 /* LCOV_EXCL_START */
879 static int __fault_handler(int pid)
880 {
881         GList *iter;
882         struct _widget_instance *instance;
883
884         iter = _widget_instances;
885
886         while (iter) {
887                 instance = (struct _widget_instance *)iter->data;
888                 if (instance && instance->pid == pid) {
889                         instance->pid = -1;
890                         instance->status = WIDGET_INSTANCE_TERMINATED;
891                         __notify_event(WIDGET_INSTANCE_EVENT_FAULT, instance->widget_id, instance->id);
892                 }
893                 iter = iter->next;
894         }
895
896         return 0;
897 }
898 /* LCOV_EXCL_STOP */
899
900 EAPI int widget_instance_init(const char *viewer_id)
901 {
902         if (viewer_id == NULL)
903                 return -1;
904
905         viewer_appid = strdup(viewer_id);
906
907         __connect_status_handler();
908
909         _D("widget_instance_init %s", viewer_id);
910         if (aul_app_com_create(viewer_id, NULL, __widget_handler, NULL, &conn_viewer) < 0) {
911                 _E("failed to create app com endpoint");
912                 return -1;
913         }
914
915         return 0;
916 }
917
918 EAPI int widget_instance_fini()
919 {
920         if (sdk_util.initialized) {
921                 aul_debug_info_fini();
922                 sdk_util.initialized = false;
923         }
924
925         if (sdk_util.b) {
926                 bundle_free(sdk_util.b);
927                 sdk_util.b = NULL;
928         }
929
930         if (lifecycle_tbl) {
931                 g_hash_table_destroy(lifecycle_tbl);
932                 lifecycle_tbl = NULL;
933         }
934
935         if (conn_viewer) {
936                 if (aul_app_com_leave(conn_viewer) < 0)
937                         _E("failed to leave app com endpoint viewer");
938                 conn_viewer = NULL;
939         }
940
941         if (conn_status) {
942                 if (aul_app_com_leave(conn_status) < 0)
943                         _E("failed to leave app com endpoint status");
944                 conn_status = NULL;
945         }
946
947         if (viewer_appid) {
948                 free(viewer_appid);
949                 viewer_appid = NULL;
950         }
951
952         if (package_id) {
953                 free(package_id);
954                 package_id = NULL;
955         }
956
957         return 0;
958 }
959
960 EAPI int widget_instance_get_error_code(widget_instance_h instance, int *err)
961 {
962         if (instance == NULL || err == NULL)
963                 return -1;
964
965         *err = instance->err;
966
967         return 0;
968 }
969
970 EAPI int widget_instance_get_id(widget_instance_h instance, char **id)
971 {
972         if (instance == NULL || id == NULL)
973                 return -1;
974
975         *id = (char *)instance->id;
976         return 0;
977 }
978
979 EAPI int widget_instance_get_content(widget_instance_h instance, char **content)
980 {
981         if (instance == NULL || content == NULL)
982                 return -1;
983
984         *content = instance->content_info;
985         return 0;
986 }
987
988 EAPI int widget_instance_get_width(widget_instance_h instance, int *w)
989 {
990         if (instance == NULL || w == NULL)
991                 return -1;
992
993         *w = instance->w;
994         return 0;
995 }
996
997 EAPI int widget_instance_get_height(widget_instance_h instance, int *h)
998 {
999         if (instance == NULL || h == NULL)
1000                 return -1;
1001
1002         *h = instance->h;
1003         return 0;
1004 }
1005
1006 EAPI int widget_instance_get_period(widget_instance_h instance, double *period)
1007 {
1008         if (instance == NULL || period == NULL)
1009                 return -1;
1010
1011         *period = instance->period;
1012         return 0;
1013 }
1014
1015 EAPI int widget_instance_change_period(const char *widget_id, const char *instance_id, double period)
1016 {
1017         int ret;
1018         bundle *b;
1019
1020         b = bundle_create();
1021         if (!b) {
1022                 _E("out of memory"); /* LCOV_EXCL_LINE */
1023                 return -1; /* LCOV_EXCL_LINE */
1024         }
1025
1026         bundle_add_byte(b, WIDGET_K_PERIOD, &period, sizeof(double));
1027         bundle_add_str(b, WIDGET_K_OPERATION, "period");
1028         ret = aul_widget_instance_update(widget_id, instance_id, b);
1029         bundle_free(b);
1030
1031         return ret;
1032 }
1033
1034 EAPI int widget_instance_trigger_update(widget_instance_h instance, const char *content_info, int force)
1035 {
1036         if (!instance)
1037                 return -1;
1038
1039         return widget_instance_trigger_update_v2(instance->widget_id, instance->id, content_info, force);
1040 }
1041
1042 EAPI int widget_instance_trigger_update_v2(const char *widget_id,
1043                 const char *instance_id, const char *content_info, int force)
1044 {
1045         int ret;
1046
1047         bundle *kb;
1048
1049         kb = bundle_create();
1050         if (!kb) {
1051                 _E("out of memory"); /* LCOV_EXCL_LINE */
1052                 return -1; /* LCOV_EXCL_LINE */
1053         }
1054
1055         bundle_add_str(kb, WIDGET_K_OPERATION, "update");
1056
1057         if (force)
1058                 bundle_add_str(kb, WIDGET_K_FORCE, "true");
1059
1060         if (content_info)
1061                 bundle_add_str(kb, WIDGET_K_CONTENT_INFO, content_info);
1062
1063         ret = aul_widget_instance_update(widget_id, instance_id, kb);
1064
1065         bundle_free(kb);
1066
1067         if (ret >= 0)
1068                 return WIDGET_ERROR_NONE;
1069
1070         switch (ret) {
1071         case AUL_R_ENOAPP:
1072                 ret = WIDGET_ERROR_NOT_EXIST;
1073                 break;
1074         case AUL_R_EILLACC:
1075                 ret = WIDGET_ERROR_PERMISSION_DENIED;
1076                 break;
1077         case AUL_R_EINVAL:
1078                 ret = WIDGET_ERROR_INVALID_PARAMETER;
1079                 break;
1080         case AUL_R_ECANCELED:
1081                 ret = WIDGET_ERROR_CANCELED;
1082                 break;
1083         default:
1084                 ret = WIDGET_ERROR_FAULT;
1085         }
1086
1087         return ret;
1088 }
1089
1090 EAPI widget_instance_h widget_instance_get_instance(const char *widget_id, const char *instance_id)
1091 {
1092         widget_instance_h instance;
1093
1094         if (widget_id == NULL || instance_id == NULL)
1095                 return NULL;
1096
1097         if (_widget_apps && _widget_instances) {
1098                 instance = __pick_instance(instance_id);
1099                 return widget_instance_ref(instance);
1100         }
1101
1102         return NULL;
1103 }
1104
1105 EAPI int widget_instance_get_instance_list(const char *widget_id, widget_instance_list_cb cb, void *data)
1106 {
1107         widget_instance_h instance;
1108         struct widget_app *app;
1109         GList *head = NULL;
1110
1111         if (widget_id == NULL)
1112                 return -1;
1113
1114         if (_widget_apps)
1115                 app = __pick_app(widget_id);
1116         else
1117                 return -2;
1118
1119         if (app) {
1120                 head = app->instances;
1121
1122                 while (head) {
1123                         instance = (widget_instance_h)head->data;
1124                         if (cb(instance->widget_id, instance->id, data) != 0)
1125                                 break;
1126
1127                         head = head->next;
1128                 }
1129         }
1130
1131         return 0;
1132 }
1133
1134 EAPI void widget_instance_unref(widget_instance_h instance)
1135 {
1136         if (instance == NULL)
1137                 return;
1138
1139         instance->ref--;
1140
1141         if (instance->ref > -1)
1142                 return;
1143
1144         __remove_instance(instance);
1145 }
1146
1147 EAPI widget_instance_h widget_instance_ref(widget_instance_h instance)
1148 {
1149         if (instance)
1150                 instance->ref++;
1151
1152         return instance;
1153 }
1154
1155 EAPI int widget_instance_listen_event(widget_instance_event_cb cb, void *data)
1156 {
1157         struct event_cb_s *cb_info;
1158
1159         cb_info = (struct event_cb_s *)malloc(sizeof(struct event_cb_s));
1160         if (!cb_info) {
1161                 _E("out of memory"); /* LCOV_EXCL_LINE */
1162                 return -1; /* LCOV_EXCL_LINE */
1163         }
1164
1165         cb_info->cb = cb;
1166         cb_info->data = data;
1167
1168         event_cbs = g_list_append(event_cbs, cb_info);
1169         if (!event_cbs) {
1170                 _E("out of memory"); /* LCOV_EXCL_LINE */
1171                 return -1; /* LCOV_EXCL_LINE */
1172         }
1173
1174         return 0;
1175 }
1176
1177 EAPI int widget_instance_unlisten_event(widget_instance_event_cb cb)
1178 {
1179         struct event_cb_s *cb_info;
1180         GList *iter = event_cbs;
1181
1182         if (!cb) {
1183                 _E("invalid parameter");
1184                 return -1;
1185         }
1186
1187         while (iter) {
1188                 cb_info = (struct event_cb_s *)iter->data;
1189                 if (cb_info && cb_info->cb == cb) {
1190                         event_cbs = g_list_remove_link(event_cbs, iter);
1191                         free(cb_info);
1192                         g_list_free(iter);
1193                         return 0;
1194                 }
1195                 iter = iter->next;
1196         }
1197
1198         _E("wrong argument");
1199         return -1;
1200 }
1201
1202 static void __destroy_lifecycle_local(gpointer data)
1203 {
1204         struct lifecycle_local_s *cb_info = (struct lifecycle_local_s *)data;
1205
1206         if (cb_info == NULL)
1207                 return;
1208
1209         if (cb_info->widget_id)
1210                 free(cb_info->widget_id);
1211         free(cb_info);
1212 }
1213
1214 /* within package only */
1215 EAPI int widget_instance_listen_status(const char *widget_id, widget_instance_event_cb cb, void *data)
1216 {
1217         struct lifecycle_local_s *cb_info;
1218
1219         if (!widget_id)
1220                 widget_id = "NULL"; /* listen all widget */
1221
1222         cb_info = (struct lifecycle_local_s *)malloc(sizeof(struct lifecycle_local_s));
1223         if (!cb_info) {
1224                 _E("out of memory"); /* LCOV_EXCL_LINE */
1225                 return -1; /* LCOV_EXCL_LINE */
1226         }
1227
1228         cb_info->widget_id = strdup(widget_id);
1229         cb_info->cb = cb;
1230         cb_info->data = data;
1231         if (!lifecycle_tbl) {
1232                 lifecycle_tbl = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
1233                                 __destroy_lifecycle_local);
1234                 if (!lifecycle_tbl) {
1235                         free(cb_info);
1236                         return -1;
1237                 }
1238         }
1239
1240         g_hash_table_insert(lifecycle_tbl, cb_info->widget_id, cb_info);
1241
1242         __connect_status_handler();
1243
1244         return 0;
1245 }
1246
1247 EAPI int widget_instance_unlisten_status(const char *widget_id)
1248 {
1249         struct lifecycle_local_s *cb_info;
1250
1251         if (!widget_id)
1252                 widget_id = "NULL";
1253
1254         cb_info = (struct lifecycle_local_s *)g_hash_table_lookup(lifecycle_tbl, widget_id);
1255         if (!cb_info)
1256                 return -1;
1257
1258         g_hash_table_remove(lifecycle_tbl, widget_id);
1259
1260         return 0;
1261 }
1262
1263 EAPI int widget_service_set_sdk_util(bundle *data)
1264 {
1265         const char *val;
1266         int r;
1267
1268         val = bundle_get_val(data, AUL_K_SDK);
1269         if (val == NULL)
1270                 return -1;
1271
1272         if (!sdk_util.initialized) {
1273                 r = aul_debug_info_init();
1274                 if (r != AUL_R_OK) {
1275                         _E("Failed to initialize debug info");
1276                         return -1;
1277                 }
1278         }
1279
1280         if (sdk_util.b)
1281                 bundle_free(sdk_util.b);
1282
1283         sdk_util.b = bundle_create();
1284         if (sdk_util.b == NULL) {
1285                 _E("Failed to create bundle");
1286                 return -1;
1287         }
1288
1289         r = aul_debug_info_set(data, sdk_util.b);
1290         if (r != AUL_R_OK) {
1291                 _E("Failed to set debug info");
1292                 bundle_free(sdk_util.b);
1293                 sdk_util.b = NULL;
1294                 return -1;
1295         }
1296
1297         return 0;
1298 }