2 * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <bundle_internal.h>
25 #include <glib-object.h>
28 #include <widget_errno.h>
29 #include <widget_instance.h>
30 #include <aul_app_com.h>
31 #include <Ecore_Wayland.h>
32 #include <system_info.h>
34 #include <vconf-internal-keys.h>
35 #include <screen_connector_provider.h>
36 #include <appcore_multiwindow_base.h>
38 #include "widget_base.h"
44 #define LOG_TAG "CAPI_WIDGET_APPLICATION"
45 #define APP_TYPE_WIDGET "widgetapp"
46 #define STATUS_FOREGROUND "fg"
47 #define STATUS_BACKGROUND "bg"
49 static int __app_event_converter[APPCORE_BASE_EVENT_MAX] = {
50 [APP_EVENT_LOW_MEMORY] = APPCORE_BASE_EVENT_LOW_MEMORY,
51 [APP_EVENT_LOW_BATTERY] = APPCORE_BASE_EVENT_LOW_BATTERY,
52 [APP_EVENT_LANGUAGE_CHANGED] = APPCORE_BASE_EVENT_LANG_CHANGE,
53 [APP_EVENT_DEVICE_ORIENTATION_CHANGED]
54 = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED,
55 [APP_EVENT_REGION_FORMAT_CHANGED] = APPCORE_BASE_EVENT_REGION_CHANGE,
56 [APP_EVENT_SUSPENDED_STATE_CHANGED]
57 = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE,
60 struct app_event_info {
61 app_event_type_e type;
65 struct app_event_handler {
66 app_event_type_e type;
72 struct widget_foreach_context {
73 widget_base_instance_cb callback;
77 typedef struct _widget_base_context {
83 } widget_base_context;
85 typedef struct _widget_base_instance_data {
93 char *pending_content;
95 } widget_base_instance_data;
97 static widget_base_context __context;
99 static char *__package_id;
100 static bool __fg_signal;
101 static char *__viewer_endpoint;
102 static bool __is_permanent;
103 static void __call_update_cb(const char *class_id, const char *id, int force,
104 const char *content_raw);
106 static gboolean __timeout_cb(gpointer user_data)
108 widget_base_instance_data *data =
109 (widget_base_instance_data *)user_data;
110 appcore_multiwindow_base_instance_h cxt;
111 const char *class_id;
113 cxt = appcore_multiwindow_base_instance_find(data->id);
114 if (appcore_multiwindow_base_instance_is_resumed(cxt)) {
115 LOGD("Periodic update!");
116 class_id = appcore_multiwindow_base_instance_get_class_id(cxt);
117 __call_update_cb(class_id, data->id, 0, NULL);
119 data->pending_update = true;
120 if (data->periodic_timer) {
121 LOGD("Remove timer!");
122 g_source_remove(data->periodic_timer);
123 data->periodic_timer = 0;
127 return G_SOURCE_CONTINUE;
130 static bool __is_widget_feature_enabled(void)
132 static bool feature = false;
133 static bool retrieved = false;
136 if (retrieved == true)
139 ret = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
140 if (ret != SYSTEM_INFO_ERROR_NONE) {
141 LOGE("failed to get system info"); /* LCOV_EXCL_LINE */
142 return false; /* LCOV_EXCL_LINE */
150 /* LCOV_EXCL_START */
151 static void __on_poweroff(keynode_t *key, void *data)
155 val = vconf_keynode_get_int(key);
157 case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
158 case VCONFKEY_SYSMAN_POWER_OFF_RESTART:
159 LOGI("power off changed: %d", val);
162 case VCONFKEY_SYSMAN_POWER_OFF_NONE:
163 case VCONFKEY_SYSMAN_POWER_OFF_POPUP:
171 static void __check_empty_instance(void)
173 int cnt = appcore_multiwindow_base_instance_get_cnt();
179 static void __instance_drop(appcore_multiwindow_base_instance_h instance_h)
181 widget_base_instance_data *data;
183 data = appcore_multiwindow_base_instance_get_extra(instance_h);
184 appcore_multiwindow_base_instance_drop(instance_h);
185 free(data->pending_content);
189 __check_empty_instance();
192 static gint __comp_class(gconstpointer a, gconstpointer b)
194 const widget_base_class *cls = a;
196 return strcmp(cls->id, b);
199 static widget_base_class *__get_class(const char *class_id)
201 widget_base_class *cls;
204 class_node = g_list_find_custom(__context.classes, class_id,
206 if (class_node == NULL) {
207 LOGE("empty classes");
210 cls = (widget_base_class *)class_node->data;
215 static int __send_lifecycle_event(const char *class_id, const char *instance_id,
218 bundle *b = bundle_create();
222 LOGE("out of memory"); /* LCOV_EXCL_LINE */
223 return -1; /* LCOV_EXCL_LINE */
226 bundle_add_str(b, AUL_K_WIDGET_ID, class_id);
227 bundle_add_str(b, AUL_K_WIDGET_INSTANCE_ID, instance_id);
228 bundle_add_byte(b, AUL_K_WIDGET_STATUS, &status, sizeof(int));
229 bundle_add_str(b, AUL_K_PKGID, __package_id);
231 LOGD("send lifecycle %s(%d)", instance_id, status);
232 ret = aul_app_com_send("widget.status", b);
234 LOGE("send lifecycle error:%d", ret); /* LCOV_EXCL_LINE */
241 static int __send_update_status(const char *class_id, const char *instance_id,
242 int status, bundle *extra)
246 bundle_raw *raw = NULL;
251 LOGE("out of memory"); /* LCOV_EXCL_LINE */
252 return -1; /* LCOV_EXCL_LINE */
255 bundle_add_str(b, AUL_K_WIDGET_ID, class_id);
256 bundle_add_str(b, AUL_K_WIDGET_INSTANCE_ID, instance_id);
257 bundle_add_byte(b, AUL_K_WIDGET_STATUS, &status, sizeof(int));
260 bundle_encode(extra, &raw, &len);
261 bundle_add_str(b, WIDGET_K_CONTENT_INFO, (const char *)raw);
262 aul_widget_instance_add(class_id, instance_id);
265 LOGD("send update %s(%d) to %s", instance_id, status, __viewer_endpoint);
266 aul_app_com_send(__viewer_endpoint, b);
269 case WIDGET_INSTANCE_EVENT_CREATE:
270 lifecycle = WIDGET_LIFE_CYCLE_EVENT_CREATE;
272 case WIDGET_INSTANCE_EVENT_DESTROY:
273 lifecycle = WIDGET_LIFE_CYCLE_EVENT_DESTROY;
275 case WIDGET_INSTANCE_EVENT_PAUSE:
276 lifecycle = WIDGET_LIFE_CYCLE_EVENT_PAUSE;
278 case WIDGET_INSTANCE_EVENT_RESUME:
279 lifecycle = WIDGET_LIFE_CYCLE_EVENT_RESUME;
284 __send_lifecycle_event(class_id, instance_id, lifecycle);
293 static void __control_create(const char *class_id, const char *id, bundle *b)
295 widget_base_instance_data *data;
296 char *content = NULL;
297 double *period = NULL;
301 data = (widget_base_instance_data *)
302 calloc(1, sizeof(widget_base_instance_data));
304 LOGE("Out of memory");
308 data->id = strdup(id);
310 ret = bundle_get_byte(b, WIDGET_K_PERIOD, (void **)&period, &size);
311 if (ret == BUNDLE_ERROR_NONE) {
312 data->period = *period;
313 data->periodic_timer = g_timeout_add_seconds(data->period,
317 /* call stub create */
318 appcore_multiwindow_base_instance_run(class_id, id, data);
320 bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content);
322 data->content = strdup(content);
326 static void __control_resume(const char *class_id, const char *id, bundle *b)
328 appcore_multiwindow_base_instance_h cxt;
330 cxt = appcore_multiwindow_base_instance_find(id);
332 LOGE("context not found: %s", id);
336 /* call stub resume */
337 appcore_multiwindow_base_instance_resume(cxt);
340 static void __control_pause(const char *class_id, const char *id, bundle *b)
342 appcore_multiwindow_base_instance_h instance_h;
344 instance_h = appcore_multiwindow_base_instance_find(id);
347 LOGE("instance not found: %s", id);
351 /* call stub pause */
352 appcore_multiwindow_base_instance_pause(instance_h);
355 static void __control_resize(const char *class_id, const char *id, bundle *b)
357 appcore_multiwindow_base_instance_h instance_h;
364 widget_base_class *cls;
365 const appcore_multiwindow_base_class *raw_cls;
367 instance_h = appcore_multiwindow_base_instance_find(id);
369 LOGE("context not found: %s", id);
373 raw_cls = appcore_multiwindow_base_instance_get_class(instance_h);
377 cls = __get_class(class_id);
379 LOGE("class not found: %s", class_id);
382 class_data = raw_cls->data;
383 bundle_get_str(b, WIDGET_K_WIDTH, &w_str);
384 bundle_get_str(b, WIDGET_K_HEIGHT, &h_str);
387 w = (int)g_ascii_strtoll(w_str, &remain, 10);
390 h = (int)g_ascii_strtoll(h_str, &remain, 10);
393 cls->ops.resize(instance_h, w, h, class_data);
395 LOGD("%s is resized to %dx%d", id, w, h);
396 __send_update_status(class_id, id,
397 WIDGET_INSTANCE_EVENT_SIZE_CHANGED, NULL);
400 static void __call_update_cb(const char *class_id, const char *id, int force,
401 const char *content_raw)
404 widget_base_class *cls;
405 const appcore_multiwindow_base_class *raw_cls;
406 appcore_multiwindow_base_instance_h instance_h;
407 bundle *content = NULL;
409 instance_h = appcore_multiwindow_base_instance_find(id);
411 LOGE("context not found: %s", id);
415 raw_cls = appcore_multiwindow_base_instance_get_class(instance_h);
417 LOGE("class is NULL");
421 class_data = raw_cls->data;
422 cls = __get_class(class_id);
424 LOGE("class not found: %s", class_id);
428 if (!cls->ops.update) {
429 LOGE("update callback is NULL");
434 content = bundle_decode((const bundle_raw *)content_raw,
435 strlen(content_raw));
439 cls->ops.update(instance_h, content, force, class_data);
441 __send_update_status(class_id, id,
442 WIDGET_INSTANCE_EVENT_UPDATE, NULL);
443 LOGD("updated:%s", id);
446 bundle_free(content);
449 static void __update_pending_content(
450 appcore_multiwindow_base_instance_h instance_h,
451 const char *content_raw)
453 widget_base_instance_data *data;
455 data = (widget_base_instance_data *)
456 appcore_multiwindow_base_instance_get_extra(instance_h);
458 if (data->pending_content) {
459 free(data->pending_content);
460 data->pending_content = NULL;
464 data->pending_content = strdup(content_raw);
465 if (data->pending_content == NULL)
466 LOGW("Out of memory");
469 data->pending_update = true;
472 static void __update_process(const char *class_id, const char *id,
473 appcore_multiwindow_base_instance_h instance_h, void *data)
475 char *content_raw = NULL;
476 char *force_str = NULL;
481 LOGE("bundle is NULL");
485 bundle_get_str(b, WIDGET_K_FORCE, &force_str);
487 if (force_str && strcmp(force_str, "true") == 0)
492 bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content_raw);
493 if (!appcore_multiwindow_base_instance_is_resumed(instance_h) && !force)
494 __update_pending_content(instance_h, content_raw);
496 __call_update_cb(class_id, id, force, content_raw);
499 static void __control_update(const char *class_id, const char *id, bundle *b)
501 appcore_multiwindow_base_instance_h instance_h;
504 appcore_multiwindow_base_instance_foreach(class_id,
505 __update_process, b);
509 instance_h = appcore_multiwindow_base_instance_find(id);
511 LOGE("context not found: %s", id);
515 __update_process(class_id, id, instance_h, b);
518 static void __control_destroy(const char *class_id, const char *id, bundle *b)
520 appcore_multiwindow_base_instance_h instance_h;
521 widget_base_instance_data *data;
523 instance_h = appcore_multiwindow_base_instance_find(id);
525 LOGE("could not find widget obj: %s, clear amd info", id);
526 aul_widget_instance_del(class_id, id);
530 data = (widget_base_instance_data *)
531 appcore_multiwindow_base_instance_get_extra(instance_h);
534 /* call stub terminate */
535 appcore_multiwindow_base_instance_exit(instance_h);
536 free(data->pending_content);
540 __check_empty_instance();
543 static void __control_change_period(const char *class_id, const char *id,
546 appcore_multiwindow_base_instance_h instance_h;
547 widget_base_instance_data *data;
548 double *period = NULL;
552 instance_h = appcore_multiwindow_base_instance_find(id);
554 LOGE("context not found: %s", id);
558 data = (widget_base_instance_data *)
559 appcore_multiwindow_base_instance_get_extra(instance_h);
562 LOGE("could not find instance data: %s", id);
566 if (data->periodic_timer) {
567 LOGD("Remove timer!");
568 g_source_remove(data->periodic_timer);
569 data->periodic_timer = 0;
572 ret = bundle_get_byte(b, WIDGET_K_PERIOD, (void **)&period, &size);
573 if (ret == BUNDLE_ERROR_NONE)
574 data->period = *period;
576 if (data->period > 0) {
577 LOGD("Restart timer!");
578 data->periodic_timer = g_timeout_add_seconds(data->period,
585 static int __multiwindow_create(void *data)
587 char pkgid[256] = {0, };
590 appcore_multiwindow_base_on_create();
591 app_get_id(&__appid);
592 if (aul_app_get_pkgid_bypid(getpid(), pkgid, sizeof(pkgid)) == 0)
593 __package_id = strdup(pkgid);
595 if (!__package_id || !__appid) {
596 LOGE("__package_id is NULL");
600 screen_connector_provider_init();
601 vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS,
602 __on_poweroff, NULL);
605 if (__context.ops.create)
606 ret = __context.ops.create(data);
608 LOGD("widget base is created");
612 static int __multiwindow_terminate(void *data)
614 if (__context.ops.terminate)
615 __context.ops.terminate(data);
617 vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS,
619 screen_connector_provider_fini();
621 if (__viewer_endpoint) {
622 free(__viewer_endpoint);
623 __viewer_endpoint = NULL;
636 appcore_multiwindow_base_on_terminate();
638 LOGD("widget base is terminated");
642 static int __multiwindow_control(bundle *b, void *data)
644 char *class_id = NULL;
646 char *operation = NULL;
648 appcore_multiwindow_base_on_control(b);
649 bundle_get_str(b, WIDGET_K_CLASS, &class_id);
650 /* for previous version compatibility, use appid for default class id */
651 if (class_id == NULL)
654 bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id);
655 bundle_get_str(b, WIDGET_K_OPERATION, &operation);
658 LOGE("operation is NULL");
662 if (strcmp(operation, "create") == 0)
663 __control_create(class_id, id, b);
664 else if (strcmp(operation, "resize") == 0)
665 __control_resize(class_id, id, b);
666 else if (strcmp(operation, "update") == 0)
667 __control_update(class_id, id, b);
668 else if (strcmp(operation, "destroy") == 0)
669 __control_destroy(class_id, id, b);
670 else if (strcmp(operation, "resume") == 0)
671 __control_resume(class_id, id, b);
672 else if (strcmp(operation, "pause") == 0)
673 __control_pause(class_id, id, b);
674 else if (strcmp(operation, "terminate") == 0)
675 __control_destroy(class_id, id, b);
676 else if (strcmp(operation, "period") == 0)
677 __control_change_period(class_id, id, b);
682 static void __inst_resume_cb(const char *class_id, const char *id,
683 appcore_multiwindow_base_instance_h cxt, void *data)
685 __control_resume(class_id, id, data);
688 static void __get_content(bundle *b)
690 char *instance_id = NULL;
691 appcore_multiwindow_base_instance_h cxt;
692 widget_base_instance_data * we;
694 bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &instance_id);
696 LOGE("instance id is NULL");
700 cxt = appcore_multiwindow_base_instance_find(instance_id);
702 LOGE("could not find widget obj: %s", instance_id);
706 we = appcore_multiwindow_base_instance_get_extra(cxt);
708 LOGE("widget extra is NULL");
713 bundle_add_str(b, AUL_K_WIDGET_CONTENT_INFO, we->content);
714 LOGD("content info of %s found", instance_id);
716 bundle_add_str(b, AUL_K_WIDGET_CONTENT_INFO, "");
717 LOGD("empty content info added");
721 static int __multiwindow_receive(aul_type type, bundle *b, void *data)
723 appcore_multiwindow_base_on_receive(type, b);
727 appcore_multiwindow_base_instance_foreach_full(
728 __inst_resume_cb, b);
733 case AUL_WIDGET_CONTENT:
743 static void __multiwindow_init(int argc, char **argv, void *data)
745 if (__context.ops.init)
746 __context.ops.init(argc, argv, data);
749 static void __multiwindow_finish(void)
751 if (__context.ops.finish) {
752 __context.ops.finish();
753 /* Check Loader case */
754 if (getenv("AUL_LOADER_INIT")) {
755 unsetenv("AUL_LOADER_INIT");
756 __context.ops.finish();
761 static void __multiwindow_run(void *data)
763 if (__context.ops.run)
764 __context.ops.run(data);
767 static void __multiwindow_exit(void *data)
769 if (__context.ops.exit)
770 __context.ops.exit(data);
773 EXPORT_API int widget_base_exit(void)
775 appcore_multiwindow_base_exit();
776 if (appcore_multiwindow_base_instance_get_cnt() != 0 && __is_permanent)
782 static gboolean __finish_event_cb(gpointer user_data)
784 appcore_multiwindow_base_instance_h cxt = user_data;
787 const char *class_id;
790 LOGE("user_data is NULL");
794 id = appcore_multiwindow_base_instance_get_id(cxt);
795 class_id = appcore_multiwindow_base_instance_get_class_id(cxt);
799 LOGE("Out-of-memory");
803 bundle_add_str(b, WIDGET_K_OPERATION, "terminate");
804 __control_destroy(class_id, id, b);
810 EXPORT_API int widget_base_terminate_context(widget_base_instance_h context)
812 if (!__is_widget_feature_enabled()) {
813 LOGE("not supported"); /* LCOV_EXCL_LINE */
814 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
818 LOGE("context is null");
819 return WIDGET_ERROR_INVALID_PARAMETER;
822 g_idle_add(__finish_event_cb, context);
824 return WIDGET_ERROR_NONE;
827 static void __inst_full_cb(const char *class_id, const char *id,
828 appcore_multiwindow_base_instance_h cxt, void *data)
830 struct widget_foreach_context *foreach_context = data;
835 if (foreach_context->callback)
836 foreach_context->callback(cxt, foreach_context->data);
839 EXPORT_API int widget_base_foreach_context(widget_base_instance_cb cb, void *data)
841 struct widget_foreach_context foreach_context;
843 if (!__is_widget_feature_enabled()) {
844 LOGE("not supported"); /* LCOV_EXCL_LINE */
845 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
849 LOGE("callback is NULL");
850 return WIDGET_ERROR_INVALID_PARAMETER;
853 foreach_context.callback = cb;
854 foreach_context.data = data;
855 appcore_multiwindow_base_instance_foreach_full(__inst_full_cb, &foreach_context);
857 return WIDGET_ERROR_NONE;
860 static int __event_cb(void *event, void *data)
862 app_event_handler_h handler = data;
864 struct app_event_info app_event;
866 app_event.type = handler->type;
867 app_event.value = event;
870 handler->cb(&app_event, handler->data);
875 EXPORT_API int widget_base_add_event_handler(app_event_handler_h *event_handler,
876 app_event_type_e event_type,
877 app_event_cb callback,
882 app_event_handler_h handler;
884 r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
886 return WIDGET_BASE_ERROR_FAULT;
889 return WIDGET_BASE_ERROR_NOT_SUPPORTED;
891 if (event_handler == NULL || callback == NULL)
892 return WIDGET_BASE_ERROR_INVALID_PARAMETER;
894 if (event_type < APP_EVENT_LOW_MEMORY
895 || event_type > APP_EVENT_REGION_FORMAT_CHANGED)
896 return WIDGET_BASE_ERROR_INVALID_PARAMETER;
898 if (event_type == APP_EVENT_DEVICE_ORIENTATION_CHANGED)
899 return WIDGET_BASE_ERROR_NOT_SUPPORTED;
902 handler = calloc(1, sizeof(struct app_event_handler));
904 return WIDGET_BASE_ERROR_OUT_OF_MEMORY;
906 handler->type = event_type;
907 handler->cb = callback;
908 handler->data = user_data;
909 handler->raw = appcore_base_add_event(
910 __app_event_converter[event_type], __event_cb, handler);
911 *event_handler = handler;
913 return WIDGET_BASE_ERROR_NONE;
916 EXPORT_API int widget_base_remove_event_handler(app_event_handler_h
921 app_event_type_e type;
923 r = system_info_get_platform_bool(FEATURE_SHELL_APPWIDGET, &feature);
925 return WIDGET_BASE_ERROR_FAULT;
928 return WIDGET_BASE_ERROR_NOT_SUPPORTED;
930 if (event_handler == NULL)
931 return WIDGET_BASE_ERROR_INVALID_PARAMETER;
933 type = event_handler->type;
934 if (type < APP_EVENT_LOW_MEMORY ||
935 type > APP_EVENT_REGION_FORMAT_CHANGED)
936 return WIDGET_BASE_ERROR_INVALID_PARAMETER;
938 r = appcore_base_remove_event(event_handler->raw);
940 return WIDGET_BASE_ERROR_INVALID_PARAMETER;
944 return WIDGET_BASE_ERROR_NONE;
947 EXPORT_API int widget_base_context_set_content_info(
948 widget_base_instance_h context,
949 bundle *content_info)
952 bundle_raw *raw = NULL;
955 const char *class_id;
956 widget_base_instance_data *data;
957 appcore_multiwindow_base_instance_h instance_h;
959 if (!__is_widget_feature_enabled()) {
960 LOGE("not supported"); /* LCOV_EXCL_LINE */
961 return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
964 if (!context || !content_info)
965 return WIDGET_BASE_ERROR_INVALID_PARAMETER;
967 instance_h = (appcore_multiwindow_base_instance_h)context;
968 id = appcore_multiwindow_base_instance_get_id(instance_h);
969 class_id = appcore_multiwindow_base_instance_get_class_id(instance_h);
970 data = appcore_multiwindow_base_instance_get_extra(instance_h);
972 if (!class_id || !id || !data)
973 return WIDGET_BASE_ERROR_FAULT;
975 ret = __send_update_status(class_id, id,
976 WIDGET_INSTANCE_EVENT_EXTRA_UPDATED, content_info);
981 bundle_encode(content_info, &raw, &len);
983 data->content = strdup((const char *)raw);
985 data->content = NULL;
989 /* LCOV_EXCL_START */
990 LOGE("failed to send content info: %s of %s (%d)", id,
992 return WIDGET_BASE_ERROR_IO_ERROR;
996 return WIDGET_BASE_ERROR_NONE;
999 EXPORT_API int widget_base_context_get_tag(widget_base_instance_h context, void **tag)
1001 appcore_multiwindow_base_instance_h instance_h;
1002 widget_base_instance_data *data;
1004 if (!__is_widget_feature_enabled()) {
1005 LOGE("not supported"); /* LCOV_EXCL_LINE */
1006 return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1009 if (!context || !tag) {
1010 LOGE("Invalid parameter");
1011 return WIDGET_BASE_ERROR_INVALID_PARAMETER;
1014 instance_h = (appcore_multiwindow_base_instance_h)context;
1015 data = (widget_base_instance_data *)
1016 appcore_multiwindow_base_instance_get_extra(instance_h);
1019 LOGE("Invalid parameter");
1020 return WIDGET_ERROR_INVALID_PARAMETER;
1025 return WIDGET_BASE_ERROR_NONE;
1028 EXPORT_API int widget_base_context_set_tag(widget_base_instance_h context, void *tag)
1030 appcore_multiwindow_base_instance_h instance_h;
1031 widget_base_instance_data *data;
1033 if (!__is_widget_feature_enabled()) {
1034 LOGE("not supported"); /* LCOV_EXCL_LINE */
1035 return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1039 LOGE("Invalid parameter");
1040 return WIDGET_BASE_ERROR_INVALID_PARAMETER;
1043 instance_h = (appcore_multiwindow_base_instance_h)context;
1044 data = (widget_base_instance_data *)
1045 appcore_multiwindow_base_instance_get_extra(instance_h);
1048 return WIDGET_BASE_ERROR_NONE;
1051 EXPORT_API void *widget_base_context_get_user_data(
1052 widget_base_instance_h context)
1054 appcore_multiwindow_base_instance_h instance_h;
1055 widget_base_instance_data *data;
1057 if (!__is_widget_feature_enabled()) {
1058 LOGE("not supported"); /* LCOV_EXCL_LINE */
1059 return NULL; /* LCOV_EXCL_LINE */
1063 LOGE("Invalid parameter");
1067 instance_h = (appcore_multiwindow_base_instance_h)context;
1068 data = (widget_base_instance_data *)
1069 appcore_multiwindow_base_instance_get_extra(instance_h);
1071 return data->user_data;
1075 EXPORT_API int widget_base_context_set_user_data(
1076 widget_base_instance_h context, void *user_data)
1078 appcore_multiwindow_base_instance_h instance_h;
1079 widget_base_instance_data *data;
1081 if (!__is_widget_feature_enabled()) {
1082 LOGE("not supported"); /* LCOV_EXCL_LINE */
1083 return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1087 LOGE("Invalid parameter");
1088 return WIDGET_BASE_ERROR_INVALID_PARAMETER;
1091 instance_h = (appcore_multiwindow_base_instance_h)context;
1092 data = (widget_base_instance_data *)
1093 appcore_multiwindow_base_instance_get_extra(instance_h);
1094 data->user_data = user_data;
1096 return WIDGET_BASE_ERROR_NONE;
1099 EXPORT_API int widget_base_context_get_id(widget_base_instance_h context, char **id)
1101 appcore_multiwindow_base_instance_h instance_h;
1103 if (!__is_widget_feature_enabled()) {
1104 LOGE("not supported"); /* LCOV_EXCL_LINE */
1105 return WIDGET_BASE_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1108 instance_h = (appcore_multiwindow_base_instance_h)context;
1109 *id = (char *)appcore_multiwindow_base_instance_get_id(instance_h);
1111 return WIDGET_BASE_ERROR_NONE;
1114 EXPORT_API const char *widget_base_get_viewer_endpoint()
1116 return __viewer_endpoint;
1119 EXPORT_API int widget_base_init(widget_base_ops ops, int argc, char **argv,
1123 char *viewer_endpoint = NULL;
1124 appcore_multiwindow_base_ops raw_ops
1125 = appcore_multiwindow_base_get_default_ops();
1127 __context.ops = ops;
1128 __context.argc = argc;
1129 __context.argv = argv;
1130 __context.data = data;
1132 /* override methods */
1133 raw_ops.base.create = __multiwindow_create;
1134 raw_ops.base.control = __multiwindow_control;
1135 raw_ops.base.terminate = __multiwindow_terminate;
1136 raw_ops.base.receive = __multiwindow_receive;
1137 raw_ops.base.init = __multiwindow_init;
1138 raw_ops.base.finish = __multiwindow_finish;
1139 raw_ops.base.run = __multiwindow_run;
1140 raw_ops.base.exit = __multiwindow_exit;
1142 if (!__is_widget_feature_enabled()) {
1143 LOGE("not supported"); /* LCOV_EXCL_LINE */
1144 return WIDGET_ERROR_NOT_SUPPORTED; /* LCOV_EXCL_LINE */
1147 kb = bundle_import_from_argv(argc, argv);
1149 bundle_get_str(kb, WIDGET_K_ENDPOINT, &viewer_endpoint);
1150 if (viewer_endpoint) {
1151 LOGD("viewer endpoint :%s", viewer_endpoint);
1152 __viewer_endpoint = strdup(viewer_endpoint);
1154 LOGE("endpoint is missing");
1159 LOGE("failed to get launch argv"); /* LCOV_EXCL_LINE */
1160 return WIDGET_ERROR_FAULT;
1163 if (appcore_multiwindow_base_init(raw_ops, argc, argv, data) < 0)
1164 return WIDGET_ERROR_FAULT;
1166 return WIDGET_ERROR_NONE;
1169 static int __on_create(void *data)
1171 return widget_base_on_create();
1174 static int __on_terminate(void *data)
1176 return widget_base_on_terminate();
1179 static void __on_init(int argc, char **argv, void *data)
1181 widget_base_on_init(argc, argv);
1184 static void __on_finish(void)
1186 widget_base_on_finish();
1189 static void __on_run(void *data)
1191 widget_base_on_run();
1194 static void __on_exit(void *data)
1196 widget_base_on_exit();
1199 EXPORT_API int widget_base_on_create(void)
1201 appcore_multiwindow_base_on_create();
1206 EXPORT_API int widget_base_on_terminate(void)
1208 appcore_multiwindow_base_on_terminate();
1213 EXPORT_API int widget_base_on_init(int argc, char **argv)
1218 EXPORT_API void widget_base_on_finish(void)
1222 EXPORT_API void widget_base_on_run(void)
1226 EXPORT_API void widget_base_on_exit(void)
1230 EXPORT_API widget_base_ops widget_base_get_default_ops(void)
1232 widget_base_ops ops;
1234 /* override methods */
1235 ops.create = __on_create;
1236 ops.terminate = __on_terminate;
1237 ops.init = __on_init;
1238 ops.finish = __on_finish;
1240 ops.exit = __on_exit;
1245 static void __free_class(gpointer data)
1247 widget_base_class *cls = data;
1253 EXPORT_API void widget_base_fini(void)
1255 g_list_free_full(__context.classes, __free_class);
1256 __context.classes = NULL;
1258 appcore_multiwindow_base_fini();
1261 EXPORT_API int widget_base_context_window_bind(
1262 widget_base_instance_h instance_h, const char *id,
1263 Ecore_Wl_Window *wl_win)
1265 struct wl_surface *surface;
1267 surface = ecore_wl_window_surface_get(wl_win);
1268 if (surface == NULL) {
1269 LOGE("failed to get surface"); /* LCOV_EXCL_LINE */
1270 return WIDGET_BASE_ERROR_FAULT; /* LCOV_EXCL_LINE */
1273 screen_connector_provider_remote_enable(id, surface);
1274 appcore_multiwindow_base_window_bind(instance_h, wl_win);
1276 return WIDGET_BASE_ERROR_NONE;
1279 static int __class_on_create(widget_base_instance_h instance_h, bundle *content,
1280 int w, int h, void *class_data)
1282 return widget_base_class_on_create(instance_h, content, w, h);
1285 static int __class_on_resume(widget_base_instance_h instance_h, void *class_data)
1287 return widget_base_class_on_resume(instance_h);
1290 static int __class_on_pause(widget_base_instance_h instance_h,
1293 return widget_base_class_on_pause(instance_h);
1296 static int __class_on_resize(widget_base_instance_h instance_h, int w, int h,
1299 return widget_base_class_on_resize(instance_h, w, h);
1302 static int __class_on_update(widget_base_instance_h instance_h, bundle *content,
1303 int force, void *class_data)
1305 return widget_base_class_on_update(instance_h, content, force);
1308 static int __class_on_destroy(widget_base_instance_h instance_h,
1309 widget_base_destroy_type_e reason, bundle *content,
1312 return widget_base_class_on_destroy(instance_h, reason, content);
1315 static void __multiwindow_instance_create(
1316 appcore_multiwindow_base_instance_h instance_h,
1319 widget_base_instance_data *instance_data;
1321 bundle *content_info = NULL;
1323 char *class_id = NULL;
1324 char *operation = NULL;
1325 char *content = NULL;
1328 char *remain = NULL;
1332 widget_base_class *cls;
1334 appcore_multiwindow_base_class_on_create(instance_h);
1335 instance_data = appcore_multiwindow_base_instance_get_extra(instance_h);
1336 b = instance_data->args;
1338 bundle_get_str(b, WIDGET_K_CLASS, &class_id);
1339 /* for previous version compatibility, use appid for default class id */
1340 if (class_id == NULL)
1343 cls = __get_class(class_id);
1345 LOGE("class not found: %s", class_id);
1349 bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &id);
1350 bundle_get_str(b, WIDGET_K_OPERATION, &operation);
1353 LOGE("no operation provided");
1357 bundle_get_str(b, WIDGET_K_CONTENT_INFO, &content);
1358 bundle_get_str(b, WIDGET_K_WIDTH, &w_str);
1359 bundle_get_str(b, WIDGET_K_HEIGHT, &h_str);
1362 w = (int)g_ascii_strtoll(w_str, &remain, 10);
1365 h = (int)g_ascii_strtoll(h_str, &remain, 10);
1368 content_info = bundle_decode((const bundle_raw *)content,
1371 if (cls->ops.create)
1372 ret = cls->ops.create(instance_h, content_info, w, h, class_data);
1375 LOGW("Create callback returns error(%d)", ret);
1376 ret = __send_update_status(class_id, id,
1377 WIDGET_INSTANCE_EVENT_CREATE_ABORTED, NULL);
1378 __instance_drop(instance_h);
1380 LOGD("%s is created", id);
1381 ret = __send_update_status(class_id, id,
1382 WIDGET_INSTANCE_EVENT_CREATE, NULL);
1384 aul_widget_instance_add(class_id, id);
1388 bundle_free(content_info);
1391 static void __multiwindow_instance_resume(
1392 appcore_multiwindow_base_instance_h instance_h,
1396 const char *class_id;
1397 widget_base_class *cls;
1398 widget_base_instance_data *data;
1400 appcore_multiwindow_base_class_on_resume(instance_h);
1401 id = appcore_multiwindow_base_instance_get_id(instance_h);
1402 class_id = appcore_multiwindow_base_instance_get_class_id(instance_h);
1403 cls = __get_class(class_id);
1405 LOGE("class not found: %s", class_id);
1409 data = (widget_base_instance_data *)
1410 appcore_multiwindow_base_instance_get_extra(instance_h);
1412 if (data->pending_update) {
1413 LOGD("pending update!");
1414 data->pending_update = false;
1415 __call_update_cb(class_id, data->id, 0, data->pending_content);
1416 if (data->period > 0) {
1417 LOGD("Restart timer!");
1418 data->periodic_timer = g_timeout_add_seconds(
1420 __timeout_cb, data);
1424 if (cls->ops.resume)
1425 cls->ops.resume(instance_h, class_data);
1427 LOGD("%s is resumed", id);
1428 __send_update_status(class_id, id,
1429 WIDGET_INSTANCE_EVENT_RESUME, NULL);
1432 LOGD("Send fg signal to resourceD");
1433 aul_send_app_status_change_signal(getpid(),
1442 static void __multiwindow_instance_pause(
1443 appcore_multiwindow_base_instance_h instance_h,
1447 const char *class_id;
1448 widget_base_class *cls;
1450 appcore_multiwindow_base_class_on_pause(instance_h);
1451 id = appcore_multiwindow_base_instance_get_id(instance_h);
1452 class_id = appcore_multiwindow_base_instance_get_class_id(instance_h);
1453 cls = __get_class(class_id);
1455 LOGE("class not found: %s", class_id);
1460 cls->ops.pause(instance_h, class_data);
1462 LOGD("%s is paused", id);
1463 __send_update_status(class_id, id,
1464 WIDGET_INSTANCE_EVENT_PAUSE, NULL);
1467 LOGD("Send bg signal to resourceD");
1468 aul_send_app_status_change_signal(getpid(),
1473 __fg_signal = false;
1477 static void __multiwindow_instance_terminate(
1478 appcore_multiwindow_base_instance_h instance_h,
1481 widget_base_instance_data *data;
1483 char *operation = NULL;
1484 bundle *content_info;
1485 widget_base_destroy_type_e reason = WIDGET_BASE_DESTROY_TYPE_TEMPORARY;
1486 int event = WIDGET_INSTANCE_EVENT_TERMINATE;
1488 const char *class_id;
1489 widget_base_class *cls;
1491 id = appcore_multiwindow_base_instance_get_id(instance_h);
1492 class_id = appcore_multiwindow_base_instance_get_class_id(instance_h);
1493 data = appcore_multiwindow_base_instance_get_extra(
1494 (appcore_multiwindow_base_instance_h)instance_h);
1496 cls = __get_class(class_id);
1498 LOGE("class not found: %s", class_id);
1503 bundle_get_str(b, WIDGET_K_OPERATION, &operation);
1504 if (operation && strcmp(operation, "destroy") == 0)
1505 reason = WIDGET_BASE_DESTROY_TYPE_PERMANENT;
1509 content_info = bundle_decode((const bundle_raw *)data->content,
1510 strlen(data->content));
1512 content_info = bundle_create();
1514 if (cls->ops.destroy)
1515 cls->ops.destroy(instance_h, reason, content_info, class_data);
1517 LOGD("%s is destroyed %d", id, reason);
1518 if (reason == WIDGET_BASE_DESTROY_TYPE_PERMANENT) {
1519 __is_permanent = true;
1520 event = WIDGET_INSTANCE_EVENT_DESTROY;
1521 aul_widget_instance_del(class_id, id);
1523 __is_permanent = false;
1524 __send_update_status(class_id, id,
1525 WIDGET_INSTANCE_EVENT_EXTRA_UPDATED,
1530 bundle_free(content_info);
1532 if (data->periodic_timer)
1533 g_source_remove(data->periodic_timer);
1535 __send_update_status(class_id, id, event, NULL);
1536 appcore_multiwindow_base_class_on_terminate(instance_h);
1539 EXPORT_API int widget_base_class_on_create(widget_base_instance_h instance_h,
1540 bundle *content, int w, int h)
1542 appcore_multiwindow_base_class_on_create(instance_h);
1547 EXPORT_API int widget_base_class_on_pause(widget_base_instance_h instance_h)
1549 appcore_multiwindow_base_class_on_pause(instance_h);
1554 EXPORT_API int widget_base_class_on_resume(widget_base_instance_h instance_h)
1556 appcore_multiwindow_base_class_on_resume(instance_h);
1561 EXPORT_API int widget_base_class_on_resize(widget_base_instance_h instance_h,
1567 EXPORT_API int widget_base_class_on_update(widget_base_instance_h instance_h,
1568 bundle *content, int force)
1573 EXPORT_API int widget_base_class_on_destroy(widget_base_instance_h instance_h,
1574 widget_base_destroy_type_e reason, bundle *content)
1576 appcore_multiwindow_base_class_on_terminate(instance_h);
1581 EXPORT_API widget_base_class widget_base_class_get_default(void)
1583 widget_base_class cls;
1585 cls.ops.create = __class_on_create;
1586 cls.ops.resize = __class_on_resize;
1587 cls.ops.update = __class_on_update;
1588 cls.ops.destroy = __class_on_destroy;
1589 cls.ops.pause = __class_on_pause;
1590 cls.ops.resume = __class_on_resume;
1595 EXPORT_API widget_base_class *widget_base_class_add(widget_base_class cls,
1596 const char *class_id, void *class_data)
1598 widget_base_class *c;
1599 appcore_multiwindow_base_class raw_cls;
1601 if (!__is_widget_feature_enabled()) {
1602 LOGE("not supported");
1603 set_last_result(WIDGET_ERROR_NOT_SUPPORTED);
1608 LOGE("class is is NULL");
1609 set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
1613 raw_cls.id = strdup(class_id);
1614 raw_cls.data = class_data;
1615 raw_cls.create = __multiwindow_instance_create;
1616 raw_cls.terminate = __multiwindow_instance_terminate;
1617 raw_cls.pause = __multiwindow_instance_pause;
1618 raw_cls.resume = __multiwindow_instance_resume;
1619 appcore_multiwindow_base_class_add(raw_cls);
1621 c = malloc(sizeof(widget_base_class));
1626 c->id = strdup(class_id);
1627 __context.classes = g_list_append(__context.classes, c);