22a20cd12b001d2dfb1d5cfc2328fa3a52160659
[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_terminate_app(const char *instance_id)
517 {
518         int ret;
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: termiante app (instance not yet initialized: %s)", instance_id);
527                 return -1;
528         }
529
530         if (instance->pid <= 0) {
531                 _E("Invalid pid (%d)", instance->pid);
532                 return -1;
533         }
534
535         ret = aul_terminate_pid(instance->pid);
536         if (ret != 0) {
537                 _E("Fail to terminate (%d)", instance->pid);
538                 return -1;
539         }
540
541         return ret;
542 }
543
544 EAPI int widget_instance_destroy(const char *instance_id)
545 {
546         int ret = 0;
547         struct _widget_instance *instance;
548
549         if (instance_id == NULL)
550                 return -1;
551
552         instance = __pick_instance(instance_id);
553         if (!instance) {
554                 _E("illegal operation: destroy (instance not yet initialized: %s)", instance_id);
555                 return -1;
556         }
557
558         if (instance->pid > 0) {
559                 ret = __send_aul_cmd(instance, "destroy", NULL);
560         } else { /* uninitialized */
561                 __remove_instance(instance);
562         }
563
564         return ret;
565 }
566
567 EAPI int widget_instance_resume(const char *instance_id)
568 {
569         int ret = 0;
570         struct _widget_instance *instance;
571
572         if (instance_id == NULL)
573                 return -1;
574
575         instance = __pick_instance(instance_id);
576         if (!instance) {
577                 _E("illegal operation: resume (instance not yet initialized: %s)", instance_id);
578                 return -1;
579         }
580
581         ret = __send_aul_cmd(instance, "resume", NULL);
582
583         return ret;
584 }
585
586 EAPI int widget_instance_pause(const char *instance_id)
587 {
588         int ret = 0;
589         struct _widget_instance *instance;
590
591         if (instance_id == NULL)
592                 return -1;
593
594         instance = __pick_instance(instance_id);
595         if (!instance) {
596                 _E("illegal operation: pause (instance not yet initialized: %s)", instance_id);
597                 return -1;
598         }
599
600         ret = __send_aul_cmd(instance, "pause", NULL);
601
602         return ret;
603 }
604
605 EAPI int widget_instance_resize(const char *instance_id, int w, int h)
606 {
607         int ret = 0;
608         bundle *b;
609         struct _widget_instance *instance;
610
611         if (instance_id == NULL)
612                 return -1;
613
614         instance = __pick_instance(instance_id);
615         if (!instance) {
616                 _E("illegal operation: resize (instance not yet initialized: %s)", instance_id);
617                 return -1;
618         }
619
620         b = bundle_create();
621         if (b == NULL)
622                 return -1;
623
624         __set_width(b, w);
625         __set_height(b, h);
626
627         ret = __send_aul_cmd(instance, "resize", b);
628
629         bundle_free(b);
630
631         return ret;
632 }
633
634 EAPI int widget_instance_foreach(const char *widget_id, widget_instance_foreach_cb cb, void *data)
635 {
636         GList *apps = _widget_apps;
637         GList *instances = NULL;
638         struct widget_app *app = NULL;
639         struct _widget_instance *instance = NULL;
640
641         if (widget_id == NULL || cb == NULL)
642                 return -1;
643
644         while (apps) {
645                 app = apps->data;
646                 if (app && g_strcmp0(app->widget_id, widget_id) == 0) {
647                         instances = app->instances;
648                         while (instances) {
649                                 instance = instances->data;
650                                 if (instance && cb(instance, data) < 0)
651                                         break;
652
653                                 instances = instances->next;
654                         }
655                 }
656                 apps = apps->next;
657         }
658
659         return 0;
660 }
661
662 static void __notify_event(int event, const char *widget_id, const char *instance_id)
663 {
664         struct event_cb_s *cb_info;
665         GList *iter = event_cbs;
666
667         while (iter) {
668                 cb_info = (struct event_cb_s *)iter->data;
669                 if (cb_info && cb_info->cb)
670                         cb_info->cb(widget_id, instance_id, event, cb_info->data);
671
672                 iter = iter->next;
673         }
674 }
675
676 static int __check_valid_sender(char *widget_id, int pid)
677 {
678         struct widget_app *app = NULL;
679         widget_instance_h instance;
680         GList *head = NULL;
681
682         app = __pick_app(widget_id);
683         if (app) {
684                 head = app->instances;
685                 if (head) {
686                         instance = (widget_instance_h)head->data;
687                         if (instance->pid == -1 || instance->pid == pid)
688                                 return 0;
689                         _E("instance->pid (%d), pid (%d)", instance->pid, pid);
690                 }
691         }
692         return -1;
693 }
694
695 static int __check_valid_sender_v2(const char *sender_pkgid)
696 {
697         char pkgid[256] = {0, };
698         int ret;
699
700         if (sender_pkgid == NULL)
701                 return -1;
702
703         if (package_id == NULL) {
704                 ret = aul_app_get_pkgid_bypid(getpid(), pkgid, sizeof(pkgid));
705                 if (ret != AUL_R_OK) {
706                         _E("Failed to get pkgid");
707                         return -1;
708                 }
709
710                 package_id = strdup(pkgid);
711                 if (package_id == NULL) {
712                         _E("out of memory");
713                         return -1;
714                 }
715         }
716
717         _D("sender_pkgid: %s, pkgid: %s", sender_pkgid, package_id);
718         if (strcmp(package_id, sender_pkgid) == 0)
719                 return 0;
720
721         return -1;
722 }
723
724 static int __status_handler(const char *endpoint, aul_app_com_result_e e, bundle *envelope, void *user_data)
725 {
726         char *widget_id = NULL;
727         char *instance_id = NULL;
728         char *sender_pkgid = NULL;
729         char *is_faulted = NULL;
730         int *status;
731         size_t status_sz = 0;
732         struct lifecycle_local_s *cb_info;
733         char *sender_pid_str;
734         int sender_pid;
735
736         bundle_get_str(envelope, AUL_K_WIDGET_ID, &widget_id);
737         bundle_get_str(envelope, AUL_K_WIDGET_INSTANCE_ID, &instance_id);
738         bundle_get_byte(envelope, AUL_K_WIDGET_STATUS, (void **)&status, &status_sz);
739         bundle_get_str(envelope, AUL_K_COM_SENDER_PID, &sender_pid_str);
740         bundle_get_str(envelope, AUL_K_PKGID, &sender_pkgid);
741         bundle_get_str(envelope, AUL_K_IS_FAULT, &is_faulted);
742
743         if (widget_id == NULL || status == NULL) {
744                 _E("undefined class or instance %s of %s", instance_id, widget_id);
745                 if (status != NULL)
746                         _E("status: %d", *status);
747
748                 return 0;
749         }
750
751         sender_pid = atoi(sender_pid_str);
752         if (__check_valid_sender(widget_id, sender_pid) == -1) {
753                 bundle_get_str(envelope, AUL_K_PKGID, &sender_pkgid);
754                 LOGW("It's not my widget(%s), let's check package", widget_id);
755                 if (__check_valid_sender_v2(sender_pkgid) < 0) {
756                         LOGW("My package do not have widget_id %s", widget_id);
757                         return 0;
758                 }
759         }
760
761         if (*status == AUL_WIDGET_LIFE_CYCLE_EVENT_APP_DEAD &&
762                         is_faulted && !strcmp(is_faulted, "true")) {
763                 LOGW("handle dead widget(%s) instances", widget_id);
764                 aul_widget_write_log(LOG_TAG, "[%s:%d] %s sender(%d)",
765                         __FUNCTION__, __LINE__, widget_id, sender_pid);
766                 __fault_handler(sender_pid);
767         }
768
769         cb_info = (struct lifecycle_local_s *)g_hash_table_lookup(lifecycle_tbl, "NULL");
770         if (cb_info)
771                 cb_info->cb(widget_id, instance_id, *status, cb_info->data);
772
773         cb_info = (struct lifecycle_local_s *)g_hash_table_lookup(lifecycle_tbl, widget_id);
774         if (cb_info)
775                 cb_info->cb(widget_id, instance_id, *status, cb_info->data);
776
777         return 0;
778 }
779
780 static int __connect_status_handler()
781 {
782         if (is_status_handler_connected)
783                 return 0;
784
785         if (aul_app_com_create("widget.status", NULL, __status_handler, NULL, &conn_status) < 0) {
786                 _E("failed to create status");
787                 return -1;
788         }
789
790         is_status_handler_connected = 1;
791
792         return 0;
793 }
794
795 static int __widget_instance_handler(int status, char *widget_id,
796                 char *instance_id, char *content_info, int err)
797 {
798
799         struct _widget_instance *instance;
800
801         if (instance_id == NULL) {
802                 _E("undefined class or instance of %s", widget_id);
803                 return 0;
804         }
805
806         _D("update status %s on %d", instance_id, status);
807
808         instance = __pick_instance(instance_id);
809
810         if (instance == NULL) {
811                 _E("undefined instance id: %s of %s", instance_id, widget_id);
812                 return 0;
813         }
814
815         switch (status) {
816         case WIDGET_INSTANCE_EVENT_CREATE:
817                 instance->status = WIDGET_INSTANCE_RUNNING;
818                 break;
819         case WIDGET_INSTANCE_EVENT_TERMINATE:
820                 instance->status = WIDGET_INSTANCE_TERMINATED;
821                 break;
822         case WIDGET_INSTANCE_EVENT_DESTROY:
823                 instance->status = WIDGET_INSTANCE_DELETED;
824                 break;
825         case WIDGET_INSTANCE_EVENT_PAUSE:
826                 break;
827         case WIDGET_INSTANCE_EVENT_RESUME:
828                 break;
829         case WIDGET_INSTANCE_EVENT_UPDATE:
830                 break;
831         case WIDGET_INSTANCE_EVENT_EXTRA_UPDATED:
832                 if (content_info) {
833                         if (instance->content_info)
834                                 free(instance->content_info);
835
836                         instance->content_info = strdup(content_info);
837                 }
838                 break;
839         case WIDGET_INSTANCE_EVENT_FAULT:
840                 break;
841         case WIDGET_INSTANCE_EVENT_CREATE_ABORTED:
842                 instance->pid = -1;
843                 instance->err = err;
844                 break;
845         default:
846                 _E("unknown status: %d", status);
847                 break;
848         }
849
850         __notify_event(status, widget_id, instance_id);
851
852         if (instance->status == WIDGET_INSTANCE_DELETED)
853                 widget_instance_unref(instance);
854
855         return 0;
856 }
857
858 static int __widget_handler(const char *viewer_id, aul_app_com_result_e e, bundle *envelope, void *user_data)
859 {
860         char *widget_id = NULL;
861         char *instance_id = NULL;
862         char *error_code = NULL;
863         int *status = NULL;
864         size_t status_sz = 0;
865         char *content_info = NULL;
866         char *sender_pid_str = NULL;
867         int sender_pid;
868         int ret;
869         int err = 0;
870
871         bundle_get_str(envelope, AUL_K_WIDGET_ID, &widget_id);
872         bundle_get_byte(envelope, AUL_K_WIDGET_STATUS, (void **)&status, &status_sz);
873
874         if (widget_id == NULL) {
875                 LOGE("undefined widget_id");
876                 return 0;
877         }
878
879         if (*status == WIDGET_INSTANCE_EVENT_APP_RESTART_REQUEST) {
880                 LOGW("WIDGET_INSTANCE_EVENT_APP_RESTART_REQUEST notify");
881                 bundle_get_str(envelope, AUL_K_COM_SENDER_PID, &sender_pid_str);
882                 if (sender_pid_str == NULL) {
883                         LOGE("Failed to get sender pid of %s", widget_id);
884                         return 0;
885                 }
886                 sender_pid = atoi(sender_pid_str);
887                 ret = __check_valid_sender(widget_id, sender_pid);
888                 if (ret == 0)
889                         __notify_event(*status, widget_id, "");
890         } else {
891                 bundle_get_str(envelope, AUL_K_WIDGET_INSTANCE_ID, &instance_id);
892                 bundle_get_str(envelope, WIDGET_K_CONTENT_INFO, &content_info);
893                 bundle_get_str(envelope, AUL_K_WIDGET_ERROR_CODE, &error_code);
894                 if (error_code)
895                         err = atoi(error_code);
896
897                 __widget_instance_handler(*status, widget_id, instance_id,
898                                 content_info, err);
899         }
900
901         return 0;
902 }
903
904 /* LCOV_EXCL_START */
905 static int __fault_handler(int pid)
906 {
907         GList *iter;
908         struct _widget_instance *instance;
909
910         iter = _widget_instances;
911
912         while (iter) {
913                 instance = (struct _widget_instance *)iter->data;
914                 if (instance && instance->pid == pid) {
915                         instance->pid = -1;
916                         instance->status = WIDGET_INSTANCE_TERMINATED;
917                         __notify_event(WIDGET_INSTANCE_EVENT_FAULT, instance->widget_id, instance->id);
918                 }
919                 iter = iter->next;
920         }
921
922         return 0;
923 }
924 /* LCOV_EXCL_STOP */
925
926 EAPI int widget_instance_init(const char *viewer_id)
927 {
928         if (viewer_id == NULL)
929                 return -1;
930
931         viewer_appid = strdup(viewer_id);
932
933         __connect_status_handler();
934
935         _D("widget_instance_init %s", viewer_id);
936         if (aul_app_com_create(viewer_id, NULL, __widget_handler, NULL, &conn_viewer) < 0) {
937                 _E("failed to create app com endpoint");
938                 return -1;
939         }
940
941         return 0;
942 }
943
944 EAPI int widget_instance_fini()
945 {
946         if (sdk_util.initialized) {
947                 aul_debug_info_fini();
948                 sdk_util.initialized = false;
949         }
950
951         if (sdk_util.b) {
952                 bundle_free(sdk_util.b);
953                 sdk_util.b = NULL;
954         }
955
956         if (lifecycle_tbl) {
957                 g_hash_table_destroy(lifecycle_tbl);
958                 lifecycle_tbl = NULL;
959         }
960
961         if (conn_viewer) {
962                 if (aul_app_com_leave(conn_viewer) < 0)
963                         _E("failed to leave app com endpoint viewer");
964                 conn_viewer = NULL;
965         }
966
967         if (conn_status) {
968                 if (aul_app_com_leave(conn_status) < 0)
969                         _E("failed to leave app com endpoint status");
970                 conn_status = NULL;
971         }
972
973         if (viewer_appid) {
974                 free(viewer_appid);
975                 viewer_appid = NULL;
976         }
977
978         if (package_id) {
979                 free(package_id);
980                 package_id = NULL;
981         }
982
983         return 0;
984 }
985
986 EAPI int widget_instance_get_error_code(widget_instance_h instance, int *err)
987 {
988         if (instance == NULL || err == NULL)
989                 return -1;
990
991         *err = instance->err;
992
993         return 0;
994 }
995
996 EAPI int widget_instance_get_id(widget_instance_h instance, char **id)
997 {
998         if (instance == NULL || id == NULL)
999                 return -1;
1000
1001         *id = (char *)instance->id;
1002         return 0;
1003 }
1004
1005 EAPI int widget_instance_get_content(widget_instance_h instance, char **content)
1006 {
1007         if (instance == NULL || content == NULL)
1008                 return -1;
1009
1010         *content = instance->content_info;
1011         return 0;
1012 }
1013
1014 EAPI int widget_instance_get_width(widget_instance_h instance, int *w)
1015 {
1016         if (instance == NULL || w == NULL)
1017                 return -1;
1018
1019         *w = instance->w;
1020         return 0;
1021 }
1022
1023 EAPI int widget_instance_get_height(widget_instance_h instance, int *h)
1024 {
1025         if (instance == NULL || h == NULL)
1026                 return -1;
1027
1028         *h = instance->h;
1029         return 0;
1030 }
1031
1032 EAPI int widget_instance_set_period(widget_instance_h instance, double period)
1033 {
1034         if (instance == NULL || period < 0)
1035                 return -1;
1036
1037         instance->period = period;
1038         return 0;
1039 }
1040
1041 EAPI int widget_instance_get_period(widget_instance_h instance, double *period)
1042 {
1043         if (instance == NULL || period == NULL)
1044                 return -1;
1045
1046         *period = instance->period;
1047         return 0;
1048 }
1049
1050 EAPI int widget_instance_change_period(const char *widget_id, const char *instance_id, double period)
1051 {
1052         int ret;
1053         bundle *b;
1054
1055         b = bundle_create();
1056         if (!b) {
1057                 _E("out of memory"); /* LCOV_EXCL_LINE */
1058                 return -1; /* LCOV_EXCL_LINE */
1059         }
1060
1061         bundle_add_byte(b, WIDGET_K_PERIOD, &period, sizeof(double));
1062         bundle_add_str(b, WIDGET_K_OPERATION, "period");
1063         ret = aul_widget_instance_update(widget_id, instance_id, b);
1064         bundle_free(b);
1065
1066         return ret;
1067 }
1068
1069 EAPI int widget_instance_trigger_update(widget_instance_h instance, const char *content_info, int force)
1070 {
1071         if (!instance)
1072                 return -1;
1073
1074         return widget_instance_trigger_update_v2(instance->widget_id, instance->id, content_info, force);
1075 }
1076
1077 EAPI int widget_instance_trigger_update_v2(const char *widget_id,
1078                 const char *instance_id, const char *content_info, int force)
1079 {
1080         int ret;
1081
1082         bundle *kb;
1083
1084         kb = bundle_create();
1085         if (!kb) {
1086                 _E("out of memory"); /* LCOV_EXCL_LINE */
1087                 return -1; /* LCOV_EXCL_LINE */
1088         }
1089
1090         bundle_add_str(kb, WIDGET_K_OPERATION, "update");
1091
1092         if (force)
1093                 bundle_add_str(kb, WIDGET_K_FORCE, "true");
1094
1095         if (content_info)
1096                 bundle_add_str(kb, WIDGET_K_CONTENT_INFO, content_info);
1097
1098         ret = aul_widget_instance_update(widget_id, instance_id, kb);
1099
1100         bundle_free(kb);
1101
1102         if (ret >= 0)
1103                 return WIDGET_ERROR_NONE;
1104
1105         switch (ret) {
1106         case AUL_R_ENOAPP:
1107                 ret = WIDGET_ERROR_NOT_EXIST;
1108                 break;
1109         case AUL_R_EILLACC:
1110                 ret = WIDGET_ERROR_PERMISSION_DENIED;
1111                 break;
1112         case AUL_R_EINVAL:
1113                 ret = WIDGET_ERROR_INVALID_PARAMETER;
1114                 break;
1115         case AUL_R_ECANCELED:
1116                 ret = WIDGET_ERROR_CANCELED;
1117                 break;
1118         default:
1119                 ret = WIDGET_ERROR_FAULT;
1120         }
1121
1122         return ret;
1123 }
1124
1125 EAPI widget_instance_h widget_instance_get_instance(const char *widget_id, const char *instance_id)
1126 {
1127         widget_instance_h instance;
1128
1129         if (widget_id == NULL || instance_id == NULL)
1130                 return NULL;
1131
1132         if (_widget_apps && _widget_instances) {
1133                 instance = __pick_instance(instance_id);
1134                 return widget_instance_ref(instance);
1135         }
1136
1137         return NULL;
1138 }
1139
1140 EAPI int widget_instance_get_instance_list(const char *widget_id, widget_instance_list_cb cb, void *data)
1141 {
1142         widget_instance_h instance;
1143         struct widget_app *app;
1144         GList *head = NULL;
1145
1146         if (widget_id == NULL)
1147                 return -1;
1148
1149         if (_widget_apps)
1150                 app = __pick_app(widget_id);
1151         else
1152                 return -2;
1153
1154         if (app) {
1155                 head = app->instances;
1156
1157                 while (head) {
1158                         instance = (widget_instance_h)head->data;
1159                         if (cb(instance->widget_id, instance->id, data) != 0)
1160                                 break;
1161
1162                         head = head->next;
1163                 }
1164         }
1165
1166         return 0;
1167 }
1168
1169 EAPI void widget_instance_unref(widget_instance_h instance)
1170 {
1171         if (instance == NULL)
1172                 return;
1173
1174         instance->ref--;
1175
1176         if (instance->ref > -1)
1177                 return;
1178
1179         __remove_instance(instance);
1180 }
1181
1182 EAPI widget_instance_h widget_instance_ref(widget_instance_h instance)
1183 {
1184         if (instance)
1185                 instance->ref++;
1186
1187         return instance;
1188 }
1189
1190 EAPI int widget_instance_listen_event(widget_instance_event_cb cb, void *data)
1191 {
1192         struct event_cb_s *cb_info;
1193
1194         cb_info = (struct event_cb_s *)malloc(sizeof(struct event_cb_s));
1195         if (!cb_info) {
1196                 _E("out of memory"); /* LCOV_EXCL_LINE */
1197                 return -1; /* LCOV_EXCL_LINE */
1198         }
1199
1200         cb_info->cb = cb;
1201         cb_info->data = data;
1202
1203         event_cbs = g_list_append(event_cbs, cb_info);
1204         if (!event_cbs) {
1205                 _E("out of memory"); /* LCOV_EXCL_LINE */
1206                 return -1; /* LCOV_EXCL_LINE */
1207         }
1208
1209         return 0;
1210 }
1211
1212 EAPI int widget_instance_unlisten_event(widget_instance_event_cb cb)
1213 {
1214         struct event_cb_s *cb_info;
1215         GList *iter = event_cbs;
1216
1217         if (!cb) {
1218                 _E("invalid parameter");
1219                 return -1;
1220         }
1221
1222         while (iter) {
1223                 cb_info = (struct event_cb_s *)iter->data;
1224                 if (cb_info && cb_info->cb == cb) {
1225                         event_cbs = g_list_remove_link(event_cbs, iter);
1226                         free(cb_info);
1227                         g_list_free(iter);
1228                         return 0;
1229                 }
1230                 iter = iter->next;
1231         }
1232
1233         _E("wrong argument");
1234         return -1;
1235 }
1236
1237 static void __destroy_lifecycle_local(gpointer data)
1238 {
1239         struct lifecycle_local_s *cb_info = (struct lifecycle_local_s *)data;
1240
1241         if (cb_info == NULL)
1242                 return;
1243
1244         if (cb_info->widget_id)
1245                 free(cb_info->widget_id);
1246         free(cb_info);
1247 }
1248
1249 /* within package only */
1250 EAPI int widget_instance_listen_status(const char *widget_id, widget_instance_event_cb cb, void *data)
1251 {
1252         struct lifecycle_local_s *cb_info;
1253
1254         if (!widget_id)
1255                 widget_id = "NULL"; /* listen all widget */
1256
1257         cb_info = (struct lifecycle_local_s *)malloc(sizeof(struct lifecycle_local_s));
1258         if (!cb_info) {
1259                 _E("out of memory"); /* LCOV_EXCL_LINE */
1260                 return -1; /* LCOV_EXCL_LINE */
1261         }
1262
1263         cb_info->widget_id = strdup(widget_id);
1264         cb_info->cb = cb;
1265         cb_info->data = data;
1266         if (!lifecycle_tbl) {
1267                 lifecycle_tbl = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
1268                                 __destroy_lifecycle_local);
1269                 if (!lifecycle_tbl) {
1270                         free(cb_info->widget_id);
1271                         free(cb_info);
1272                         return -1;
1273                 }
1274         }
1275
1276         g_hash_table_insert(lifecycle_tbl, cb_info->widget_id, cb_info);
1277
1278         __connect_status_handler();
1279
1280         return 0;
1281 }
1282
1283 EAPI int widget_instance_unlisten_status(const char *widget_id)
1284 {
1285         struct lifecycle_local_s *cb_info;
1286
1287         if (!widget_id)
1288                 widget_id = "NULL";
1289
1290         cb_info = (struct lifecycle_local_s *)g_hash_table_lookup(lifecycle_tbl, widget_id);
1291         if (!cb_info)
1292                 return -1;
1293
1294         g_hash_table_remove(lifecycle_tbl, widget_id);
1295
1296         return 0;
1297 }
1298
1299 EAPI int widget_service_set_sdk_util(bundle *data)
1300 {
1301         const char *val;
1302         int r;
1303
1304         val = bundle_get_val(data, AUL_K_SDK);
1305         if (val == NULL)
1306                 return -1;
1307
1308         if (!sdk_util.initialized) {
1309                 r = aul_debug_info_init();
1310                 if (r != AUL_R_OK) {
1311                         _E("Failed to initialize debug info");
1312                         return -1;
1313                 }
1314         }
1315
1316         if (sdk_util.b)
1317                 bundle_free(sdk_util.b);
1318
1319         sdk_util.b = bundle_create();
1320         if (sdk_util.b == NULL) {
1321                 _E("Failed to create bundle");
1322                 return -1;
1323         }
1324
1325         r = aul_debug_info_set(data, sdk_util.b);
1326         if (r != AUL_R_OK) {
1327                 _E("Failed to set debug info");
1328                 bundle_free(sdk_util.b);
1329                 sdk_util.b = NULL;
1330                 return -1;
1331         }
1332
1333         return 0;
1334 }
1335
1336 EAPI int widget_instance_convert_event_to_lifecycle_status(int event)
1337 {
1338         switch (event) {
1339         case WIDGET_INSTANCE_EVENT_CREATE:
1340                 return WIDGET_LIFE_CYCLE_EVENT_CREATE;
1341         case WIDGET_INSTANCE_EVENT_DESTROY:
1342                 return WIDGET_LIFE_CYCLE_EVENT_DESTROY;
1343         case WIDGET_INSTANCE_EVENT_PAUSE:
1344                 return WIDGET_LIFE_CYCLE_EVENT_PAUSE;
1345         case WIDGET_INSTANCE_EVENT_RESUME:
1346                 return WIDGET_LIFE_CYCLE_EVENT_RESUME;
1347         }
1348
1349         return -1;
1350 }
1351
1352 EAPI int widget_instance_delete(const char *widget_id, const char *instance_id)
1353 {
1354         int ret;
1355
1356         ret = aul_widget_instance_del(widget_id, instance_id);
1357         if (ret == AUL_R_OK)
1358                 return WIDGET_ERROR_NONE;
1359
1360         switch (ret) {
1361         case AUL_R_ERROR:
1362                 ret = WIDGET_ERROR_OUT_OF_MEMORY;
1363                 break;
1364         case AUL_R_EINVAL:
1365                 ret = WIDGET_ERROR_INVALID_PARAMETER;
1366                 break;
1367         default:
1368                 ret = WIDGET_ERROR_FAULT;
1369                 break;
1370         }
1371
1372         return ret;
1373 }