2 * Copyright (c) 2016 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.
17 #include <sys/types.h>
18 #include <sys/socket.h>
26 #include <linux/limits.h>
28 #include <Ecore_Wayland.h>
29 #include <wayland-client.h>
30 #include <wayland-tbm-client.h>
31 #include <tizen-extension-client-protocol.h>
34 #include <Ecore_Evas.h>
35 #include <Ecore_Input_Evas.h>
36 #include <Elementary.h>
37 #include <glib-object.h>
44 #include <bundle_internal.h>
46 #include <voice_control_elm.h>
47 #include <voice_control_elm_private.h>
49 #include "appcore_base.h"
50 #include "appcore_ui_base.h"
51 #include "appcore_ui_base_private.h"
52 #include "appcore_ui_plugin.h"
62 typedef struct _appcore_ui_base_context {
63 appcore_ui_base_ops ops;
72 Ecore_Event_Handler *hshow;
73 Ecore_Event_Handler *hhide;
74 Ecore_Event_Handler *hvchange;
75 Ecore_Event_Handler *hlower;
76 } appcore_ui_base_context;
79 static bool b_active = false;
80 static bool first_launch = true;
88 static GSList *g_winnode_list;
89 static appcore_ui_base_context __context;
90 static struct wl_display *dsp;
91 static struct wl_registry *reg;
92 static struct tizen_policy *tz_policy;
93 static bool bg_state = false;
95 static void __wl_listener_cb(void *data, struct wl_registry *reg,
96 uint32_t id, const char *interface, uint32_t ver)
98 if (interface && !strcmp(interface, "tizen_policy")) {
100 tz_policy = wl_registry_bind(reg, id,
101 &tizen_policy_interface, 1);
105 static void __wl_listener_remove_cb(void *data, struct wl_registry *reg,
111 static const struct wl_registry_listener reg_listener = {
113 __wl_listener_remove_cb
116 static Eina_Bool __stub_show_cb(void *data, int type, void *event)
118 if (__context.ops.window.show)
119 __context.ops.window.show(type, event, __context.data);
121 return ECORE_CALLBACK_RENEW;
124 static Eina_Bool __stub_hide_cb(void *data, int type, void *event)
126 if (__context.ops.window.hide)
127 __context.ops.window.hide(type, event, __context.data);
129 return ECORE_CALLBACK_RENEW;
132 static Eina_Bool __stub_visibility_cb(void *data, int type, void *event)
134 if (__context.ops.window.visibility)
135 __context.ops.window.visibility(type, event, __context.data);
137 return ECORE_CALLBACK_RENEW;
140 static Eina_Bool __stub_lower_cb(void *data, int type, void *event)
142 if (__context.ops.window.lower)
143 __context.ops.window.lower(type, event, __context.data);
145 return ECORE_CALLBACK_RENEW;
148 static void __prepare_to_suspend(void)
150 int suspend = APPCORE_BASE_SUSPENDED_STATE_WILL_ENTER_SUSPEND;
152 if (appcore_base_is_bg_allowed() && !appcore_base_is_suspended()) {
153 appcore_base_raise_event((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
154 appcore_base_toggle_suspended_state();
158 static void __exit_from_suspend(void)
160 int suspend = APPCORE_BASE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
162 if (appcore_base_is_suspended()) {
163 appcore_base_raise_event((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
164 appcore_base_toggle_suspended_state();
168 static void __do_pause(void)
170 if (__context.state == AS_RUNNING) {
171 if (__context.ops.pause) {
172 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PAUSE");
173 __context.ops.pause(__context.data);
174 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
177 __context.state = AS_PAUSED;
178 __prepare_to_suspend();
180 aul_status_update(STATUS_BG);
183 static void __do_resume(void)
185 if (__context.state == AS_PAUSED || __context.state == AS_CREATED) {
186 __exit_from_suspend();
187 if (__context.ops.resume) {
188 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]", __context.appid);
189 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESUME");
190 __context.ops.resume(__context.data);
191 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
192 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]", __context.appid);
193 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:Launching:done]", __context.appid);
195 if ((__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL) &&
196 __context.below_app) {
197 aul_app_group_activate_below(__context.below_app);
198 free(__context.below_app);
199 __context.below_app = NULL;
201 __context.state = AS_RUNNING;
204 aul_status_update(STATUS_VISIBLE);
207 static GSList *__find_win(unsigned int win)
212 for (iter = g_winnode_list; iter; iter = g_slist_next(iter)) {
214 if (t && t->win == win)
221 static int __get_main_window(void)
223 struct win_node *entry = NULL;
225 if (g_winnode_list != NULL) {
226 entry = g_winnode_list->data;
227 return (unsigned int) entry->win;
233 static int __get_main_surface(void)
235 struct win_node *entry = NULL;
237 if (g_winnode_list != NULL) {
238 entry = g_winnode_list->data;
239 return (unsigned int) entry->surf;
245 static bool __add_win(unsigned int win, unsigned int surf)
250 _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
255 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
259 t = calloc(1, sizeof(struct win_node));
265 t->bfobscured = FALSE;
267 g_winnode_list = g_slist_append(g_winnode_list, t);
272 static bool __delete_win(unsigned int win)
279 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n",
285 g_winnode_list = g_slist_delete_link(g_winnode_list, f);
290 static bool __update_win(unsigned int win, unsigned int surf, bool bfobscured)
295 _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
301 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
305 t = (struct win_node *)f->data;
309 t->bfobscured = bfobscured;
314 static void __raise_win(void)
316 Ecore_Wl_Window *win;
319 if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL))
322 win_id = __get_main_window();
324 _DBG("Raise window: %d", win_id);
325 win = ecore_wl_window_find(win_id);
326 ecore_wl_window_activate(win);
329 static void __pause_win(void)
331 Ecore_Wl_Window *win;
332 GSList *wlist = g_winnode_list;
333 struct win_node *entry = NULL;
335 if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL))
338 _DBG("Pause window");
343 _DBG("Pause window: %d", entry->win);
344 win = ecore_wl_window_find(entry->win);
345 ecore_wl_window_iconified_set(win, EINA_TRUE);
351 static int __init_wl(void)
353 _DBG("initialize wayland");
354 dsp = wl_display_connect(NULL);
356 _ERR("Failed to connect wl display");
360 reg = wl_display_get_registry(dsp);
362 _ERR("Failed to get registry");
363 wl_display_disconnect(dsp);
367 wl_registry_add_listener(reg, ®_listener, NULL);
368 wl_display_roundtrip(dsp);
371 _ERR("Failed to get tizen policy interface");
372 wl_registry_destroy(reg);
373 wl_display_disconnect(dsp);
380 static void __finish_wl(void)
383 tizen_policy_destroy(tz_policy);
388 wl_registry_destroy(reg);
393 wl_display_disconnect(dsp);
398 static void __set_bg_state(void)
400 if (!tz_policy && __init_wl() < 0)
403 tizen_policy_set_background_state(tz_policy, getpid());
404 wl_display_roundtrip(dsp);
406 _DBG("bg state: %d", bg_state);
409 static void __unset_bg_state(void)
414 tizen_policy_unset_background_state(tz_policy, getpid());
415 wl_display_roundtrip(dsp);
417 _DBG("bg state: %d", bg_state);
420 static void __do_start(bundle *b)
422 const char *bg_launch;
423 const char *below_app;
425 if (__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL) {
426 if (__context.below_app) {
427 free(__context.below_app);
428 __context.below_app = NULL;
431 below_app = bundle_get_val(b, AUL_SVC_K_RELOCATE_BELOW);
433 __context.below_app = strdup(below_app);
437 first_launch = FALSE;
441 if (__context.hint & APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL) {
442 bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
443 if (bg_launch && strcmp(bg_launch, "enable") == 0) {
444 if (!bg_state && __context.state != AS_RUNNING)
452 if (__context.hint & APPCORE_UI_BASE_HINT_WINDOW_AUTO_CONTROL) {
458 EXPORT_API int appcore_ui_base_on_receive(aul_type type, bundle *b)
460 if (__context.state == AS_DYING) {
461 _ERR("Skip the event in dying state");
465 if (type == AUL_TERMINATE_BGAPP && __context.state != AS_PAUSED)
468 if (type == AUL_START)
469 __exit_from_suspend();
471 appcore_base_on_receive(type, b);
484 case AUL_TERMINATE_BGAPP:
485 _DBG("[APP %d] is paused. TERMINATE", getpid());
486 __context.state = AS_DYING;
487 aul_status_update(STATUS_DYING);
488 if (__context.ops.base.exit)
489 __context.ops.base.exit(__context.data);
501 EXPORT_API int appcore_ui_base_on_create(void)
503 appcore_base_on_create();
505 __context.hshow = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_SHOW, __stub_show_cb, NULL);
506 __context.hhide = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_HIDE, __stub_hide_cb, NULL);
507 __context.hvchange = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
508 __stub_visibility_cb, NULL);
509 __context.hlower = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_LOWER, __stub_lower_cb, NULL);
510 __context.state = AS_CREATED;
511 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]", __context.appid);
516 EXPORT_API int appcore_ui_base_on_terminate(void)
518 if (__context.state == AS_RUNNING) {
519 if (__context.ops.pause)
520 __context.ops.pause(__context.data);
523 __context.state = AS_DYING;
525 appcore_base_on_terminate();
530 EXPORT_API int appcore_ui_base_on_pause(void)
535 EXPORT_API int appcore_ui_base_on_resume(void)
540 EXPORT_API int appcore_ui_base_on_control(bundle *b)
542 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]", __context.appid);
543 appcore_base_on_control(b);
544 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]", __context.appid);
549 static void __group_attach()
551 if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL))
554 appcore_ui_base_group_add();
557 static void __group_lower()
559 if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL))
561 appcore_ui_base_group_remove();
564 EXPORT_API void appcore_ui_base_group_add()
566 static bool attached = false;
568 _DBG("__group_attach");
572 int wid = __get_main_surface();
574 _ERR("window wasn't ready");
578 aul_app_group_set_window(wid);
582 EXPORT_API void appcore_ui_base_group_remove()
586 _DBG("__group_lower");
587 aul_app_group_lower(&exit);
589 _DBG("__group_lower : sub-app!");
590 if (__context.ops.base.exit)
591 __context.ops.base.exit(__context.data);
595 EXPORT_API void appcore_ui_base_window_on_show(int type, void *event)
597 Ecore_Wl_Event_Window_Show *ev;
600 if (ev->parent_win != 0) {
601 /* This is child window. Skip!!! */
605 _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x, %d\n", ev->win, ev->data[0]);
607 if (!__find_win((unsigned int)ev->win))
608 __add_win((unsigned int)ev->win, (unsigned int)ev->data[0]);
610 __update_win((unsigned int)ev->win, (unsigned int)ev->data[0], FALSE);
612 if (ev->data[0] != 0)
616 static bool __check_visible(void)
619 struct win_node *entry = NULL;
621 _DBG("[EVENT_TEST][EVENT] __check_visible\n");
623 for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
625 _DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
626 if (entry->bfobscured == FALSE)
633 EXPORT_API void appcore_ui_base_window_on_hide(int type, void *event)
635 Ecore_Wl_Event_Window_Hide *ev;
639 _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
641 if (__find_win((unsigned int)ev->win)) {
642 __delete_win((unsigned int)ev->win);
643 bvisibility = __check_visible();
644 if (!bvisibility && b_active == TRUE) {
645 _DBG(" Go to Pasue state \n");
652 EXPORT_API void appcore_ui_base_window_on_lower(int type, void *event)
654 Ecore_Wl_Event_Window_Lower *ev;
659 _DBG("ECORE_WL_EVENT_WINDOW_LOWER window id:%u\n", ev->win);
663 EXPORT_API void appcore_ui_base_window_on_visibility(int type, void *event)
665 Ecore_Wl_Event_Window_Visibility_Change *ev;
669 __update_win((unsigned int)ev->win, 0, ev->fully_obscured);
670 bvisibility = __check_visible();
672 _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
674 if (bvisibility && b_active == FALSE) {
675 _DBG(" Go to Resume state\n");
678 } else if (!bvisibility && b_active == TRUE) {
679 _DBG(" Go to Pasue state \n");
683 _DBG(" No change state \n");
688 EXPORT_API int appcore_ui_base_init(appcore_ui_base_ops ops, int argc, char **argv,
689 void *data, unsigned int hint)
692 const char *bg_launch;
694 char appid[PATH_MAX] = {0, };
696 bool is_vc_vt_automode = false;
698 appcore_ui_plugin_init(&ops, argc, argv, &hint);
699 aul_app_get_appid_bypid(getpid(), appid, sizeof(appid));
701 __context.data = data;
702 __context.argc = argc;
703 __context.argv = argv;
704 __context.hint = hint;
705 __context.state = AS_NONE;
706 __context.appid = strdup(appid);
708 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", appid);
709 elm_init(argc, argv);
711 r = vc_elm_is_supported_vt_auto(&is_vc_vt_automode);
713 _ERR("[VC] Fail to get vconfkey of vt_automode");
715 if (is_vc_vt_automode == true) {
717 vc_elm_set_auto_register_mode(2, 0);
721 if (__context.hint & APPCORE_UI_BASE_HINT_HW_ACC_CONTROL) {
722 hwacc = getenv("HWACC");
725 _DBG("elm_config_accel_preference_set is not called");
726 } else if (strcmp(hwacc, "USE") == 0) {
727 elm_config_accel_preference_set("hw");
728 _DBG("elm_config_accel_preference_set : hw");
729 } else if (strcmp(hwacc, "NOT_USE") == 0) {
730 elm_config_accel_preference_set("none");
731 _DBG("elm_config_accel_preference_set : none");
733 _DBG("elm_config_accel_preference_set is not called");
737 if (__context.hint & APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL) {
738 b = bundle_import_from_argv(argc, argv);
740 bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
741 if (bg_launch && strcmp(bg_launch, "enable") == 0)
748 return appcore_base_init(ops.base, argc, argv, data);
751 EXPORT_API void appcore_ui_base_fini(void)
753 bool is_vc_vt_automode = false;
757 appcore_ui_plugin_fini();
760 ecore_event_handler_del(__context.hshow);
762 ecore_event_handler_del(__context.hhide);
763 if (__context.hvchange)
764 ecore_event_handler_del(__context.hvchange);
765 if (__context.hlower)
766 ecore_event_handler_del(__context.hlower);
770 r = vc_elm_is_supported_vt_auto(&is_vc_vt_automode);
772 _ERR("[VC] Fail to get vconfkey of vt_automode");
774 if (is_vc_vt_automode == true)
775 vc_elm_deinitialize();
780 /* Check loader case */
781 if (getenv("AUL_LOADER_INIT")) {
782 unsetenv("AUL_LOADER_INIT");
786 free(__context.appid);
787 __context.appid = NULL;
790 EXPORT_API void appcore_ui_base_pause(void)
795 EXPORT_API void appcore_ui_base_resume(void)
800 EXPORT_API bool appcore_ui_base_is_resumed(void)
802 return __context.state == AS_RUNNING;
805 EXPORT_API void appcore_ui_base_exit(void)
807 if (__context.ops.base.exit)
808 __context.ops.base.exit(__context.data);
811 EXPORT_API unsigned int appcore_ui_base_get_main_window(void)
813 return __get_main_window();
816 EXPORT_API unsigned int appcore_ui_base_get_main_surface(void)
818 return __get_main_surface();
821 static int __on_receive(aul_type type, bundle *b, void *data)
823 return appcore_ui_base_on_receive(type, b);
826 static int __on_create(void *data)
828 return appcore_ui_base_on_create();
831 static int __on_terminate(void *data)
833 return appcore_ui_base_on_terminate();
836 static int __on_pause(void *data)
838 return appcore_ui_base_on_pause();
841 static int __on_resume(void *data)
843 return appcore_ui_base_on_resume();
846 static void __window_on_show(int type, void *event, void *data)
848 appcore_ui_base_window_on_show(type, event);
851 static void __window_on_hide(int type, void *event, void *data)
853 appcore_ui_base_window_on_hide(type, event);
856 static void __window_on_lower(int type, void *event, void *data)
858 appcore_ui_base_window_on_lower(type, event);
861 static void __window_on_visibility(int type, void *event, void *data)
863 appcore_ui_base_window_on_visibility(type, event);
866 static void __run(void *data)
871 static void __exit(void *data)
876 EXPORT_API appcore_ui_base_ops appcore_ui_base_get_default_ops(void)
878 appcore_ui_base_ops ops;
880 ops.base = appcore_base_get_default_ops();
882 /* override methods */
883 ops.base.create = __on_create;
884 ops.base.terminate = __on_terminate;
885 ops.base.receive = __on_receive;
886 ops.base.run = __run;
887 ops.base.exit = __exit;
889 ops.pause = __on_pause;
890 ops.resume = __on_resume;
891 ops.window.show = __window_on_show;
892 ops.window.hide = __window_on_hide;
893 ops.window.lower = __window_on_lower;
894 ops.window.visibility = __window_on_visibility;