2 * Copyright 2013 Samsung Electronics Co., Ltd
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
8 * http://floralicense.org/license/
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.
25 #include <widget_errno.h>
26 #include <widget_service.h>
27 #include <widget_conf.h>
28 #include <widget_abi.h>
29 #include <widget_util.h>
33 #include <pkgmgr-info.h>
39 #include <com-core_packet.h>
41 #include "widget_provider.h"
42 #include "widget_provider_buffer.h"
44 #include "widget_provider_app.h"
45 #include "widget_provider_app_internal.h"
48 #include "connection.h"
50 #define PKGMGR_COMPONENT_TYPE_WATCH_APP "watchapp"
51 #define BUFFER_MAX 256
58 struct widget_provider_event_callback *table;
61 Eina_List *handle_list;
64 struct internal_item {
73 char *hw_acceleration;
74 Ecore_Timer *ping_timer;
78 Eina_List *internal_item_list;
79 Eina_List *widget_pre_callback_list[WIDGET_PRE_CALLBACK_COUNT];
84 .hw_acceleration = NULL,
89 .internal_item_list = NULL,
90 .widget_pre_callback_list = { NULL, },
93 struct pre_callback_item {
94 widget_pre_callback_t cb;
98 static void invoke_pre_callback(widget_pre_callback_e type, const char *id)
102 struct pre_callback_item *item;
104 EINA_LIST_FOREACH_SAFE(s_info.widget_pre_callback_list[type], l, n, item) {
105 item->cb(id, item->data);
109 static inline char *package_get_pkgid(const char *appid)
112 pkgmgrinfo_appinfo_h handle;
113 char *new_appid = NULL;
116 ret = pkgmgrinfo_appinfo_get_appinfo(appid, &handle);
117 if (ret != PMINFO_R_OK) {
118 ErrPrint("Failed to get appinfo\n");
122 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &new_appid);
123 if (ret != PMINFO_R_OK) {
124 pkgmgrinfo_appinfo_destroy_appinfo(handle);
125 ErrPrint("Failed to get pkgname for (%s)\n", appid);
129 if (new_appid && new_appid[0] != '\0') {
130 pkgid = strdup(new_appid);
132 ErrPrint("strdup: %s\n", strerror(errno));
135 pkgmgrinfo_appinfo_destroy_appinfo(handle);
140 char *widget_pkgname(void)
142 widget_list_h list_handle;
143 const char *abi_pkgname = NULL;
145 char *converted_provider_pkgname = NULL;
149 pkgid = package_get_pkgid(provider_pkgname());
150 list_handle = widget_service_create_widget_list(pkgid, NULL);
151 abi_pkgname = s_info.abi ? widget_abi_get_pkgname_by_abi(s_info.abi) : NULL;
154 widget_service_destroy_widget_list(list_handle);
155 ErrPrint("Failed to get pkgname[%s]", s_info.abi);
161 while (widget_service_get_item_from_widget_list(list_handle, NULL, &widget_id, NULL) == WIDGET_ERROR_NONE) {
163 ErrPrint("Invalid widget_id\n");
167 // tmp == /APPID/.provider <<- PROVIDER UI-APP
168 // widget_id == org.tizen.watch-hello <<-- WIDGET ID
169 // provider_pkgname == org.tizen.watch-hello.provider
170 converted_provider_pkgname = widget_util_replace_string(abi_pkgname, WIDGET_CONF_REPLACE_TAG_APPID, widget_id);
171 if (!converted_provider_pkgname) {
177 /* Verify the Package Name */
178 verified = !strcmp(converted_provider_pkgname, provider_pkgname());
179 DbgFree(converted_provider_pkgname);
189 widget_service_destroy_widget_list(list_handle);
193 static Eina_Bool periodic_updator(void *data)
195 struct item *item = data;
197 if (item->table->update) {
199 ret = item->table->update(item->id, NULL, 0, item->table->data);
201 ErrPrint("Provider update: [%s] returns 0x%X\n", item->id, ret);
205 return ECORE_CALLBACK_RENEW;
208 static struct method s_table[] = {
215 static struct internal_item *internal_item_create(const char *uri)
217 struct internal_item *item;
219 item = malloc(sizeof(*item));
221 ErrPrint("Heap: %s\n", strerror(errno));
225 item->id = strdup(uri);
227 ErrPrint("Heap: %s\n", strerror(errno));
232 s_info.internal_item_list = eina_list_append(s_info.internal_item_list, item);
237 static void internal_item_destroy(struct internal_item *item)
239 s_info.internal_item_list = eina_list_remove(s_info.internal_item_list, item);
245 static struct internal_item *internal_item_find(const char *uri)
248 struct internal_item *item;
250 EINA_LIST_FOREACH(s_info.internal_item_list, l, item) {
251 if (!strcmp(item->id, uri)) {
259 static struct item *instance_create(const char *id, double period, struct widget_provider_event_callback *table, const char *direct_addr)
263 item = calloc(1, sizeof(*item));
265 ErrPrint("Heap: %s\n", strerror(errno));
269 item->id = strdup(id);
271 ErrPrint("Heap: %s\n", strerror(errno));
277 * If the "secured" flag is toggled,
278 * The master will send the update event to this provider app.
280 if (!s_info.secured && period > 0.0f) {
281 item->update_timer = util_timer_add(period, periodic_updator, item);
282 if (!item->update_timer) {
283 ErrPrint("Failed to create a timer\n");
292 struct connection *conn_handle;
294 conn_handle = connection_find_by_addr(direct_addr);
296 conn_handle = connection_create(direct_addr, (void *)s_table);
298 ErrPrint("Failed to create a new connection\n");
300 item->handle_list = eina_list_append(item->handle_list, conn_handle);
303 item->handle_list = eina_list_append(item->handle_list, conn_handle);
304 (void)connection_ref(conn_handle);
309 s_info.inst_list = eina_list_append(s_info.inst_list, item);
314 static void instance_destroy(struct item *item)
316 struct connection *conn_handle;
317 s_info.inst_list = eina_list_remove(s_info.inst_list, item);
318 if (item->update_timer) {
319 util_timer_del(item->update_timer);
322 EINA_LIST_FREE(item->handle_list, conn_handle) {
323 (void)connection_unref(conn_handle);
328 static struct item *instance_find(const char *id)
333 EINA_LIST_FOREACH(s_info.inst_list, l, item) {
334 if (!strcmp(item->id, id)) {
342 static int method_new(struct widget_event_arg *arg, int *width, int *height, double *priority, void *data)
344 struct widget_provider_event_callback *table = data;
348 DbgPrint("Create: pkgname[%s], id[%s], content[%s], timeout[%d], has_script[%d], period[%lf], cluster[%s], category[%s], skip[%d], abi[%s], size: %dx%d\n",
349 arg->pkgname, arg->id,
350 arg->info.widget_create.content,
351 arg->info.widget_create.timeout,
352 arg->info.widget_create.has_script,
353 arg->info.widget_create.period,
354 arg->info.widget_create.cluster, arg->info.widget_create.category,
355 arg->info.widget_create.skip_need_to_create,
356 arg->info.widget_create.abi,
357 arg->info.widget_create.width,
358 arg->info.widget_create.height);
360 invoke_pre_callback(WIDGET_PRE_CREATE_CALLBACK, arg->id);
362 if (!table->create) {
363 ErrPrint("Function is not implemented\n");
364 return WIDGET_ERROR_NOT_SUPPORTED;
367 inst = instance_create(arg->id, arg->info.widget_create.period, table, arg->info.widget_create.direct_addr);
369 return WIDGET_ERROR_FAULT;
372 ret = table->create(widget_util_uri_to_path(arg->id), arg->info.widget_create.content, arg->info.widget_create.width, arg->info.widget_create.height, table->data);
373 if (ret != WIDGET_ERROR_NONE) {
374 ErrPrint("Failed to create an instance\n");
375 instance_destroy(inst);
377 struct widget_buffer *buffer;
379 buffer = widget_provider_buffer_find_buffer(WIDGET_TYPE_WIDGET, arg->pkgname, arg->id);
382 (void)widget_provider_buffer_get_size(buffer, width, height, &bps);
389 static int method_renew(struct widget_event_arg *arg, void *data)
391 struct widget_provider_event_callback *table = data;
395 DbgPrint("Re-create: pkgname[%s], id[%s], content[%s], timeout[%d], has_script[%d], period[%lf], cluster[%s], category[%s], abi[%s], size: %dx%d\n",
396 arg->pkgname, arg->id,
397 arg->info.widget_recreate.content,
398 arg->info.widget_recreate.timeout,
399 arg->info.widget_recreate.has_script,
400 arg->info.widget_recreate.period,
401 arg->info.widget_recreate.cluster,
402 arg->info.widget_recreate.category,
403 arg->info.widget_recreate.abi,
404 arg->info.widget_recreate.width,
405 arg->info.widget_recreate.height);
407 invoke_pre_callback(WIDGET_PRE_CREATE_CALLBACK, arg->id);
409 if (!table->create) {
410 ErrPrint("Function is not implemented\n");
411 return WIDGET_ERROR_NOT_SUPPORTED;
414 inst = instance_create(arg->id, arg->info.widget_recreate.period, table, arg->info.widget_recreate.direct_addr);
416 return WIDGET_ERROR_FAULT;
419 ret = table->create(widget_util_uri_to_path(arg->id), arg->info.widget_recreate.content, arg->info.widget_recreate.width, arg->info.widget_recreate.height, table->data);
421 instance_destroy(inst);
427 static int method_delete(struct widget_event_arg *arg, void *data)
429 struct widget_provider_event_callback *table = data;
433 DbgPrint("pkgname[%s] id[%s]\n", arg->pkgname, arg->id);
435 invoke_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, arg->id);
437 if (!table->destroy) {
438 ErrPrint("Function is not implemented\n");
439 return WIDGET_ERROR_NOT_SUPPORTED;
442 inst = instance_find(arg->id);
444 return WIDGET_ERROR_INVALID_PARAMETER;
447 ret = table->destroy(widget_util_uri_to_path(arg->id), arg->info.widget_destroy.type, table->data);
448 instance_destroy(inst);
452 static int method_content_event(struct widget_event_arg *arg, void *data)
454 struct widget_provider_event_callback *table = data;
457 if (!table->text_signal) {
458 ErrPrint("Function is not implemented\n");
459 return WIDGET_ERROR_NOT_SUPPORTED;
462 ret = table->text_signal(widget_util_uri_to_path(arg->id),
463 arg->info.content_event.signal_name, arg->info.content_event.source,
464 &arg->info.content_event.info,
470 static int method_clicked(struct widget_event_arg *arg, void *data)
472 int ret = WIDGET_ERROR_NONE;
473 #ifdef WIDGET_FEATURE_HANDLE_CLICKED_EVENT
474 struct widget_provider_event_callback *table = data;
476 DbgPrint("pkgname[%s] id[%s] event[%s] timestamp[%lf] x[%lf] y[%lf]\n",
477 arg->pkgname, arg->id,
478 arg->info.clicked.event, arg->info.clicked.timestamp,
479 arg->info.clicked.x, arg->info.clicked.y);
481 if (!table->clicked) {
482 ErrPrint("Function is not implemented\n");
483 return WIDGET_ERROR_NOT_SUPPORTED;
486 ret = table->clicked(widget_util_uri_to_path(arg->id), arg->info.clicked.event, arg->info.clicked.x, arg->info.clicked.y, arg->info.clicked.timestamp, table->data);
487 #endif /* WIDGET_FEATURE_HANDLE_CLICKED_EVENT */
492 static int method_text_signal(struct widget_event_arg *arg, void *data)
494 struct widget_provider_event_callback *table = data;
497 if (!table->text_signal) {
498 ErrPrint("Function is not implemented\n");
499 return WIDGET_ERROR_NOT_SUPPORTED;
502 ret = table->text_signal(widget_util_uri_to_path(arg->id),
503 arg->info.text_signal.signal_name, arg->info.text_signal.source,
504 &arg->info.text_signal.info, table->data);
509 static int method_resize(struct widget_event_arg *arg, void *data)
511 struct widget_provider_event_callback *table = data;
514 invoke_pre_callback(WIDGET_PRE_RESIZE_CALLBACK, arg->id);
516 if (!table->resize) {
517 ErrPrint("Function is not implemented\n");
518 return WIDGET_ERROR_NOT_SUPPORTED;
521 DbgPrint("pkgname[%s] id[%s] w[%d] h[%d]\n", arg->pkgname, arg->id, arg->info.resize.w, arg->info.resize.h);
522 ret = table->resize(widget_util_uri_to_path(arg->id), arg->info.resize.w, arg->info.resize.h, table->data);
526 static int method_set_period(struct widget_event_arg *arg, void *data)
530 DbgPrint("pkgname[%s] id[%s] period[%lf]\n", arg->pkgname, arg->id, arg->info.set_period.period);
531 inst = instance_find(arg->id);
533 return WIDGET_ERROR_INVALID_PARAMETER;
536 if (inst->update_timer) {
537 util_timer_interval_set(inst->update_timer, arg->info.set_period.period);
540 return WIDGET_ERROR_NONE;
543 static int method_change_group(struct widget_event_arg *arg, void *data)
545 return WIDGET_ERROR_NOT_SUPPORTED;
548 static int method_pinup(struct widget_event_arg *arg, void *data)
550 return WIDGET_ERROR_NOT_SUPPORTED;
553 static int method_update_content(struct widget_event_arg *arg, void *data)
555 struct widget_provider_event_callback *table = data;
558 if (!table->update) {
559 return WIDGET_ERROR_NOT_SUPPORTED;
562 ret = table->update(widget_util_uri_to_path(arg->id), arg->info.update_content.content, arg->info.update_content.force, table->data);
566 static int method_pause(struct widget_event_arg *arg, void *data)
568 struct widget_provider_event_callback *table = data;
572 if (s_info.paused == 1) {
573 DbgPrint("Already paused\n");
574 return WIDGET_ERROR_NONE;
579 EINA_LIST_FOREACH(s_info.inst_list, l, inst) {
580 if (inst->paused == 1) {
584 if (inst->update_timer) {
585 util_timer_freeze(inst->update_timer);
589 table->pause(widget_util_uri_to_path(inst->id), table->data);
593 if (s_info.ping_timer) {
594 ecore_timer_freeze(s_info.ping_timer);
597 return WIDGET_ERROR_NONE;
600 static int method_resume(struct widget_event_arg *arg, void *data)
602 struct widget_provider_event_callback *table = data;
606 if (s_info.paused == 0) {
607 DbgPrint("Already resumed\n");
608 return WIDGET_ERROR_NONE;
613 EINA_LIST_FOREACH(s_info.inst_list, l, inst) {
614 if (inst->paused == 1) {
618 if (inst->update_timer) {
619 util_timer_thaw(inst->update_timer);
623 table->resume(widget_util_uri_to_path(inst->id), table->data);
627 if (s_info.ping_timer) {
628 ecore_timer_thaw(s_info.ping_timer);
631 return WIDGET_ERROR_NONE;
634 static Eina_Bool send_ping_cb(void *data)
636 widget_provider_send_ping();
638 return ECORE_CALLBACK_RENEW;
641 static int method_disconnected(struct widget_event_arg *arg, void *data)
643 struct widget_provider_event_callback *table = data;
650 if (s_info.ping_timer) {
651 ecore_timer_del(s_info.ping_timer);
652 s_info.ping_timer = NULL;
656 * After clean up all connections to master, (why?)
657 * invoke destroy callback for every instances.
659 EINA_LIST_FOREACH_SAFE(s_info.inst_list, l, n, item) {
660 invoke_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, item->id);
662 if (table->destroy) {
663 (void)table->destroy(widget_util_uri_to_path(item->id), WIDGET_DESTROY_TYPE_FAULT, item->table->data);
667 * instance_destroy will remove the "item" from this "inst_list"
669 instance_destroy(item);
672 if (table->disconnected) {
673 table->disconnected(table->data);
678 return WIDGET_ERROR_NONE;
681 static int method_connected(struct widget_event_arg *arg, void *data)
684 struct widget_provider_event_callback *table = data;
686 ret = widget_provider_send_hello();
688 s_info.ping_timer = ecore_timer_add(WIDGET_CONF_DEFAULT_PING_TIME / 2.0f, send_ping_cb, NULL);
689 if (!s_info.ping_timer) {
690 ErrPrint("Failed to add a ping timer\n");
694 if (table->connected) {
695 table->connected(table->data);
698 return WIDGET_ERROR_NONE;
701 static int method_viewer_connected(struct widget_event_arg *arg, void *data)
705 item = instance_find(arg->id);
707 return WIDGET_ERROR_INVALID_PARAMETER;
710 if (arg->info.viewer_connected.direct_addr && arg->info.viewer_connected.direct_addr[0]) {
711 struct connection *handle;
713 * \TODO: Create a new connection if the direct_addr is valid
715 handle = connection_find_by_addr(arg->info.viewer_connected.direct_addr);
717 (void)connection_ref(handle);
719 handle = connection_create(arg->info.viewer_connected.direct_addr, (void *)s_table);
722 item->handle_list = eina_list_append(item->handle_list, handle);
724 DbgPrint("Newly comming connection has no valid direct_addr\n");
727 return WIDGET_ERROR_NOT_SUPPORTED;
730 static int method_viewer_disconnected(struct widget_event_arg *arg, void *data)
734 item = instance_find(arg->id);
736 return WIDGET_ERROR_INVALID_PARAMETER;
739 if (arg->info.viewer_disconnected.direct_addr && arg->info.viewer_disconnected.direct_addr[0]) {
740 struct connection *handle;
742 * \TODO: Create a new connection if the direct_addr is valid
744 handle = connection_find_by_addr(arg->info.viewer_disconnected.direct_addr);
746 if (eina_list_data_find(item->handle_list, handle)) {
747 item->handle_list = eina_list_remove(item->handle_list, handle);
748 (void)connection_unref(handle);
751 ErrPrint("There is no valid connection object: %s\n", arg->info.viewer_disconnected.direct_addr);
754 DbgPrint("Disconnected connection has no valid direct_addr\n");
757 return WIDGET_ERROR_NOT_SUPPORTED;
760 static int method_gbar_created(struct widget_event_arg *arg, void *data)
762 int ret = WIDGET_ERROR_NONE;
763 #ifdef WIDGET_FEATURE_GBAR_SUPPORTED
764 struct widget_provider_event_callback *table = data;
766 if (!table->gbar.create) {
767 return WIDGET_ERROR_NOT_SUPPORTED;
770 ret = table->gbar.create(widget_util_uri_to_path(arg->id), arg->info.gbar_create.w, arg->info.gbar_create.h, arg->info.gbar_create.x, arg->info.gbar_create.y, table->data);
772 ret = WIDGET_ERROR_NOT_SUPPORTED;
773 #endif /* WIDGET_FEATURE_GBAR_SUPPORTED */
777 static int method_gbar_destroyed(struct widget_event_arg *arg, void *data)
779 int ret = WIDGET_ERROR_NONE;
780 #ifdef WIDGET_FEATURE_GBAR_SUPPORTED
781 struct widget_provider_event_callback *table = data;
783 if (!table->gbar.destroy) {
784 return WIDGET_ERROR_NOT_SUPPORTED;
787 ret = table->gbar.destroy(widget_util_uri_to_path(arg->id), arg->info.gbar_destroy.reason, table->data)
789 ret = WIDGET_ERROR_NOT_SUPPORTED;
790 #endif /* WIDGET_FEATURE_GBAR_SUPPORTED */
794 static int method_gbar_moved(struct widget_event_arg *arg, void *data)
796 int ret = WIDGET_ERROR_NONE;
797 #ifdef WIDGET_FEATURE_GBAR_SUPPORTED
798 struct widget_provider_event_callback *table = data;
799 if (!table->gbar.resize_move) {
800 return WIDGET_ERROR_NOT_SUPPORTED;
803 ret = table->gbar.resize_move(widget_util_uri_to_path(arg->id), arg->info.gbar_move.w, arg->info.gbar_move.h, arg->info.gbar_move.x, arg->info.gbar_move.y, table->data);
805 ret = WIDGET_ERROR_NOT_SUPPORTED;
806 #endif /* WIDGET_FEATURE_GBAR_SUPPORTED */
810 static int method_widget_pause(struct widget_event_arg *arg, void *data)
812 struct widget_provider_event_callback *table = data;
816 inst = instance_find(arg->id);
818 return WIDGET_ERROR_INVALID_PARAMETER;
821 if (inst->paused == 1) {
822 DbgPrint("Already paused\n");
823 return WIDGET_ERROR_ALREADY_EXIST;
828 if (s_info.paused == 1) {
829 return WIDGET_ERROR_NONE;
832 if (inst->update_timer) {
833 util_timer_freeze(inst->update_timer);
837 return WIDGET_ERROR_NOT_SUPPORTED;
840 ret = table->pause(widget_util_uri_to_path(arg->id), table->data);
844 static int method_widget_resume(struct widget_event_arg *arg, void *data)
846 struct widget_provider_event_callback *table = data;
850 inst = instance_find(arg->id);
852 return WIDGET_ERROR_INVALID_PARAMETER;
855 if (inst->paused == 0) {
856 return WIDGET_ERROR_ALREADY_EXIST;
861 if (s_info.paused == 1) {
862 return WIDGET_ERROR_NONE;
865 if (inst->update_timer) {
866 util_timer_thaw(inst->update_timer);
869 if (!table->resume) {
870 return WIDGET_ERROR_NOT_SUPPORTED;
873 ret = table->resume(widget_util_uri_to_path(arg->id), table->data);
877 static int connection_disconnected_cb(int handle, void *data)
879 struct connection *connection;
880 struct connection *conn_handle;
886 connection = connection_find_by_fd(handle);
891 EINA_LIST_FOREACH(s_info.inst_list, l, inst) {
892 EINA_LIST_FOREACH_SAFE(inst->handle_list, k, n, conn_handle) {
893 if (conn_handle == connection) {
896 * This instance has connection to client
897 * but now it is lost.
899 * the provider_app_send_updated function will send event to the master.
901 DbgPrint("Disconnected: %s\n", inst->id);
904 * To prevent from nested callback call.
905 * reset handle first.
907 inst->handle_list = eina_list_remove(inst->handle_list, conn_handle);
909 (void)connection_unref(conn_handle);
917 void client_fini(void)
919 struct internal_item *item;
921 if (!s_info.initialized) {
922 LOGE("Provider is not initialized\n");
926 DbgPrint("Finalize the Provider App Connection\n");
927 s_info.initialized = 0;
929 widget_provider_fini();
931 DbgPrint("Provider is disconnected(%s)\n", s_info.abi);
934 free(s_info.hw_acceleration);
941 s_info.hw_acceleration = NULL;
943 connection_del_event_handler(CONNECTION_EVENT_TYPE_DISCONNECTED, connection_disconnected_cb);
945 EINA_LIST_FREE(s_info.internal_item_list, item) {
946 DbgPrint("Internal item[%s] destroyed\n", item->id);
952 int client_is_initialized(void)
954 return s_info.initialized;
957 static int method_connected_sync(struct widget_event_arg *arg, void *data)
960 struct widget_provider_event_callback *table = data;
965 * hello_sync will invoke the widget_create funcion from its inside.
966 * So we should to call the connected event callback first.
967 * We should keep callback sequence.
969 * connected -> widget_created
972 if (table->connected) {
973 table->connected(table->data);
976 ret = widget_provider_send_hello_sync(provider_pkgname());
979 s_info.ping_timer = ecore_timer_add(WIDGET_CONF_DEFAULT_PING_TIME / 2.0f, send_ping_cb, NULL);
980 if (!s_info.ping_timer) {
981 ErrPrint("Failed to add a ping timer\n");
985 return WIDGET_ERROR_NONE;
988 static int is_watchapp(void)
991 pkgmgrinfo_appinfo_h handle = NULL;
994 if (pkgmgrinfo_appinfo_get_appinfo(provider_pkgname(), &handle) != PMINFO_R_OK) {
995 ErrPrint("appid[%s] is invalid\n", provider_pkgname());
999 if (pkgmgrinfo_appinfo_get_component_type(handle, &value) == PMINFO_R_OK) {
1001 DbgPrint("component type: %s\n", value);
1004 if (!strcmp(value, PKGMGR_COMPONENT_TYPE_WATCH_APP)) {
1006 DbgPrint("this app is watch app");
1010 pkgmgrinfo_appinfo_destroy_appinfo(handle);
1015 int client_init_sync(struct widget_provider_event_callback *table)
1020 char *hw_acceleration = NULL;
1022 struct widget_event_table method_table = {
1023 .widget_create = method_new,
1024 .widget_recreate = method_renew,
1025 .widget_destroy = method_delete,
1026 .resize = method_resize,
1027 .update_content = method_update_content,
1028 .content_event = method_content_event,
1029 .clicked = method_clicked,
1030 .text_signal = method_text_signal,
1031 .set_period = method_set_period,
1032 .change_group = method_change_group,
1033 .pinup = method_pinup,
1034 .pause = method_pause,
1035 .resume = method_resume,
1036 .widget_pause = method_widget_pause,
1037 .widget_resume = method_widget_resume,
1038 .disconnected = method_disconnected,
1039 .connected = method_connected_sync,
1040 .viewer_connected = method_viewer_connected,
1041 .viewer_disconnected = method_viewer_disconnected,
1046 .gbar_create = method_gbar_created,
1047 .gbar_destroy = method_gbar_destroyed,
1048 .gbar_move = method_gbar_moved,
1051 if (s_info.initialized == 1) {
1052 DbgPrint("Provider App is already initialized\n");
1053 return WIDGET_ERROR_NONE;
1058 if (s_info.name && s_info.abi) {
1059 DbgPrint("Name and ABI is assigned already\n");
1061 return WIDGET_ERROR_NONE;
1064 if (!widget_conf_is_loaded()) {
1065 widget_conf_reset();
1066 if (widget_conf_load() < 0) {
1067 ErrPrint("Failed to load conf\n");
1071 if (!is_watchapp()) {
1072 ErrPrint("This Provider is not watch app\n");
1073 widget_conf_reset();
1075 return WIDGET_ERROR_NONE;
1078 name = malloc(BUFFER_MAX);
1080 widget_conf_reset();
1082 return WIDGET_ERROR_OUT_OF_MEMORY;
1085 snprintf(name, BUFFER_MAX - 1, "%d.%lf", getpid(), util_timestamp());
1087 abi = strdup("app");
1090 widget_conf_reset();
1092 return WIDGET_ERROR_OUT_OF_MEMORY;
1095 hw_acceleration = strdup("use-sw");
1096 if (!hw_acceleration) {
1099 widget_conf_reset();
1101 return WIDGET_ERROR_OUT_OF_MEMORY;
1104 DbgPrint("Name assigned: %s (%s)\n", name, abi);
1105 DbgPrint("Secured: %s\n", "true");
1106 DbgPrint("hw-acceleration: %s\n", hw_acceleration);
1108 widget_provider_prepare_init(abi, hw_acceleration, 1);
1109 ret = widget_provider_init(util_screen_get(), name, &method_table, table, 1, 1);
1110 ErrPrint("widget_provider_init return [%d]\n", ret);
1112 free(hw_acceleration);
1115 widget_conf_reset();
1118 s_info.initialized = 1;
1122 s_info.hw_acceleration = hw_acceleration;
1124 if (connection_add_event_handler(CONNECTION_EVENT_TYPE_DISCONNECTED, connection_disconnected_cb, NULL) < 0) {
1125 ErrPrint("Failed to add a disconnected event callback\n");
1129 return WIDGET_ERROR_NONE;
1132 int client_init(app_control_h service, struct widget_provider_event_callback *table)
1135 char *secured = NULL;
1138 char *hw_acceleration = NULL;
1139 struct widget_event_table method_table = {
1140 .widget_create = method_new,
1141 .widget_recreate = method_renew,
1142 .widget_destroy = method_delete,
1143 .gbar_create = method_gbar_created,
1144 .gbar_destroy = method_gbar_destroyed,
1145 .gbar_move = method_gbar_moved,
1146 .resize = method_resize,
1147 .update_content = method_update_content,
1148 .content_event = method_content_event,
1149 .clicked = method_clicked,
1150 .text_signal = method_text_signal,
1151 .set_period = method_set_period,
1152 .change_group = method_change_group,
1153 .pinup = method_pinup,
1154 .pause = method_pause,
1155 .resume = method_resume,
1156 .widget_pause = method_widget_pause,
1157 .widget_resume = method_widget_resume,
1158 .disconnected = method_disconnected,
1159 .connected = method_connected,
1160 .viewer_connected = method_viewer_connected,
1161 .viewer_disconnected = method_viewer_disconnected,
1164 if (s_info.initialized == 1) {
1165 DbgPrint("Provider App is already initialized\n");
1166 return WIDGET_ERROR_NONE;
1171 if (s_info.name && s_info.abi) {
1172 DbgPrint("Name and ABI is assigned already\n");
1174 return WIDGET_ERROR_NONE;
1177 if (!widget_conf_is_loaded()) {
1178 widget_conf_reset();
1179 if (widget_conf_load() < 0) {
1180 ErrPrint("Failed to load conf\n");
1184 ret = app_control_get_extra_data(service, WIDGET_CONF_BUNDLE_SLAVE_NAME, &name);
1185 if (ret != APP_CONTROL_ERROR_NONE) {
1186 ErrPrint("Name is not valid\n");
1187 widget_conf_reset();
1189 return WIDGET_ERROR_INVALID_PARAMETER;
1192 ret = app_control_get_extra_data(service, WIDGET_CONF_BUNDLE_SLAVE_SECURED, &secured);
1193 if (ret != APP_CONTROL_ERROR_NONE) {
1195 ErrPrint("Secured is not valid\n");
1196 widget_conf_reset();
1198 return WIDGET_ERROR_INVALID_PARAMETER;
1201 ret = app_control_get_extra_data(service, WIDGET_CONF_BUNDLE_SLAVE_ABI, &abi);
1202 if (ret != APP_CONTROL_ERROR_NONE) {
1205 widget_conf_reset();
1207 return WIDGET_ERROR_INVALID_PARAMETER;
1210 ret = app_control_get_extra_data(service, WIDGET_CONF_BUNDLE_SLAVE_HW_ACCELERATION, &hw_acceleration);
1211 if (ret != APP_CONTROL_ERROR_NONE) {
1212 DbgPrint("hw-acceleration is not set\n");
1215 if (name && abi && secured) {
1216 DbgPrint("Name assigned: %s (%s)\n", name, abi);
1217 DbgPrint("Secured: %s\n", s_info.secured);
1218 DbgPrint("hw-acceleration: %s\n", hw_acceleration);
1220 widget_provider_prepare_init(abi, hw_acceleration, !strcmp(secured, "true"));
1221 ret = widget_provider_init(util_screen_get(), name, &method_table, table, 1, 1);
1225 widget_conf_reset();
1228 s_info.initialized = 1;
1231 s_info.secured = !strcasecmp(secured, "true");
1232 s_info.hw_acceleration = hw_acceleration;
1234 if (connection_add_event_handler(CONNECTION_EVENT_TYPE_DISCONNECTED, connection_disconnected_cb, NULL) < 0) {
1235 ErrPrint("Failed to add a disconnected event callback\n");
1243 free(hw_acceleration);
1244 widget_conf_reset();
1246 ret = WIDGET_ERROR_INVALID_PARAMETER;
1252 PAPI int widget_provider_app_send_updated_event(const char *id, int idx, int x, int y, int w, int h, int for_gbar)
1256 int ret = WIDGET_ERROR_DISABLED;
1257 char *desc_name = NULL;
1258 widget_damage_region_s region = {
1266 return WIDGET_ERROR_INVALID_PARAMETER;
1269 uri = util_path_to_uri(id);
1271 return WIDGET_ERROR_OUT_OF_MEMORY;
1277 len = strlen(id) + strlen(".desc") + 3;
1278 desc_name = malloc(len);
1281 return WIDGET_ERROR_OUT_OF_MEMORY;
1283 snprintf(desc_name, len, "%s.desc", id);
1287 * Do we have to search instance in this function?
1288 * This function is very frequently called one.
1289 * So we have to do not heavy operation in here!!!
1292 inst = instance_find(uri);
1293 if (inst && inst->handle_list) {
1295 struct connection *conn_handle;
1297 EINA_LIST_FOREACH(inst->handle_list, l, conn_handle) {
1298 ret = widget_provider_send_direct_updated(connection_handle(conn_handle), provider_pkgname(), uri, idx, ®ion, for_gbar, desc_name);
1304 * Even if we lost direct connection to the viewer,
1305 * we will send this to the master again.
1307 if (ret != WIDGET_ERROR_NONE) {
1308 ret = widget_provider_send_updated(provider_pkgname(), uri, idx, ®ion, for_gbar, desc_name);
1317 PAPI int widget_provider_app_send_buffer_updated_event(widget_buffer_h handle, int idx, int x, int y, int w, int h, int for_gbar)
1320 int ret = WIDGET_ERROR_DISABLED;
1321 char *desc_name = NULL;
1323 widget_damage_region_s region = {
1331 return WIDGET_ERROR_INVALID_PARAMETER;
1334 uri = widget_provider_buffer_id(handle);
1336 return WIDGET_ERROR_INVALID_PARAMETER;
1343 id = widget_util_uri_to_path(uri);
1345 return WIDGET_ERROR_FAULT;
1348 len = strlen(id) + strlen(".desc") + 3;
1349 desc_name = malloc(len);
1351 return WIDGET_ERROR_OUT_OF_MEMORY;
1353 snprintf(desc_name, len, "%s.desc", id);
1357 * Do we have to search instance in this function?
1358 * This function is very frequently called one.
1359 * So we have to do not heavy operation in here!!!
1362 inst = instance_find(uri);
1363 if (inst && inst->handle_list) {
1365 struct connection *conn_handle;
1367 EINA_LIST_FOREACH(inst->handle_list, l, conn_handle) {
1368 ret = widget_provider_send_direct_buffer_updated(connection_handle(conn_handle), handle, idx, ®ion, for_gbar, desc_name);
1374 * Even if we lost direct connection to the viewer,
1375 * we will send this to the master again.
1377 if (ret != WIDGET_ERROR_NONE) {
1378 ret = widget_provider_send_buffer_updated(handle, idx, ®ion, for_gbar, desc_name);
1386 PAPI int widget_provider_app_send_extra_info(const char *id, const char *content_info, const char *title)
1392 return WIDGET_ERROR_INVALID_PARAMETER;
1395 uri = util_path_to_uri(id);
1397 return WIDGET_ERROR_OUT_OF_MEMORY;
1400 ret = widget_provider_send_extra_info(provider_pkgname(), uri, 1.0f, content_info, title, NULL, NULL);
1406 PAPI int widget_provider_app_set_data(const char *id, void *data)
1411 return WIDGET_ERROR_INVALID_PARAMETER;
1414 uri = util_path_to_uri(id);
1416 return WIDGET_ERROR_OUT_OF_MEMORY;
1419 if (!strncmp(uri, SCHEMA_INTERNAL, strlen(SCHEMA_INTERNAL))) {
1420 struct internal_item *item;
1422 item = internal_item_find(uri);
1426 return WIDGET_ERROR_NOT_EXIST;
1429 item = internal_item_create(uri);
1432 return WIDGET_ERROR_FAULT;
1438 internal_item_destroy(item);
1439 return WIDGET_ERROR_NONE;
1447 item = instance_find(uri);
1450 return WIDGET_ERROR_ALREADY_EXIST;
1456 return WIDGET_ERROR_NONE;
1459 PAPI void *widget_provider_app_get_data(const char *id)
1468 uri = util_path_to_uri(id);
1473 if (!strncmp(uri, SCHEMA_INTERNAL, strlen(SCHEMA_INTERNAL))) {
1474 struct internal_item *item;
1476 item = internal_item_find(uri);
1485 item = instance_find(uri);
1496 PAPI void *widget_provider_app_get_data_list(void)
1499 Eina_List *return_list = NULL;
1502 EINA_LIST_FOREACH(s_info.inst_list, l, item) {
1503 return_list = eina_list_append(return_list, item->data);
1509 PAPI int widget_provider_app_create_app(void)
1511 return WIDGET_ERROR_NONE;
1514 PAPI int widget_provider_app_terminate_app(widget_destroy_type_e reason, int destroy_instances)
1516 struct widget_provider_event_callback *table;
1522 DbgPrint("Reason: %d, %d\n", reason, destroy_instances);
1524 if (!destroy_instances) {
1525 DbgPrint("Do not destroy instances\n");
1526 return WIDGET_ERROR_NONE;
1529 table = widget_provider_callback_data();
1531 ErrPrint("Provider App is not initialized\n");
1532 return WIDGET_ERROR_FAULT;
1535 EINA_LIST_FOREACH_SAFE(s_info.inst_list, l, n, item) {
1536 invoke_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, item->id);
1538 if (table->destroy) {
1539 (void)table->destroy(widget_util_uri_to_path(item->id), reason, table->data);
1542 instance_destroy(item);
1546 DbgPrint("%d instances are destroyed\n", ret);
1548 return ret ? WIDGET_ERROR_NONE : WIDGET_ERROR_NOT_EXIST;
1551 EAPI int widget_provider_app_add_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
1553 struct pre_callback_item *item;
1556 if (!cb || type == WIDGET_PRE_CALLBACK_COUNT) {
1557 return WIDGET_ERROR_INVALID_PARAMETER;
1560 EINA_LIST_FOREACH(s_info.widget_pre_callback_list[type], l, item) {
1561 if (item->cb == cb && item->data == data) {
1562 return WIDGET_ERROR_ALREADY_EXIST;
1566 item = malloc(sizeof(*item));
1568 ErrPrint("malloc: %s\n", strerror(errno));
1569 return WIDGET_ERROR_OUT_OF_MEMORY;
1575 s_info.widget_pre_callback_list[type] = eina_list_append(s_info.widget_pre_callback_list[type], item);
1579 EAPI int widget_provider_app_del_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
1583 struct pre_callback_item *item;
1585 if (!cb || type == WIDGET_PRE_CALLBACK_COUNT) {
1586 ErrPrint("Invalid parameter\n");
1587 return WIDGET_ERROR_INVALID_PARAMETER;
1590 EINA_LIST_FOREACH_SAFE(s_info.widget_pre_callback_list[type], l, n, item) {
1591 if (item->cb == cb && item->data == data) {
1592 s_info.widget_pre_callback_list[type] = eina_list_remove_list(s_info.widget_pre_callback_list[type], l);
1594 return WIDGET_ERROR_NONE;
1598 return WIDGET_ERROR_NOT_EXIST;