Memory leak while creating duplicate bundle
[platform/core/appfw/app-core.git] / src / appcore-efl.c
1 /*
2  * Copyright (c) 2000 - 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 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <sys/un.h>
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <stdarg.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <stdlib.h>
26
27 #if defined(WAYLAND)
28 #include <Ecore_Wayland.h>
29 #include <wayland-client.h>
30 #include <wayland-tbm-client.h>
31 #include <tizen-extension-client-protocol.h>
32 #elif defined(X11)
33 #include <X11/Xatom.h>
34 #include <X11/Xlib.h>
35 #include <Ecore_X.h>
36 #endif
37
38 #include <Ecore.h>
39 #include <Ecore_Evas.h>
40 #include <Ecore_Input_Evas.h>
41 #include <Elementary.h>
42 #include <glib-object.h>
43 #include <malloc.h>
44 #include <glib.h>
45 #include <gio/gio.h>
46 #include <stdbool.h>
47 #include <aul.h>
48 #include <aul_svc.h>
49 #include <bundle_internal.h>
50 #include <ttrace.h>
51
52 #include "appcore-internal.h"
53 #include "appcore-efl.h"
54 #include <system_info.h>
55
56 static pid_t _pid;
57 static bool resource_reclaiming = TRUE;
58 static int tmp_val = 0;
59
60 struct ui_priv {
61         const char *name;
62         enum app_state state;
63
64         Ecore_Event_Handler *hshow;
65         Ecore_Event_Handler *hhide;
66         Ecore_Event_Handler *hvchange;
67 #if defined(WAYLAND)
68         Ecore_Event_Handler *hlower;
69 #endif
70         Ecore_Event_Handler *hcmsg; /* WM_ROTATE */
71
72         Ecore_Timer *mftimer; /* Ecore Timer for memory flushing */
73
74         struct appcore *app_core;
75         void (*prepare_to_suspend) (void *data);
76         void (*exit_from_suspend) (void *data);
77         struct appcore_ops *ops;
78         void (*mfcb) (void); /* Memory Flushing Callback */
79
80         /* WM_ROTATE */
81         int wm_rot_supported;
82         int rot_started;
83         int (*rot_cb) (void *event_info, enum appcore_rm, void *);
84         void *rot_cb_data;
85         enum appcore_rm rot_mode;
86         char *below_app;
87 };
88
89 static struct ui_priv priv;
90
91 static const char *_ae_name[AE_MAX] = {
92         [AE_UNKNOWN] = "UNKNOWN",
93         [AE_CREATE] = "CREATE",
94         [AE_TERMINATE] = "TERMINATE",
95         [AE_PAUSE] = "PAUSE",
96         [AE_RESUME] = "RESUME",
97         [AE_RESET] = "RESET",
98         [AE_LOWMEM_POST] = "LOWMEM_POST",
99         [AE_MEM_FLUSH] = "MEM_FLUSH",
100         [AE_UPDATE_REQUESTED] = "UPDATE_REQUESTED",
101 };
102
103 static const char *_as_name[] = {
104         [AS_NONE] = "NONE",
105         [AS_CREATED] = "CREATED",
106         [AS_RUNNING] = "RUNNING",
107         [AS_PAUSED] = "PAUSED",
108         [AS_DYING] = "DYING",
109 };
110
111 static bool b_active = FALSE;
112 static bool first_launch = TRUE;
113
114 struct win_node {
115         unsigned int win;
116 #if defined(WAYLAND)
117         unsigned int surf;
118 #endif
119         bool bfobscured;
120 };
121
122 #if defined(X11)
123 static struct ui_wm_rotate wm_rotate;
124 #endif
125 static Eina_Bool __visibility_cb(void *data, int type, void *event);
126 static GSList *g_winnode_list;
127
128 static struct wl_display *dsp;
129 static struct wl_registry *reg;
130 static struct tizen_policy *tz_policy;
131 static bool bg_state = false;
132
133 static void __wl_listener_cb(void *data, struct wl_registry *reg,
134                 uint32_t id, const char *interface, uint32_t ver)
135 {
136         if (interface && !strcmp(interface, "tizen_policy")) {
137                 if (!tz_policy)
138                         tz_policy = wl_registry_bind(reg, id,
139                                         &tizen_policy_interface, 1);
140         }
141 }
142
143 static void __wl_listener_remove_cb(void *data, struct wl_registry *reg,
144                 unsigned int id)
145 {
146         /* do nothing */
147 }
148
149 static const struct wl_registry_listener reg_listener = {
150         __wl_listener_cb,
151         __wl_listener_remove_cb
152 };
153
154 static int __init_wl(void)
155 {
156         _DBG("initialize wayland");
157         dsp = wl_display_connect(NULL);
158         if (dsp == NULL) {
159                 _ERR("Failed to connect wl display");
160                 return -1;
161         }
162
163         reg = wl_display_get_registry(dsp);
164         if (reg == NULL) {
165                 _ERR("Failed to get registry");
166                 wl_display_disconnect(dsp);
167                 return -1;
168         }
169
170         wl_registry_add_listener(reg, &reg_listener, NULL);
171         wl_display_roundtrip(dsp);
172
173         if (!tz_policy) {
174                 _ERR("Failed to get tizen policy interface");
175                 wl_registry_destroy(reg);
176                 wl_display_disconnect(dsp);
177                 return -1;
178         }
179
180         return 0;
181 }
182
183 static void __finish_wl(void)
184 {
185         if (tz_policy) {
186                 tizen_policy_destroy(tz_policy);
187                 tz_policy = NULL;
188         }
189
190         if (reg) {
191                 wl_registry_destroy(reg);
192                 reg = NULL;
193         }
194
195         if (dsp) {
196                 wl_display_disconnect(dsp);
197                 dsp = NULL;
198         }
199 }
200
201 static void __set_bg_state(void)
202 {
203         if (__init_wl() < 0)
204                 return;
205
206         tizen_policy_set_background_state(tz_policy, getpid());
207         wl_display_roundtrip(dsp);
208         bg_state = true;
209         _DBG("bg state: %d", bg_state);
210 }
211
212 static void __unset_bg_state(void)
213 {
214         if (!tz_policy)
215                 return;
216
217         tizen_policy_unset_background_state(tz_policy, getpid());
218         wl_display_roundtrip(dsp);
219         bg_state = false;
220         _DBG("bg state: %d", bg_state);
221         __finish_wl();
222 }
223
224 static void __appcore_efl_prepare_to_suspend(void *data)
225 {
226         struct ui_priv *ui = (struct ui_priv *)data;
227         struct sys_op *op = NULL;
228         int suspend = APPCORE_SUSPENDED_STATE_WILL_ENTER_SUSPEND;
229
230         if (ui->app_core && !ui->app_core->allowed_bg && !ui->app_core->suspended_state) {
231                 op = &ui->app_core->sops[SE_SUSPENDED_STATE];
232                 if (op && op->func)
233                         op->func((void *)&suspend, op->data); /* calls c-api handler */
234
235                 ui->app_core->suspended_state = true;
236         }
237         _DBG("[__SUSPEND__]");
238 }
239
240 static void __appcore_efl_exit_from_suspend(void *data)
241 {
242         struct ui_priv *ui = (struct ui_priv *)data;
243         struct sys_op *op = NULL;
244         int suspend = APPCORE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
245
246         if (ui->app_core && !ui->app_core->allowed_bg && ui->app_core->suspended_state) {
247                 op = &ui->app_core->sops[SE_SUSPENDED_STATE];
248                 if (op && op->func)
249                         op->func((void *)&suspend, op->data); /* calls c-api handler */
250
251                 ui->app_core->suspended_state = false;
252         }
253         _DBG("[__SUSPEND__]");
254 }
255
256 static void __appcore_efl_update_requested(void *data)
257 {
258         struct ui_priv *ui = (struct ui_priv *)data;
259         struct sys_op *op;
260         int dummy = 0;
261
262         if (ui->app_core) {
263                 op = &ui->app_core->sops[SE_UPDATE_REQUESTED];
264                 if (op && op->func)
265                         op->func((void *)&dummy, op->data);
266         }
267         _DBG("[__UPDATE_REQUESTED__]");
268 }
269
270 #if defined(MEMORY_FLUSH_ACTIVATE)
271 static Eina_Bool __appcore_memory_flush_cb(void *data)
272 {
273         struct ui_priv *ui = (struct ui_priv *)data;
274
275         appcore_flush_memory();
276         if (ui)
277                 ui->mftimer = NULL;
278
279         if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT && ui && ui->prepare_to_suspend) {
280                 _DBG("[__SUSPEND__] flush case");
281                 ui->prepare_to_suspend(ui);
282         }
283
284         return ECORE_CALLBACK_CANCEL;
285 }
286
287 static int __appcore_low_memory_post_cb(struct ui_priv *ui)
288 {
289         if (ui->state == AS_PAUSED)
290                 appcore_flush_memory();
291         else
292                 malloc_trim(0);
293
294         return 0;
295 }
296
297 static void __appcore_timer_add(struct ui_priv *ui)
298 {
299         ui->mftimer = ecore_timer_add(5, __appcore_memory_flush_cb, ui);
300 }
301
302 static void __appcore_timer_del(struct ui_priv *ui)
303 {
304         if (ui->mftimer) {
305                 ecore_timer_del(ui->mftimer);
306                 ui->mftimer = NULL;
307         }
308 }
309
310 #else
311
312 static int __appcore_low_memory_post_cb(ui_priv *ui)
313 {
314         return -1;
315 }
316
317 #define __appcore_timer_add(ui) 0
318 #define __appcore_timer_del(ui) 0
319
320 #endif
321
322 static void __appcore_efl_memory_flush_cb(void)
323 {
324         _DBG("[APP %d]   __appcore_efl_memory_flush_cb()", _pid);
325         elm_cache_all_flush();
326 }
327 #if defined(WAYLAND)
328 static void wl_raise_win(void)
329 {
330         Ecore_Wl_Window *win;
331         unsigned int win_id = appcore_get_main_window();
332
333         _DBG("Raise window: %d", win_id);
334         win = ecore_wl_window_find(win_id);
335         ecore_wl_window_activate(win);
336 }
337
338 static void wl_pause_win(void)
339 {
340         Ecore_Wl_Window *win;
341         GSList *wlist = g_winnode_list;
342         struct win_node *entry = NULL;
343
344         _DBG("Pause window");
345
346         while (wlist) {
347                 entry = wlist->data;
348
349                 _DBG("Pause window: %d", entry->win);
350                 win = ecore_wl_window_find(entry->win);
351                 ecore_wl_window_iconified_set(win, EINA_TRUE);
352
353                 wlist = wlist->next;
354         }
355 }
356
357 #endif
358
359 static void __do_app(enum app_event event, void *data, bundle * b)
360 {
361         int r = -1;
362         struct ui_priv *ui = data;
363         const char *below_app;
364         const char *bg_launch;
365
366         _DBG("[APP %d] Event: %d", _pid, event);
367         _ret_if(ui == NULL || event >= AE_MAX);
368         _DBG("[APP %d] Event: %s State: %s", _pid, _ae_name[event],
369              _as_name[ui->state]);
370
371         if (event == AE_MEM_FLUSH) {
372                 ui->mfcb();
373                 return;
374         }
375
376         if (event == AE_LOWMEM_POST) {
377                 if (__appcore_low_memory_post_cb(ui) == 0)
378                         return;
379         }
380
381         if (!(ui->state == AS_PAUSED && event == AE_PAUSE))
382                 __appcore_timer_del(ui);
383
384         if (ui->state == AS_DYING) {
385                 _ERR("Skip the event in dying state");
386                 return;
387         }
388
389         if (event == AE_TERMINATE) {
390                 _DBG("[APP %d] TERMINATE", _pid);
391                 elm_exit();
392                 aul_status_update(STATUS_DYING);
393                 return;
394         }
395
396         if (event == AE_RAISE) {
397 #if defined(X11)
398                 x_raise_win(getpid());
399 #elif defined(WAYLAND)
400                 wl_raise_win();
401 #endif
402                 return;
403         }
404
405         if (event == AE_LOWER) {
406 #if defined(X11)
407                 x_pause_win(getpid());
408 #elif defined(WAYLAND)
409                 wl_pause_win();
410 #endif
411                 return;
412         }
413
414         _ret_if(ui->ops == NULL);
415
416         switch (event) {
417         case AE_RESET:
418                 _DBG("[APP %d] RESET", _pid);
419                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]", ui->name);
420
421                 if (ui->below_app) {
422                         free(ui->below_app);
423                         ui->below_app = NULL;
424                 }
425
426                 below_app = bundle_get_val(b, AUL_SVC_K_RELOCATE_BELOW);
427                 if (below_app)
428                         ui->below_app = strdup(below_app);
429                 if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT && ui->exit_from_suspend) {
430                         _DBG("[__SUSPEND__] reset case");
431                         ui->exit_from_suspend(ui);
432                 }
433
434                 if (ui->ops->reset) {
435                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
436                                         "APPCORE:RESET");
437                         r = ui->ops->reset(b, ui->ops->data);
438                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
439                 }
440                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]", ui->name);
441
442                 if (first_launch) {
443                         if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT && ui->app_core->allowed_bg)
444                                 __appcore_timer_add(ui);
445                         first_launch = FALSE;
446                 } else {
447                         _INFO("[APP %d] App already running, raise the window", _pid);
448                         if (bg_state) {
449                                 bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
450                                 if (!bg_launch || strcmp(bg_launch, "enable"))
451                                         __unset_bg_state();
452                         }
453 #ifdef X11
454                         x_raise_win(getpid());
455 #else
456                         wl_raise_win();
457 #endif
458                 }
459                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]",
460                     ui->name);
461                 break;
462         case AE_PAUSE:
463                 if (ui->state == AS_RUNNING) {
464                         _DBG("[APP %d] PAUSE", _pid);
465                         if (ui->ops->pause) {
466                                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
467                                                 "APPCORE:PAUSE");
468                                 r = ui->ops->pause(ui->ops->data);
469                                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
470                         }
471                         ui->state = AS_PAUSED;
472                         if (r >= 0 && resource_reclaiming == TRUE)
473                                 __appcore_timer_add(ui);
474                         else if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT && r >= 0 && resource_reclaiming == FALSE
475                                         && ui->prepare_to_suspend) {
476                                 _DBG("[__SUSPEND__] pause case");
477                                 ui->prepare_to_suspend(ui);
478                         }
479                 }
480                 /* TODO : rotation stop */
481                 /* r = appcore_pause_rotation_cb(); */
482                 aul_status_update(STATUS_BG);
483                 break;
484         case AE_RESUME:
485                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]",
486                                 ui->name);
487                 if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT) {
488                         if (ui->exit_from_suspend) {
489                                 _DBG("[__SUSPEND__] resume case");
490                                 ui->exit_from_suspend(ui);
491                         }
492                         if (ui->app_core->allowed_bg)
493                                 __appcore_timer_del(ui);
494                 }
495
496                 if (ui->state == AS_PAUSED || ui->state == AS_CREATED) {
497                         _DBG("[APP %d] RESUME", _pid);
498
499                         if (ui->ops->resume) {
500                                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
501                                         "APPCORE:RESUME");
502                                 ui->ops->resume(ui->ops->data);
503                                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
504                         }
505                         ui->state = AS_RUNNING;
506
507                         if (ui->below_app) {
508                                 aul_app_group_activate_below(ui->below_app);
509                                 free(ui->below_app);
510                                 ui->below_app = NULL;
511                         }
512                 }
513                 /*TODO : rotation start*/
514                 /* r = appcore_resume_rotation_cb(); */
515                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]",
516                     ui->name);
517                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:Launching:done]",
518                     ui->name);
519                 aul_status_update(STATUS_VISIBLE);
520                 break;
521         case AE_TERMINATE_BGAPP:
522                 if (ui->state == AS_PAUSED) {
523                         _DBG("[APP %d] is paused. TERMINATE", _pid);
524                         ui->state = AS_DYING;
525                         aul_status_update(STATUS_DYING);
526                         elm_exit();
527                 } else if (ui->state == AS_RUNNING) {
528                         _DBG("[APP %d] is running.", _pid);
529                 } else {
530                         _DBG("[APP %d] is another state", _pid);
531                 }
532                 break;
533         case AE_UPDATE_REQUESTED:
534                 __appcore_efl_update_requested(ui);
535                 break;
536         default:
537                 /* do nothing */
538                 break;
539         }
540 }
541
542 static struct ui_ops efl_ops = {
543         .data = &priv,
544         .cb_app = __do_app,
545 };
546
547 static bool __check_visible(void)
548 {
549         GSList *iter = NULL;
550         struct win_node *entry = NULL;
551
552         _DBG("[EVENT_TEST][EVENT] __check_visible\n");
553
554         for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
555                 entry = iter->data;
556                 _DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
557                 if (entry->bfobscured == FALSE)
558                         return TRUE;
559         }
560
561         return FALSE;
562 }
563
564 static GSList *__find_win(unsigned int win)
565 {
566         GSList *iter;
567         struct win_node *t;
568
569         for (iter = g_winnode_list; iter; iter = g_slist_next(iter)) {
570                 t = iter->data;
571                 if (t && t->win == win)
572                         return iter;
573         }
574
575         return NULL;
576 }
577
578 #if defined(X11)
579 static bool __add_win(unsigned int win)
580 {
581         struct win_node *t;
582         GSList *f;
583
584         _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
585
586         f = __find_win(win);
587         if (f) {
588                 errno = ENOENT;
589                 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
590                 return FALSE;
591         }
592
593         t = calloc(1, sizeof(struct win_node));
594         if (t == NULL)
595                 return FALSE;
596
597         t->win = win;
598         t->bfobscured = FALSE;
599
600         g_winnode_list = g_slist_append(g_winnode_list, t);
601
602         return TRUE;
603 }
604 #elif defined(WAYLAND)
605 static bool __add_win(unsigned int win, unsigned int surf)
606 {
607         struct win_node *t;
608         GSList *f;
609
610         _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
611
612         f = __find_win(win);
613         if (f) {
614                 errno = ENOENT;
615                 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
616                 return FALSE;
617         }
618
619         t = calloc(1, sizeof(struct win_node));
620         if (t == NULL)
621                 return FALSE;
622
623         t->win = win;
624         t->surf = surf;
625         t->bfobscured = FALSE;
626
627         g_winnode_list = g_slist_append(g_winnode_list, t);
628
629         return TRUE;
630 }
631 #endif
632
633 static bool __delete_win(unsigned int win)
634 {
635         GSList *f;
636
637         f = __find_win(win);
638         if (!f) {
639                 errno = ENOENT;
640                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n",
641                                 win);
642                 return FALSE;
643         }
644
645         free(f->data);
646         g_winnode_list = g_slist_delete_link(g_winnode_list, f);
647
648         return TRUE;
649 }
650
651 #if defined(X11)
652 static bool __update_win(unsigned int win, bool bfobscured)
653 {
654         GSList *f;
655         struct win_node *t;
656
657         _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
658              bfobscured);
659
660         f = __find_win(win);
661         if (!f) {
662                 errno = ENOENT;
663                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
664                 return FALSE;
665         }
666
667         t = (struct win_node *)f->data;
668         t->win = win;
669         t->bfobscured = bfobscured;
670
671         return TRUE;
672 }
673 #elif defined(WAYLAND)
674 static bool __update_win(unsigned int win, unsigned int surf, bool bfobscured)
675 {
676         GSList *f;
677         struct win_node *t;
678
679         _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
680              bfobscured);
681
682         f = __find_win(win);
683         if (!f) {
684                 errno = ENOENT;
685                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
686                 return FALSE;
687         }
688
689         t = (struct win_node *)f->data;
690         t->win = win;
691         if (surf != 0)
692                 t->surf = surf;
693         t->bfobscured = bfobscured;
694
695         return TRUE;
696 }
697 #endif
698
699 /* WM_ROTATE */
700 #ifdef X11
701 static Ecore_X_Atom _WM_WINDOW_ROTATION_SUPPORTED = 0;
702 static Ecore_X_Atom _WM_WINDOW_ROTATION_CHANGE_REQUEST = 0;
703
704 static int __check_wm_rotation_support(void)
705 {
706         _DBG("Disable window manager rotation");
707         return -1;
708
709         Ecore_X_Window root, win, win2;
710         int ret;
711
712         if (!_WM_WINDOW_ROTATION_SUPPORTED) {
713                 _WM_WINDOW_ROTATION_SUPPORTED =
714                                         ecore_x_atom_get("_E_WINDOW_ROTATION_SUPPORTED");
715         }
716
717         if (!_WM_WINDOW_ROTATION_CHANGE_REQUEST) {
718                 _WM_WINDOW_ROTATION_CHANGE_REQUEST =
719                                         ecore_x_atom_get("_E_WINDOW_ROTATION_CHANGE_REQUEST");
720         }
721
722         root = ecore_x_window_root_first_get();
723         ret = ecore_x_window_prop_xid_get(root,
724                         _WM_WINDOW_ROTATION_SUPPORTED,
725                         ECORE_X_ATOM_WINDOW,
726                         &win, 1);
727         if ((ret == 1) && (win)) {
728                 ret = ecore_x_window_prop_xid_get(win,
729                                 _WM_WINDOW_ROTATION_SUPPORTED,
730                                 ECORE_X_ATOM_WINDOW,
731                                 &win2, 1);
732                 if ((ret == 1) && (win2 == win))
733                         return 0;
734         }
735
736         return -1;
737 }
738
739 static void __set_wm_rotation_support(unsigned int win, unsigned int set)
740 {
741         GSList *iter = NULL;
742         struct win_node *entry = NULL;
743
744         if (win == 0) {
745                 for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
746                         entry = iter->data;
747                         if (entry->win) {
748                                 ecore_x_window_prop_card32_set(entry->win,
749                                                 _WM_WINDOW_ROTATION_SUPPORTED,
750                                                 &set, 1);
751                         }
752                 }
753         } else {
754                 ecore_x_window_prop_card32_set(win,
755                                 _WM_WINDOW_ROTATION_SUPPORTED,
756                                 &set, 1);
757         }
758 }
759 #endif
760
761 static Eina_Bool __show_cb(void *data, int type, void *event)
762 {
763 #if defined(WAYLAND)
764         Ecore_Wl_Event_Window_Show *ev;
765
766         ev = event;
767         if (ev->parent_win != 0) {
768                 /* This is child window. Skip!!! */
769                 return ECORE_CALLBACK_PASS_ON;
770         }
771
772         _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x, %d\n", ev->win, ev->data[0]);
773
774         if (!__find_win((unsigned int)ev->win))
775                 __add_win((unsigned int)ev->win, (unsigned int)ev->data[0]);
776         else
777                 __update_win((unsigned int)ev->win, (unsigned int)ev->data[0], FALSE);
778
779 #elif defined(X11)
780         Ecore_X_Event_Window_Show *ev;
781
782         ev = event;
783
784         _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x\n", ev->win);
785
786         if (!__find_win((unsigned int)ev->win)) {
787                 /* WM_ROTATE */
788                 if ((priv.wm_rot_supported) && (1 == priv.rot_started))
789                         __set_wm_rotation_support(ev->win, 1);
790                 __add_win((unsigned int)ev->win);
791         } else {
792                 __update_win((unsigned int)ev->win, FALSE);
793         }
794 #endif
795
796         appcore_group_attach();
797         return ECORE_CALLBACK_RENEW;
798 }
799
800 static Eina_Bool __hide_cb(void *data, int type, void *event)
801 {
802 #if defined(WAYLAND)
803         Ecore_Wl_Event_Window_Hide *ev;
804 #elif defined(X11)
805         Ecore_X_Event_Window_Hide *ev;
806 #endif
807         int bvisibility = 0;
808
809         ev = event;
810
811         _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
812
813         if (__find_win((unsigned int)ev->win)) {
814                 __delete_win((unsigned int)ev->win);
815                 bvisibility = __check_visible();
816                 if (!bvisibility && b_active == TRUE) {
817                         _DBG(" Go to Pasue state \n");
818                         b_active = FALSE;
819                         __do_app(AE_PAUSE, data, NULL);
820                 }
821         }
822
823         return ECORE_CALLBACK_RENEW;
824 }
825
826 #if defined(WAYLAND)
827 static Eina_Bool __lower_cb(void *data, int type, void *event)
828 {
829         Ecore_Wl_Event_Window_Lower *ev;
830         ev = event;
831         if (!ev) return ECORE_CALLBACK_RENEW;
832         _DBG("ECORE_WL_EVENT_WINDOW_LOWER window id:%u\n", ev->win);
833         appcore_group_lower();
834         return ECORE_CALLBACK_RENEW;
835 }
836 #endif
837
838 static Eina_Bool __visibility_cb(void *data, int type, void *event)
839 {
840 #if defined(WAYLAND)
841         Ecore_Wl_Event_Window_Visibility_Change *ev;
842         int bvisibility = 0;
843         ev = event;
844         __update_win((unsigned int)ev->win, 0, ev->fully_obscured);
845 #elif defined(X11)
846         Ecore_X_Event_Window_Visibility_Change *ev;
847         int bvisibility = 0;
848
849         ev = event;
850
851         __update_win((unsigned int)ev->win, ev->fully_obscured);
852 #endif
853         bvisibility = __check_visible();
854
855         _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
856
857         if (bvisibility && b_active == FALSE) {
858                 _DBG(" Go to Resume state\n");
859                 b_active = TRUE;
860                 __do_app(AE_RESUME, data, NULL);
861
862         } else if (!bvisibility && b_active == TRUE) {
863                 _DBG(" Go to Pasue state \n");
864                 b_active = FALSE;
865                 __do_app(AE_PAUSE, data, NULL);
866         } else
867                 _DBG(" No change state \n");
868
869         return ECORE_CALLBACK_RENEW;
870
871 }
872
873 #if defined(X11)
874 /* WM_ROTATE */
875 static Eina_Bool __cmsg_cb(void *data, int type, void *event)
876 {
877         struct ui_priv *ui = (struct ui_priv *)data;
878         Ecore_X_Event_Client_Message *e = event;
879
880         if (!ui)
881                 return ECORE_CALLBACK_PASS_ON;
882
883         if (e->format != 32)
884                 return ECORE_CALLBACK_PASS_ON;
885
886         if (e->message_type == _WM_WINDOW_ROTATION_CHANGE_REQUEST) {
887                 if ((ui->wm_rot_supported == 0)
888                         || (ui->rot_started == 0)
889                         || (ui->rot_cb == NULL)) {
890                         return ECORE_CALLBACK_PASS_ON;
891                 }
892
893                 enum appcore_rm rm;
894                 switch (e->data.l[1]) {
895                 case 0:
896                         rm = APPCORE_RM_PORTRAIT_NORMAL;
897                         break;
898                 case 90:
899                         rm = APPCORE_RM_LANDSCAPE_REVERSE;
900                         break;
901                 case 180:
902                         rm = APPCORE_RM_PORTRAIT_REVERSE;
903                         break;
904                 case 270:
905                         rm = APPCORE_RM_LANDSCAPE_NORMAL;
906                         break;
907                 default:
908                         rm = APPCORE_RM_UNKNOWN;
909                         break;
910                 }
911
912                 ui->rot_mode = rm;
913
914                 if (APPCORE_RM_UNKNOWN != rm)
915                         ui->rot_cb((void *)&rm, rm, ui->rot_cb_data);
916         }
917
918         return ECORE_CALLBACK_PASS_ON;
919 }
920 #endif
921
922 static void __add_climsg_cb(struct ui_priv *ui)
923 {
924         _ret_if(ui == NULL);
925 #if defined(WAYLAND)
926         ui->hshow =
927                 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_SHOW, __show_cb, ui);
928         ui->hhide =
929                 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_HIDE, __hide_cb, ui);
930         ui->hvchange =
931                 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
932                                 __visibility_cb, ui);
933         ui->hlower =
934                 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_LOWER,
935                                 __lower_cb, ui);
936 #elif defined(X11)
937         ui->hshow =
938                 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, __show_cb, ui);
939         ui->hhide =
940                 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, __hide_cb, ui);
941         ui->hvchange =
942                 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE,
943                                 __visibility_cb, ui);
944
945         /* Add client message callback for WM_ROTATE */
946         if (!__check_wm_rotation_support()) {
947                 ui->hcmsg = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
948                                 __cmsg_cb, ui);
949                 ui->wm_rot_supported = 1;
950                 appcore_set_wm_rotation(&wm_rotate);
951         }
952 #endif
953 }
954
955 static int __before_loop(struct ui_priv *ui, int *argc, char ***argv)
956 {
957         int r;
958         char *hwacc = NULL;
959         struct appcore *ac = NULL;
960         bundle *b;
961         const char *bg_launch;
962
963         if (argc == NULL || argv == NULL) {
964                 _ERR("argc/argv is NULL");
965                 errno = EINVAL;
966                 return -1;
967         }
968
969 #if !(GLIB_CHECK_VERSION(2, 36, 0))
970         g_type_init();
971 #endif
972         elm_init(*argc, *argv);
973
974         hwacc = getenv("HWACC");
975         if (hwacc == NULL) {
976                 _DBG("elm_config_accel_preference_set is not called");
977         } else if (strcmp(hwacc, "USE") == 0) {
978                 elm_config_accel_preference_set("hw");
979                 _DBG("elm_config_accel_preference_set : hw");
980         } else if (strcmp(hwacc, "NOT_USE") == 0) {
981                 elm_config_accel_preference_set("none");
982                 _DBG("elm_config_accel_preference_set : none");
983         } else {
984                 _DBG("elm_config_accel_preference_set is not called");
985         }
986
987         r = appcore_init(ui->name, &efl_ops, *argc, *argv);
988         _retv_if(r == -1, -1);
989
990         if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT) {
991                 appcore_get_app_core(&ac);
992                 ui->app_core = ac;
993                 SECURE_LOGD("[__SUSPEND__] appcore initialized, appcore addr: #%x", ac);
994         }
995
996         b = bundle_import_from_argv(*argc, *argv);
997         if (b) {
998                 bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
999                 if (bg_launch && strcmp(bg_launch, "enable") == 0)
1000                         __set_bg_state();
1001
1002                 bundle_free(b);
1003         }
1004
1005         LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:appcore_init:done]", ui->name);
1006         if (ui->ops && ui->ops->create) {
1007                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:CREATE");
1008                 r = ui->ops->create(ui->ops->data);
1009                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1010                 if (r < 0) {
1011                         _ERR("create() return error");
1012                         appcore_exit();
1013                         if (ui->ops && ui->ops->terminate) {
1014                                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
1015                                         "APPCORE:TERMINATE");
1016                                 ui->ops->terminate(ui->ops->data);
1017                                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1018                         }
1019                         errno = ECANCELED;
1020                         return -1;
1021                 }
1022                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]",
1023                     ui->name);
1024         }
1025         ui->state = AS_CREATED;
1026
1027         __add_climsg_cb(ui);
1028
1029         return 0;
1030 }
1031
1032 static void __after_loop(struct ui_priv *ui)
1033 {
1034         appcore_unset_rotation_cb();
1035         appcore_exit();
1036
1037         if (ui->state == AS_RUNNING) {
1038                 _DBG("[APP %d] PAUSE before termination", _pid);
1039                 if (ui->ops && ui->ops->pause) {
1040                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
1041                                         "APPCORE:PAUSE");
1042                         ui->ops->pause(ui->ops->data);
1043                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1044                 }
1045         }
1046
1047         if (ui->ops && ui->ops->terminate) {
1048                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:TERMINATE");
1049                 ui->ops->terminate(ui->ops->data);
1050                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1051         }
1052
1053         ui->state = AS_DYING;
1054
1055         if (ui->hshow)
1056                 ecore_event_handler_del(ui->hshow);
1057         if (ui->hhide)
1058                 ecore_event_handler_del(ui->hhide);
1059         if (ui->hvchange)
1060                 ecore_event_handler_del(ui->hvchange);
1061 #if defined(WAYLAND)
1062         if (ui->hlower)
1063                 ecore_event_handler_del(ui->hlower);
1064 #endif
1065
1066         __appcore_timer_del(ui);
1067
1068         elm_shutdown();
1069
1070         /* Check loader case */
1071         if (getenv("AUL_LOADER_INIT")) {
1072                 unsetenv("AUL_LOADER_INIT");
1073                 elm_shutdown();
1074         }
1075 }
1076
1077 static int __set_data(struct ui_priv *ui, const char *name,
1078                     struct appcore_ops *ops)
1079 {
1080         if (ui->name) {
1081                 _ERR("Mainloop already started");
1082                 errno = EINPROGRESS;
1083                 return -1;
1084         }
1085
1086         if (name == NULL || name[0] == '\0') {
1087                 _ERR("Invalid name");
1088                 errno = EINVAL;
1089                 return -1;
1090         }
1091
1092         if (ops == NULL) {
1093                 _ERR("ops is NULL");
1094                 errno = EINVAL;
1095                 return -1;
1096         }
1097
1098         ui->name = strdup(name);
1099         _retv_if(ui->name == NULL, -1);
1100
1101         ui->ops = ops;
1102         ui->mfcb = __appcore_efl_memory_flush_cb;
1103         _pid = getpid();
1104
1105         /* WM_ROTATE */
1106         ui->wm_rot_supported = 0;
1107         ui->rot_started = 0;
1108         ui->rot_cb = NULL;
1109         ui->rot_cb_data = NULL;
1110         ui->rot_mode = APPCORE_RM_UNKNOWN;
1111
1112         if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT) {
1113                 ui->app_core = NULL;
1114                 ui->prepare_to_suspend = __appcore_efl_prepare_to_suspend;
1115                 ui->exit_from_suspend = __appcore_efl_exit_from_suspend;
1116         }
1117
1118         return 0;
1119 }
1120
1121 static void __unset_data(struct ui_priv *ui)
1122 {
1123         if (ui->name)
1124                 free((void *)ui->name);
1125
1126         memset(ui, 0, sizeof(struct ui_priv));
1127 }
1128
1129 #if defined(X11)
1130 /* WM_ROTATE */
1131 static int __wm_set_rotation_cb(int (*cb) (void *event_info, enum appcore_rm, void *), void *data)
1132 {
1133         if (cb == NULL) {
1134                 errno = EINVAL;
1135                 return -1;
1136         }
1137
1138         if ((priv.wm_rot_supported) && (0 == priv.rot_started))
1139                 __set_wm_rotation_support(0, 1);
1140
1141         priv.rot_cb = cb;
1142         priv.rot_cb_data = data;
1143         priv.rot_started = 1;
1144
1145         return 0;
1146 }
1147
1148 static int __wm_unset_rotation_cb(void)
1149 {
1150         if ((priv.wm_rot_supported) && (1 == priv.rot_started))
1151                 __set_wm_rotation_support(0, 0);
1152
1153         priv.rot_cb = NULL;
1154         priv.rot_cb_data = NULL;
1155         priv.rot_started = 0;
1156
1157         return 0;
1158 }
1159
1160 static int __wm_get_rotation_state(enum appcore_rm *curr)
1161 {
1162         if (curr == NULL) {
1163                 errno = EINVAL;
1164                 return -1;
1165         }
1166
1167         *curr = priv.rot_mode;
1168
1169         return 0;
1170 }
1171
1172 static int __wm_pause_rotation_cb(void)
1173 {
1174         if ((priv.rot_started == 1) && (priv.wm_rot_supported))
1175                 __set_wm_rotation_support(0, 0);
1176
1177         priv.rot_started = 0;
1178
1179         return 0;
1180 }
1181
1182 static int __wm_resume_rotation_cb(void)
1183 {
1184         if ((priv.rot_started == 0) && (priv.wm_rot_supported))
1185                 __set_wm_rotation_support(0, 1);
1186
1187         priv.rot_started = 1;
1188
1189         return 0;
1190 }
1191
1192 static struct ui_wm_rotate wm_rotate = {
1193         __wm_set_rotation_cb,
1194         __wm_unset_rotation_cb,
1195         __wm_get_rotation_state,
1196         __wm_pause_rotation_cb,
1197         __wm_resume_rotation_cb
1198 };
1199 #endif
1200
1201 EXPORT_API int appcore_efl_init(const char *name, int *argc, char ***argv,
1202                      struct appcore_ops *ops)
1203 {
1204         int r;
1205
1206         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", name);
1207
1208         r = __set_data(&priv, name, ops);
1209         _retv_if(r == -1, -1);
1210
1211         r = __before_loop(&priv, argc, argv);
1212         if (r == -1) {
1213                 aul_status_update(STATUS_DYING);
1214                 __unset_data(&priv);
1215                 return -1;
1216         }
1217
1218         return 0;
1219 }
1220
1221 EXPORT_API void appcore_efl_fini(void)
1222 {
1223         aul_status_update(STATUS_DYING);
1224
1225         __after_loop(&priv);
1226
1227         __unset_data(&priv);
1228 }
1229
1230 EXPORT_API int appcore_efl_main(const char *name, int *argc, char ***argv,
1231                                 struct appcore_ops *ops)
1232 {
1233         int r;
1234
1235         r = appcore_efl_init(name, argc, argv, ops);
1236         _retv_if(r == -1, -1);
1237
1238         elm_run();
1239
1240         appcore_efl_fini();
1241
1242         return 0;
1243 }
1244
1245 EXPORT_API int appcore_set_system_resource_reclaiming(bool enable)
1246 {
1247         resource_reclaiming = enable;
1248
1249         return 0;
1250 }
1251
1252 EXPORT_API int appcore_set_app_state(int state)
1253 {
1254         priv.state = state;
1255
1256         tmp_val = 1;
1257
1258         return 0;
1259 }
1260
1261 EXPORT_API int appcore_set_preinit_window_name(const char *win_name)
1262 {
1263         int ret = -1;
1264         void *preinit_window = NULL;
1265         const Evas *e = NULL;
1266
1267         if (!win_name) {
1268                 _ERR("invalid parameter");
1269                 return ret;
1270         }
1271
1272         preinit_window = elm_win_precreated_object_get();
1273         if (!preinit_window) {
1274                 _ERR("Failed to get preinit window");
1275                 return ret;
1276         }
1277
1278         e = evas_object_evas_get((const Evas_Object *)preinit_window);
1279         if (e) {
1280                 Ecore_Evas *ee = ecore_evas_ecore_evas_get(e);
1281                 if (ee) {
1282                         ecore_evas_name_class_set(ee, win_name, win_name);
1283                         ret = 0;
1284                 }
1285         }
1286
1287         return ret;
1288 }
1289
1290 EXPORT_API unsigned int appcore_get_main_window(void)
1291 {
1292         struct win_node *entry = NULL;
1293
1294         if (g_winnode_list != NULL) {
1295                 entry = g_winnode_list->data;
1296                 return (unsigned int) entry->win;
1297         }
1298
1299         return 0;
1300 }
1301
1302 #if defined(WAYLAND)
1303 EXPORT_API unsigned int appcore_get_main_surface(void)
1304 {
1305         struct win_node *entry = NULL;
1306
1307         if (g_winnode_list != NULL) {
1308                 entry = g_winnode_list->data;
1309                 return (unsigned int) entry->surf;
1310         }
1311
1312         return 0;
1313 }
1314 #endif
1315
1316 tizen_profile_t _get_tizen_profile()
1317 {
1318         static tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
1319         if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
1320                 return profile;
1321
1322         char *profileName;
1323         system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
1324         switch (*profileName) {
1325         case 'm':
1326         case 'M':
1327                 profile = TIZEN_PROFILE_MOBILE;
1328                 break;
1329         case 'w':
1330         case 'W':
1331                 profile = TIZEN_PROFILE_WEARABLE;
1332                 break;
1333         case 't':
1334         case 'T':
1335                 profile = TIZEN_PROFILE_TV;
1336                 break;
1337         case 'i':
1338         case 'I':
1339                 profile = TIZEN_PROFILE_IVI;
1340                 break;
1341         default: // common or unTIZEN_nown ==> ALL ARE COMMON.
1342                 profile = TIZEN_PROFILE_COMMON;
1343         }
1344         free(profileName);
1345
1346         return profile;
1347 }