Support legacy lifecycle
[platform/core/appfw/app-core.git] / src / ui_base / appcore_ui_base.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
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 #define _GNU_SOURCE
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <sys/un.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <stdarg.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <linux/limits.h>
28
29 #include <Ecore_Wayland.h>
30 #include <wayland-client.h>
31 #include <wayland-tbm-client.h>
32 #include <tizen-extension-client-protocol.h>
33
34 #include <Ecore.h>
35 #include <glib-object.h>
36 #include <malloc.h>
37 #include <glib.h>
38 #include <gio/gio.h>
39 #include <stdbool.h>
40 #include <aul.h>
41 #include <aul_svc.h>
42 #include <bundle_internal.h>
43 #include <ttrace.h>
44
45 #include "appcore_base.h"
46 #include "appcore_ui_base.h"
47 #include "appcore_ui_base_private.h"
48 #include "appcore_ui_plugin.h"
49
50 enum app_state {
51         AS_NONE,
52         AS_CREATED,
53         AS_RUNNING,
54         AS_PAUSED,
55         AS_DYING,
56 };
57
58 typedef struct _appcore_ui_base_context {
59         appcore_ui_base_ops ops;
60         void *data;
61         int argc;
62         char **argv;
63         unsigned int hint;
64         char *below_app;
65         char *appid;
66         bool bg_state;
67
68         int state;
69         Ecore_Event_Handler *hshow;
70         Ecore_Event_Handler *hhide;
71         Ecore_Event_Handler *hvchange;
72         Ecore_Event_Handler *hlower;
73         Ecore_Event_Handler *hpvchange;
74 } appcore_ui_base_context;
75
76
77 static bool b_active = false;
78 static bool first_launch = true;
79
80 struct win_node {
81         unsigned int win;
82         unsigned int surf;
83         bool bfobscured;
84 };
85
86 static GSList *g_winnode_list;
87 static appcore_ui_base_context __context;
88 static struct wl_display *dsp;
89 static struct wl_registry *reg;
90 static struct tizen_policy *tz_policy;
91
92 static void __wl_listener_cb(void *data, struct wl_registry *reg,
93                 uint32_t id, const char *interface, uint32_t ver)
94 {
95         if (interface && !strcmp(interface, "tizen_policy")) {
96                 if (!tz_policy)
97                         tz_policy = wl_registry_bind(reg, id,
98                                         &tizen_policy_interface, 1);
99         }
100 }
101
102 static void __wl_listener_remove_cb(void *data, struct wl_registry *reg,
103                 unsigned int id)
104 {
105         /* do nothing */
106 }
107
108 static const struct wl_registry_listener reg_listener = {
109         __wl_listener_cb,
110         __wl_listener_remove_cb
111 };
112
113 static Eina_Bool __stub_show_cb(void *data, int type, void *event)
114 {
115         if (__context.ops.window.show)
116                 __context.ops.window.show(type, event, __context.data);
117
118         return ECORE_CALLBACK_RENEW;
119 }
120
121 static Eina_Bool __stub_hide_cb(void *data, int type, void *event)
122 {
123         if (__context.ops.window.hide)
124                 __context.ops.window.hide(type, event, __context.data);
125
126         return ECORE_CALLBACK_RENEW;
127 }
128
129 static Eina_Bool __stub_visibility_cb(void *data, int type, void *event)
130 {
131         if (__context.ops.window.visibility)
132                 __context.ops.window.visibility(type, event, __context.data);
133
134         return ECORE_CALLBACK_RENEW;
135 }
136
137 static Eina_Bool __stub_lower_cb(void *data, int type, void *event)
138 {
139         if (__context.ops.window.lower)
140                 __context.ops.window.lower(type, event, __context.data);
141
142         return ECORE_CALLBACK_RENEW;
143 }
144
145 static Eina_Bool __stub_pre_visibility_cb(void *data, int type, void *event)
146 {
147         if (__context.ops.window.pre_visibility)
148                 __context.ops.window.pre_visibility(type, event, __context.data);
149
150         return ECORE_CALLBACK_RENEW;
151 }
152
153 static void __prepare_to_suspend(void)
154 {
155         int suspend = APPCORE_BASE_SUSPENDED_STATE_WILL_ENTER_SUSPEND;
156
157         if (appcore_base_is_bg_allowed() && !appcore_base_is_suspended()) {
158                 appcore_base_raise_event((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
159                 appcore_base_toggle_suspended_state();
160         }
161 }
162
163 static void __exit_from_suspend(void)
164 {
165         int suspend = APPCORE_BASE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
166
167         if (appcore_base_is_suspended()) {
168                 appcore_base_raise_event((void *)&suspend, APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE);
169                 appcore_base_toggle_suspended_state();
170         }
171 }
172
173 static void __do_pause(void)
174 {
175         if (__context.state == AS_RUNNING) {
176                 if (__context.ops.pause) {
177                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PAUSE");
178                         __context.ops.pause(__context.data);
179                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
180                 }
181
182                 __context.state = AS_PAUSED;
183                 __prepare_to_suspend();
184         }
185         aul_status_update(STATUS_BG);
186 }
187
188 static void __do_resume(void)
189 {
190         if (__context.state == AS_PAUSED || __context.state == AS_CREATED) {
191                 __exit_from_suspend();
192                 if (__context.ops.resume) {
193                         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]", __context.appid);
194                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESUME");
195                         __context.ops.resume(__context.data);
196                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
197                         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]", __context.appid);
198                         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:Launching:done]", __context.appid);
199                 }
200                 if ((__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL) &&
201                                 __context.below_app) {
202                         aul_app_group_activate_below(__context.below_app);
203                         free(__context.below_app);
204                         __context.below_app = NULL;
205                 }
206                 __context.state = AS_RUNNING;
207         }
208
209         aul_status_update(STATUS_VISIBLE);
210 }
211
212 static GSList *__find_win(unsigned int win)
213 {
214         GSList *iter;
215         struct win_node *t;
216
217         for (iter = g_winnode_list; iter; iter = g_slist_next(iter)) {
218                 t = iter->data;
219                 if (t && t->win == win)
220                         return iter;
221         }
222
223         return NULL;
224 }
225
226 static int __get_main_window(void)
227 {
228         struct win_node *entry = NULL;
229
230         if (g_winnode_list != NULL) {
231                 entry = g_winnode_list->data;
232                 return (unsigned int) entry->win;
233         }
234
235         return 0;
236 }
237
238 static int __get_main_surface(void)
239 {
240         struct win_node *entry = NULL;
241
242         if (g_winnode_list != NULL) {
243                 entry = g_winnode_list->data;
244                 return (unsigned int) entry->surf;
245         }
246
247         return 0;
248 }
249
250 static bool __add_win(unsigned int win, unsigned int surf)
251 {
252         struct win_node *t;
253         GSList *f;
254
255         _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
256
257         f = __find_win(win);
258         if (f) {
259                 errno = ENOENT;
260                 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
261                 return FALSE;
262         }
263
264         t = calloc(1, sizeof(struct win_node));
265         if (t == NULL)
266                 return FALSE;
267
268         t->win = win;
269         t->surf = surf;
270         t->bfobscured = FALSE;
271
272         g_winnode_list = g_slist_append(g_winnode_list, t);
273
274         return TRUE;
275 }
276
277 static bool __delete_win(unsigned int win)
278 {
279         GSList *f;
280
281         f = __find_win(win);
282         if (!f) {
283                 errno = ENOENT;
284                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n",
285                                 win);
286                 return FALSE;
287         }
288
289         free(f->data);
290         g_winnode_list = g_slist_delete_link(g_winnode_list, f);
291
292         return TRUE;
293 }
294
295 static bool __update_win(unsigned int win, unsigned int surf, bool bfobscured)
296 {
297         GSList *f;
298         struct win_node *t;
299
300         _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
301              bfobscured);
302
303         f = __find_win(win);
304         if (!f) {
305                 errno = ENOENT;
306                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
307                 return FALSE;
308         }
309
310         t = (struct win_node *)f->data;
311         t->win = win;
312         if (surf != 0)
313                 t->surf = surf;
314         t->bfobscured = bfobscured;
315
316         return TRUE;
317 }
318
319 static void __raise_win(void)
320 {
321         Ecore_Wl_Window *win;
322         unsigned int win_id;
323
324         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL))
325                 return;
326
327         win_id = __get_main_window();
328
329         _DBG("Raise window: %d", win_id);
330         win = ecore_wl_window_find(win_id);
331         ecore_wl_window_activate(win);
332 }
333
334 static void __pause_win(void)
335 {
336         Ecore_Wl_Window *win;
337         GSList *wlist = g_winnode_list;
338         struct win_node *entry = NULL;
339
340         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL))
341                 return;
342
343         _DBG("Pause window");
344
345         while (wlist) {
346                 entry = wlist->data;
347
348                 _DBG("Pause window: %d", entry->win);
349                 win = ecore_wl_window_find(entry->win);
350                 ecore_wl_window_iconified_set(win, EINA_TRUE);
351
352                 wlist = wlist->next;
353         }
354 }
355
356 static int __init_wl(void)
357 {
358         _DBG("initialize wayland");
359         dsp = wl_display_connect(NULL);
360         if (dsp == NULL) {
361                 _ERR("Failed to connect wl display");
362                 return -1;
363         }
364
365         reg = wl_display_get_registry(dsp);
366         if (reg == NULL) {
367                 _ERR("Failed to get registry");
368                 wl_display_disconnect(dsp);
369                 return -1;
370         }
371
372         wl_registry_add_listener(reg, &reg_listener, NULL);
373         wl_display_roundtrip(dsp);
374
375         if (!tz_policy) {
376                 _ERR("Failed to get tizen policy interface");
377                 wl_registry_destroy(reg);
378                 wl_display_disconnect(dsp);
379                 return -1;
380         }
381
382         return 0;
383 }
384
385 static void __finish_wl(void)
386 {
387         if (tz_policy) {
388                 tizen_policy_destroy(tz_policy);
389                 tz_policy = NULL;
390         }
391
392         if (reg) {
393                 wl_registry_destroy(reg);
394                 reg = NULL;
395         }
396
397         if (dsp) {
398                 wl_display_disconnect(dsp);
399                 dsp = NULL;
400         }
401 }
402
403 static void __set_bg_state(void)
404 {
405         if (!tz_policy && __init_wl() < 0)
406                 return;
407
408         tizen_policy_set_background_state(tz_policy, getpid());
409         wl_display_roundtrip(dsp);
410         __context.bg_state = true;
411         _DBG("bg state: %d", __context.bg_state);
412 }
413
414 static void __unset_bg_state(void)
415 {
416         if (!tz_policy)
417                 return;
418
419         tizen_policy_unset_background_state(tz_policy, getpid());
420         wl_display_roundtrip(dsp);
421         __context.bg_state = false;
422         _DBG("bg state: %d", __context.bg_state);
423 }
424
425 static void __do_start(bundle *b)
426 {
427         const char *bg_launch;
428         const char *below_app;
429
430         if (__context.hint & APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL) {
431                 if (__context.below_app) {
432                         free(__context.below_app);
433                         __context.below_app = NULL;
434                 }
435
436                 below_app = bundle_get_val(b, AUL_SVC_K_RELOCATE_BELOW);
437                 if (below_app)
438                         __context.below_app = strdup(below_app);
439         }
440
441         if (first_launch) {
442                 first_launch = FALSE;
443                 return;
444         }
445
446         if (__context.hint & APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL) {
447                 bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
448                 if (bg_launch && strcmp(bg_launch, "enable") == 0) {
449                         if (!__context.bg_state &&
450                                         __context.state != AS_RUNNING)
451                                 __set_bg_state();
452                 } else {
453                         if (__context.bg_state)
454                                 __unset_bg_state();
455                 }
456         }
457
458         if (__context.hint & APPCORE_UI_BASE_HINT_WINDOW_AUTO_CONTROL) {
459                 if (!__context.bg_state)
460                         __raise_win();
461         }
462 }
463
464 static int __is_legacy_lifecycle(void)
465 {
466         static int is_legacy = -1;
467         const char *api_version;
468
469         if (is_legacy != -1)
470                 return is_legacy;
471
472         api_version = getenv("TIZEN_API_VERSION");
473         if (api_version) {
474                 if (strverscmp("2.4", api_version) > 0 &&
475                                 strverscmp("2.2.1", api_version) < 0)
476                         is_legacy = 1;
477                 else
478                         is_legacy = 0;
479         } else {
480                 is_legacy = 0;
481         }
482
483         return is_legacy;
484 }
485
486 EXPORT_API int appcore_ui_base_on_receive(aul_type type, bundle *b)
487 {
488         if (__context.state == AS_DYING) {
489                 _ERR("Skip the event in dying state");
490                 return 0;
491         }
492
493         if (type == AUL_TERMINATE_BGAPP && __context.state != AS_PAUSED)
494                 return 0;
495
496         if (type == AUL_START)
497                 __exit_from_suspend();
498
499         appcore_base_on_receive(type, b);
500
501         switch (type) {
502         case AUL_START:
503                 __do_start(b);
504                 if (__context.hint & APPCORE_UI_BASE_HINT_LEGACY_CONTROL) {
505                         if (!__context.bg_state && __is_legacy_lifecycle()) {
506                                 _DBG("Legacy lifecycle");
507                                 __do_resume();
508                         }
509                 }
510                 break;
511         case AUL_RESUME:
512                 if (__context.bg_state)
513                         __unset_bg_state();
514                 __raise_win();
515                 break;
516         case AUL_TERMINATE:
517                 break;
518         case AUL_TERMINATE_BGAPP:
519                 _DBG("[APP %d] is paused. TERMINATE", getpid());
520                 __context.state = AS_DYING;
521                 aul_status_update(STATUS_DYING);
522                 if (__context.ops.base.exit)
523                         __context.ops.base.exit(__context.data);
524                 break;
525         case AUL_PAUSE:
526                 __pause_win();
527                 break;
528         default:
529                 break;
530         }
531
532         return 0;
533 }
534
535 static void __add_ecore_events(void)
536 {
537         __context.hshow = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_SHOW,
538                         __stub_show_cb, NULL);
539         if (!__context.hshow)
540                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_SHOW event");
541
542         __context.hhide = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_HIDE,
543                         __stub_hide_cb, NULL);
544         if (!__context.hhide)
545                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_HIDE event");
546
547         __context.hvchange = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
548                         __stub_visibility_cb, NULL);
549         if (!__context.hvchange)
550                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE event");
551
552         __context.hlower = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_LOWER,
553                         __stub_lower_cb, NULL);
554         if (!__context.hlower)
555                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_LOWER event");
556
557         __context.hpvchange = ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_PRE_VISIBILITY_CHANGE,
558                         __stub_pre_visibility_cb, NULL);
559         if (!__context.hpvchange)
560                 _ERR("Failed to add ECORE_WL_EVENT_WINDOW_PRE_VISIBILITY_CHANGE event");
561 }
562
563 static void __del_ecore_events(void)
564 {
565         if (__context.hshow) {
566                 ecore_event_handler_del(__context.hshow);
567                 __context.hshow = NULL;
568         }
569
570         if (__context.hhide) {
571                 ecore_event_handler_del(__context.hhide);
572                 __context.hhide = NULL;
573         }
574
575         if (__context.hvchange) {
576                 ecore_event_handler_del(__context.hvchange);
577                 __context.hvchange = NULL;
578         }
579
580         if (__context.hlower) {
581                 ecore_event_handler_del(__context.hlower);
582                 __context.hlower = NULL;
583         }
584
585         if (__context.hpvchange) {
586                 ecore_event_handler_del(__context.hpvchange);
587                 __context.hpvchange = NULL;
588         }
589 }
590
591 EXPORT_API int appcore_ui_base_on_create(void)
592 {
593         __add_ecore_events();
594         appcore_base_on_create();
595         __context.state = AS_CREATED;
596         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]", __context.appid);
597
598         return 0;
599 }
600
601 EXPORT_API int appcore_ui_base_on_terminate(void)
602 {
603         if (__context.state == AS_RUNNING) {
604                 if (__context.ops.pause)
605                         __context.ops.pause(__context.data);
606         }
607
608         __context.state = AS_DYING;
609
610         appcore_base_on_terminate();
611
612         return 0;
613 }
614
615 EXPORT_API int appcore_ui_base_on_pause(void)
616 {
617         return 0;
618 }
619
620 EXPORT_API int appcore_ui_base_on_resume(void)
621 {
622         return 0;
623 }
624
625 EXPORT_API int appcore_ui_base_on_control(bundle *b)
626 {
627         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]", __context.appid);
628         appcore_base_on_control(b);
629         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]", __context.appid);
630
631         return 0;
632 }
633
634 static void __group_attach()
635 {
636         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL))
637                 return;
638
639         appcore_ui_base_group_add();
640 }
641
642 static void __group_lower()
643 {
644         if (!(__context.hint & APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL))
645                 return;
646         appcore_ui_base_group_remove();
647 }
648
649 EXPORT_API void appcore_ui_base_group_add()
650 {
651         static bool attached = false;
652
653         _DBG("__group_attach");
654         if (attached)
655                 return;
656
657         int wid = __get_main_surface();
658         if (wid == 0) {
659                 _ERR("window wasn't ready");
660                 return;
661         }
662
663         aul_app_group_set_window(wid);
664         attached = true;
665 }
666
667 EXPORT_API void appcore_ui_base_group_remove()
668 {
669         int exit = 0;
670
671         _DBG("__group_lower");
672         aul_app_group_lower(&exit);
673         if (exit) {
674                 _DBG("__group_lower : sub-app!");
675                 if (__context.ops.base.exit)
676                         __context.ops.base.exit(__context.data);
677         }
678 }
679
680 EXPORT_API void appcore_ui_base_window_on_show(int type, void *event)
681 {
682         Ecore_Wl_Event_Window_Show *ev;
683
684         ev = event;
685         if (ev->parent_win != 0) {
686                 /* This is child window. Skip!!! */
687                 return;
688         }
689
690         _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x, %d\n", ev->win, ev->data[0]);
691
692         if (!__find_win((unsigned int)ev->win))
693                 __add_win((unsigned int)ev->win, (unsigned int)ev->data[0]);
694         else
695                 __update_win((unsigned int)ev->win, (unsigned int)ev->data[0], FALSE);
696
697         if (ev->data[0] != 0)
698                 __group_attach();
699 }
700
701 static bool __check_visible(void)
702 {
703         GSList *iter = NULL;
704         struct win_node *entry = NULL;
705
706         _DBG("[EVENT_TEST][EVENT] __check_visible\n");
707
708         for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
709                 entry = iter->data;
710                 _DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
711                 if (entry->bfobscured == FALSE)
712                         return true;
713         }
714
715         return false;
716 }
717
718 EXPORT_API void appcore_ui_base_window_on_hide(int type, void *event)
719 {
720         Ecore_Wl_Event_Window_Hide *ev;
721         int bvisibility;
722
723         ev = event;
724         _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
725
726         if (__find_win((unsigned int)ev->win)) {
727                 __delete_win((unsigned int)ev->win);
728                 bvisibility = __check_visible();
729                 if (!bvisibility && b_active == TRUE) {
730                         _DBG(" Go to Pasue state \n");
731                         b_active = FALSE;
732                         __do_pause();
733                 }
734         }
735 }
736
737 EXPORT_API void appcore_ui_base_window_on_lower(int type, void *event)
738 {
739         Ecore_Wl_Event_Window_Lower *ev;
740
741         ev = event;
742         if (!ev)
743                 return;
744         _DBG("ECORE_WL_EVENT_WINDOW_LOWER window id:%u\n", ev->win);
745         __group_lower();
746 }
747
748 EXPORT_API void appcore_ui_base_window_on_visibility(int type, void *event)
749 {
750         Ecore_Wl_Event_Window_Visibility_Change *ev;
751         int bvisibility;
752
753         ev = event;
754         __update_win((unsigned int)ev->win, 0, ev->fully_obscured);
755         bvisibility = __check_visible();
756
757         _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
758
759         if (bvisibility && b_active == FALSE) {
760                 _DBG(" Go to Resume state\n");
761                 b_active = TRUE;
762                 __do_resume();
763         } else if (!bvisibility && b_active == TRUE) {
764                 _DBG(" Go to Pasue state \n");
765                 b_active = FALSE;
766                 __do_pause();
767         } else {
768                 _DBG(" No change state \n");
769         }
770
771 }
772
773 EXPORT_API void appcore_ui_base_window_on_pre_visibility(int type, void *event)
774 {
775         Ecore_Wl_Event_Window_Pre_Visibility_Change *ev = event;
776         bool bvisibility;
777
778         if (ev && ev->type == ECORE_WL_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED) {
779                 __update_win((unsigned int)ev->win, 0, false);
780                 bvisibility = __check_visible();
781
782                 _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
783                 if (bvisibility && b_active == FALSE) {
784                         _DBG(" Go to Resume state\n");
785                         b_active = TRUE;
786                         __do_resume();
787                 }
788         }
789 }
790
791 EXPORT_API int appcore_ui_base_init(appcore_ui_base_ops ops, int argc, char **argv,
792                 void *data, unsigned int hint)
793 {
794         const char *bg_launch;
795         bundle *b;
796         char appid[PATH_MAX] = {0, };
797
798         appcore_ui_plugin_init(&ops, argc, argv, &hint);
799         aul_app_get_appid_bypid(getpid(), appid, sizeof(appid));
800         __context.ops = ops;
801         __context.data = data;
802         __context.argc = argc;
803         __context.argv = argv;
804         __context.hint = hint;
805         __context.state = AS_NONE;
806         __context.appid = strdup(appid);
807
808         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", appid);
809         if (__context.hint & APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL) {
810                 b = bundle_import_from_argv(argc, argv);
811                 if (b) {
812                         bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
813                         if (bg_launch && strcmp(bg_launch, "enable") == 0)
814                                 __set_bg_state();
815
816                         bundle_free(b);
817                 }
818         }
819
820         return appcore_base_init(ops.base, argc, argv, data);
821 }
822
823 EXPORT_API void appcore_ui_base_fini(void)
824 {
825         __del_ecore_events();
826         __finish_wl();
827
828         free(__context.appid);
829         __context.appid = NULL;
830
831         appcore_ui_plugin_fini();
832         appcore_base_fini();
833 }
834
835 EXPORT_API void appcore_ui_base_pause(void)
836 {
837         __do_pause();
838 }
839
840 EXPORT_API void appcore_ui_base_resume(void)
841 {
842         __do_resume();
843 }
844
845 EXPORT_API bool appcore_ui_base_is_resumed(void)
846 {
847         return __context.state == AS_RUNNING;
848 }
849
850 EXPORT_API void appcore_ui_base_exit(void)
851 {
852         if (__context.ops.base.exit)
853                 __context.ops.base.exit(__context.data);
854 }
855
856 EXPORT_API unsigned int appcore_ui_base_get_main_window(void)
857 {
858         return __get_main_window();
859 }
860
861 EXPORT_API unsigned int appcore_ui_base_get_main_surface(void)
862 {
863         return __get_main_surface();
864 }
865
866 EXPORT_API int appcore_ui_base_get_hint(void)
867 {
868         return __context.hint;
869 }
870
871 EXPORT_API bool appcore_ui_base_get_bg_state(void)
872 {
873         return __context.bg_state;
874 }
875
876 EXPORT_API void appcore_ui_base_set_bg_state(bool bg_state)
877 {
878         __context.bg_state = bg_state;
879 }
880
881 static int __on_receive(aul_type type, bundle *b, void *data)
882 {
883         return appcore_ui_base_on_receive(type, b);
884 }
885
886 static int __on_create(void *data)
887 {
888         return appcore_ui_base_on_create();
889 }
890
891 static int __on_terminate(void *data)
892 {
893         return appcore_ui_base_on_terminate();
894 }
895
896 static int __on_pause(void *data)
897 {
898         return appcore_ui_base_on_pause();
899 }
900
901 static int __on_resume(void *data)
902 {
903         return appcore_ui_base_on_resume();
904 }
905
906 static void __window_on_show(int type, void *event, void *data)
907 {
908         appcore_ui_base_window_on_show(type, event);
909 }
910
911 static void __window_on_hide(int type, void *event, void *data)
912 {
913         appcore_ui_base_window_on_hide(type, event);
914 }
915
916 static void __window_on_lower(int type, void *event, void *data)
917 {
918         appcore_ui_base_window_on_lower(type, event);
919 }
920
921 static void __window_on_visibility(int type, void *event, void *data)
922 {
923         appcore_ui_base_window_on_visibility(type, event);
924 }
925
926 static void __window_on_pre_visibility(int type, void *event, void *data)
927 {
928         appcore_ui_base_window_on_pre_visibility(type, event);
929 }
930
931 EXPORT_API appcore_ui_base_ops appcore_ui_base_get_default_ops(void)
932 {
933         appcore_ui_base_ops ops;
934
935         ops.base = appcore_base_get_default_ops();
936
937         /* override methods */
938         ops.base.create = __on_create;
939         ops.base.terminate = __on_terminate;
940         ops.base.receive = __on_receive;
941         ops.base.init = NULL;
942         ops.base.finish = NULL;
943         ops.base.run = NULL;
944         ops.base.exit = NULL;
945
946         ops.pause = __on_pause;
947         ops.resume = __on_resume;
948         ops.window.show = __window_on_show;
949         ops.window.hide = __window_on_hide;
950         ops.window.lower = __window_on_lower;
951         ops.window.visibility = __window_on_visibility;
952         ops.window.pre_visibility = __window_on_pre_visibility;
953
954         return ops;
955 }
956
957