518cfa4d95ba03fa5fd08e91e8433b0e1daaf8a2
[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 #include <Ecore_Wayland.h>
28 #include <wayland-client.h>
29 #include <wayland-tbm-client.h>
30 #include <tizen-extension-client-protocol.h>
31
32 #include <Ecore.h>
33 #include <Ecore_Evas.h>
34 #include <Ecore_Input_Evas.h>
35 #include <Elementary.h>
36 #include <glib-object.h>
37 #include <malloc.h>
38 #include <glib.h>
39 #include <gio/gio.h>
40 #include <stdbool.h>
41 #include <aul.h>
42 #include <aul_svc.h>
43 #include <bundle_internal.h>
44 #include <ttrace.h>
45
46 #include "appcore-internal.h"
47 #include "appcore-efl.h"
48 #include <system_info.h>
49
50 static pid_t _pid;
51 static bool resource_reclaiming = TRUE;
52 static int tmp_val = 0;
53
54 struct ui_priv {
55         const char *name;
56         enum app_state state;
57
58         Ecore_Event_Handler *hshow;
59         Ecore_Event_Handler *hhide;
60         Ecore_Event_Handler *hvchange;
61         Ecore_Event_Handler *hlower;
62         Ecore_Event_Handler *hcmsg; /* WM_ROTATE */
63
64         Ecore_Timer *mftimer; /* Ecore Timer for memory flushing */
65
66         struct appcore *app_core;
67         void (*prepare_to_suspend) (void *data);
68         void (*exit_from_suspend) (void *data);
69         struct appcore_ops *ops;
70         void (*mfcb) (void); /* Memory Flushing Callback */
71
72         /* WM_ROTATE */
73         int wm_rot_supported;
74         int rot_started;
75         int (*rot_cb) (void *event_info, enum appcore_rm, void *);
76         void *rot_cb_data;
77         enum appcore_rm rot_mode;
78         char *below_app;
79 };
80
81 static struct ui_priv priv;
82
83 static const char *_ae_name[AE_MAX] = {
84         [AE_UNKNOWN] = "UNKNOWN",
85         [AE_CREATE] = "CREATE",
86         [AE_TERMINATE] = "TERMINATE",
87         [AE_PAUSE] = "PAUSE",
88         [AE_RESUME] = "RESUME",
89         [AE_RESET] = "RESET",
90         [AE_LOWMEM_POST] = "LOWMEM_POST",
91         [AE_MEM_FLUSH] = "MEM_FLUSH",
92         [AE_UPDATE_REQUESTED] = "UPDATE_REQUESTED",
93 };
94
95 static const char *_as_name[] = {
96         [AS_NONE] = "NONE",
97         [AS_CREATED] = "CREATED",
98         [AS_RUNNING] = "RUNNING",
99         [AS_PAUSED] = "PAUSED",
100         [AS_DYING] = "DYING",
101 };
102
103 static bool b_active = FALSE;
104 static bool first_launch = TRUE;
105
106 struct win_node {
107         unsigned int win;
108         unsigned int surf;
109         bool bfobscured;
110 };
111
112 static Eina_Bool __visibility_cb(void *data, int type, void *event);
113 static GSList *g_winnode_list;
114
115 static struct wl_display *dsp;
116 static struct wl_registry *reg;
117 static struct tizen_policy *tz_policy;
118 static bool bg_state = false;
119
120 static void __wl_listener_cb(void *data, struct wl_registry *reg,
121                 uint32_t id, const char *interface, uint32_t ver)
122 {
123         if (interface && !strcmp(interface, "tizen_policy")) {
124                 if (!tz_policy)
125                         tz_policy = wl_registry_bind(reg, id,
126                                         &tizen_policy_interface, 1);
127         }
128 }
129
130 static void __wl_listener_remove_cb(void *data, struct wl_registry *reg,
131                 unsigned int id)
132 {
133         /* do nothing */
134 }
135
136 static const struct wl_registry_listener reg_listener = {
137         __wl_listener_cb,
138         __wl_listener_remove_cb
139 };
140
141 static int __init_wl(void)
142 {
143         _DBG("initialize wayland");
144         dsp = wl_display_connect(NULL);
145         if (dsp == NULL) {
146                 _ERR("Failed to connect wl display");
147                 return -1;
148         }
149
150         reg = wl_display_get_registry(dsp);
151         if (reg == NULL) {
152                 _ERR("Failed to get registry");
153                 wl_display_disconnect(dsp);
154                 return -1;
155         }
156
157         wl_registry_add_listener(reg, &reg_listener, NULL);
158         wl_display_roundtrip(dsp);
159
160         if (!tz_policy) {
161                 _ERR("Failed to get tizen policy interface");
162                 wl_registry_destroy(reg);
163                 wl_display_disconnect(dsp);
164                 return -1;
165         }
166
167         return 0;
168 }
169
170 static void __finish_wl(void)
171 {
172         if (tz_policy) {
173                 tizen_policy_destroy(tz_policy);
174                 tz_policy = NULL;
175         }
176
177         if (reg) {
178                 wl_registry_destroy(reg);
179                 reg = NULL;
180         }
181
182         if (dsp) {
183                 wl_display_disconnect(dsp);
184                 dsp = NULL;
185         }
186 }
187
188 static void __set_bg_state(void)
189 {
190         if (!tz_policy && __init_wl() < 0)
191                 return;
192
193         tizen_policy_set_background_state(tz_policy, getpid());
194         wl_display_roundtrip(dsp);
195         bg_state = true;
196         _DBG("bg state: %d", bg_state);
197 }
198
199 static void __unset_bg_state(void)
200 {
201         if (!tz_policy)
202                 return;
203
204         tizen_policy_unset_background_state(tz_policy, getpid());
205         wl_display_roundtrip(dsp);
206         bg_state = false;
207         _DBG("bg state: %d", bg_state);
208 }
209
210 static void __appcore_efl_prepare_to_suspend(void *data)
211 {
212         struct ui_priv *ui = (struct ui_priv *)data;
213         struct sys_op *op = NULL;
214         int suspend = APPCORE_SUSPENDED_STATE_WILL_ENTER_SUSPEND;
215
216         if (ui->app_core && !ui->app_core->allowed_bg && !ui->app_core->suspended_state) {
217                 op = &ui->app_core->sops[SE_SUSPENDED_STATE];
218                 if (op && op->func)
219                         op->func((void *)&suspend, op->data); /* calls c-api handler */
220
221                 ui->app_core->suspended_state = true;
222         }
223         _DBG("[__SUSPEND__]");
224 }
225
226 static void __appcore_efl_exit_from_suspend(void *data)
227 {
228         struct ui_priv *ui = (struct ui_priv *)data;
229         struct sys_op *op = NULL;
230         int suspend = APPCORE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
231
232         if (ui->app_core && !ui->app_core->allowed_bg && ui->app_core->suspended_state) {
233                 op = &ui->app_core->sops[SE_SUSPENDED_STATE];
234                 if (op && op->func)
235                         op->func((void *)&suspend, op->data); /* calls c-api handler */
236
237                 ui->app_core->suspended_state = false;
238         }
239         _DBG("[__SUSPEND__]");
240 }
241
242 static void __appcore_efl_update_requested(void *data)
243 {
244         struct ui_priv *ui = (struct ui_priv *)data;
245         struct sys_op *op;
246         int dummy = 0;
247
248         if (ui->app_core) {
249                 op = &ui->app_core->sops[SE_UPDATE_REQUESTED];
250                 if (op && op->func)
251                         op->func((void *)&dummy, op->data);
252         }
253         _DBG("[__UPDATE_REQUESTED__]");
254 }
255
256 #if defined(MEMORY_FLUSH_ACTIVATE)
257 static Eina_Bool __appcore_memory_flush_cb(void *data)
258 {
259         struct ui_priv *ui = (struct ui_priv *)data;
260
261         appcore_flush_memory();
262         if (ui)
263                 ui->mftimer = NULL;
264
265         if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT && ui && ui->prepare_to_suspend) {
266                 _DBG("[__SUSPEND__] flush case");
267                 ui->prepare_to_suspend(ui);
268         }
269
270         return ECORE_CALLBACK_CANCEL;
271 }
272
273 static int __appcore_low_memory_post_cb(struct ui_priv *ui)
274 {
275         if (ui->state == AS_PAUSED)
276                 appcore_flush_memory();
277         else
278                 malloc_trim(0);
279
280         return 0;
281 }
282
283 static void __appcore_timer_add(struct ui_priv *ui)
284 {
285         ui->mftimer = ecore_timer_add(5, __appcore_memory_flush_cb, ui);
286 }
287
288 static void __appcore_timer_del(struct ui_priv *ui)
289 {
290         if (ui->mftimer) {
291                 ecore_timer_del(ui->mftimer);
292                 ui->mftimer = NULL;
293         }
294 }
295
296 #else
297
298 static int __appcore_low_memory_post_cb(ui_priv *ui)
299 {
300         return -1;
301 }
302
303 #define __appcore_timer_add(ui) 0
304 #define __appcore_timer_del(ui) 0
305
306 #endif
307
308 static void __appcore_efl_memory_flush_cb(void)
309 {
310         _DBG("[APP %d]   __appcore_efl_memory_flush_cb()", _pid);
311         elm_cache_all_flush();
312 }
313 static void wl_raise_win(void)
314 {
315         Ecore_Wl_Window *win;
316         unsigned int win_id = appcore_get_main_window();
317
318         _DBG("Raise window: %d", win_id);
319         win = ecore_wl_window_find(win_id);
320         ecore_wl_window_activate(win);
321 }
322
323 static void wl_pause_win(void)
324 {
325         Ecore_Wl_Window *win;
326         GSList *wlist = g_winnode_list;
327         struct win_node *entry = NULL;
328
329         _DBG("Pause window");
330
331         while (wlist) {
332                 entry = wlist->data;
333
334                 _DBG("Pause window: %d", entry->win);
335                 win = ecore_wl_window_find(entry->win);
336                 ecore_wl_window_iconified_set(win, EINA_TRUE);
337
338                 wlist = wlist->next;
339         }
340 }
341
342
343 static void __do_app(enum app_event event, void *data, bundle * b)
344 {
345         int r = -1;
346         struct ui_priv *ui = data;
347         const char *below_app;
348         const char *bg_launch;
349
350         _DBG("[APP %d] Event: %d", _pid, event);
351         _ret_if(ui == NULL || event >= AE_MAX);
352         _DBG("[APP %d] Event: %s State: %s", _pid, _ae_name[event],
353              _as_name[ui->state]);
354
355         if (event == AE_MEM_FLUSH) {
356                 ui->mfcb();
357                 return;
358         }
359
360         if (event == AE_LOWMEM_POST) {
361                 if (__appcore_low_memory_post_cb(ui) == 0)
362                         return;
363         }
364
365         if (!(ui->state == AS_PAUSED && event == AE_PAUSE))
366                 __appcore_timer_del(ui);
367
368         if (ui->state == AS_DYING) {
369                 _ERR("Skip the event in dying state");
370                 return;
371         }
372
373         if (event == AE_TERMINATE) {
374                 _DBG("[APP %d] TERMINATE", _pid);
375                 elm_exit();
376                 aul_status_update(STATUS_DYING);
377                 return;
378         }
379
380         if (event == AE_RAISE) {
381                 if (bg_state)
382                         __unset_bg_state();
383                 wl_raise_win();
384                 return;
385         }
386
387         if (event == AE_LOWER) {
388                 wl_pause_win();
389                 return;
390         }
391
392         _ret_if(ui->ops == NULL);
393
394         switch (event) {
395         case AE_RESET:
396                 _DBG("[APP %d] RESET", _pid);
397                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]", ui->name);
398
399                 if (ui->below_app) {
400                         free(ui->below_app);
401                         ui->below_app = NULL;
402                 }
403
404                 below_app = bundle_get_val(b, AUL_SVC_K_RELOCATE_BELOW);
405                 if (below_app)
406                         ui->below_app = strdup(below_app);
407                 if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT && ui->exit_from_suspend) {
408                         _DBG("[__SUSPEND__] reset case");
409                         ui->exit_from_suspend(ui);
410                 }
411
412                 if (ui->ops->reset) {
413                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
414                                         "APPCORE:RESET");
415                         r = ui->ops->reset(b, ui->ops->data);
416                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
417                 }
418                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]", ui->name);
419
420                 if (first_launch) {
421                         if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT && ui->app_core->allowed_bg)
422                                 __appcore_timer_add(ui);
423                         first_launch = FALSE;
424                 } else {
425                         _INFO("[APP %d] App already running, raise the window", _pid);
426                         bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
427                         if (bg_launch && strcmp(bg_launch, "enable") == 0) {
428                                 if (!bg_state && ui->state != AS_RUNNING)
429                                         __set_bg_state();
430                         } else {
431                                 if (bg_state)
432                                         __unset_bg_state();
433                         }
434                         if (!bg_state)
435                                 wl_raise_win();
436                 }
437                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]",
438                     ui->name);
439                 break;
440         case AE_PAUSE:
441                 if (ui->state == AS_RUNNING) {
442                         _DBG("[APP %d] PAUSE", _pid);
443                         if (ui->ops->pause) {
444                                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
445                                                 "APPCORE:PAUSE");
446                                 r = ui->ops->pause(ui->ops->data);
447                                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
448                         }
449                         ui->state = AS_PAUSED;
450                         if (r >= 0 && resource_reclaiming == TRUE)
451                                 __appcore_timer_add(ui);
452                         else if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT && r >= 0 && resource_reclaiming == FALSE
453                                         && ui->prepare_to_suspend) {
454                                 _DBG("[__SUSPEND__] pause case");
455                                 ui->prepare_to_suspend(ui);
456                         }
457                 }
458                 /* TODO : rotation stop */
459                 /* r = appcore_pause_rotation_cb(); */
460                 aul_status_update(STATUS_BG);
461                 break;
462         case AE_RESUME:
463                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]",
464                                 ui->name);
465                 if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT) {
466                         if (ui->exit_from_suspend) {
467                                 _DBG("[__SUSPEND__] resume case");
468                                 ui->exit_from_suspend(ui);
469                         }
470                         if (ui->app_core->allowed_bg)
471                                 __appcore_timer_del(ui);
472                 }
473
474                 if (ui->state == AS_PAUSED || ui->state == AS_CREATED) {
475                         _DBG("[APP %d] RESUME", _pid);
476
477                         if (ui->ops->resume) {
478                                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
479                                         "APPCORE:RESUME");
480                                 ui->ops->resume(ui->ops->data);
481                                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
482                         }
483                         ui->state = AS_RUNNING;
484
485                         if (ui->below_app) {
486                                 aul_app_group_activate_below(ui->below_app);
487                                 free(ui->below_app);
488                                 ui->below_app = NULL;
489                         }
490                 }
491                 /*TODO : rotation start*/
492                 /* r = appcore_resume_rotation_cb(); */
493                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]",
494                     ui->name);
495                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:Launching:done]",
496                     ui->name);
497                 aul_status_update(STATUS_VISIBLE);
498                 break;
499         case AE_TERMINATE_BGAPP:
500                 if (ui->state == AS_PAUSED) {
501                         _DBG("[APP %d] is paused. TERMINATE", _pid);
502                         ui->state = AS_DYING;
503                         aul_status_update(STATUS_DYING);
504                         elm_exit();
505                 } else if (ui->state == AS_RUNNING) {
506                         _DBG("[APP %d] is running.", _pid);
507                 } else {
508                         _DBG("[APP %d] is another state", _pid);
509                 }
510                 break;
511         case AE_UPDATE_REQUESTED:
512                 __appcore_efl_update_requested(ui);
513                 break;
514         default:
515                 /* do nothing */
516                 break;
517         }
518 }
519
520 static struct ui_ops efl_ops = {
521         .data = &priv,
522         .cb_app = __do_app,
523 };
524
525 static bool __check_visible(void)
526 {
527         GSList *iter = NULL;
528         struct win_node *entry = NULL;
529
530         _DBG("[EVENT_TEST][EVENT] __check_visible\n");
531
532         for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
533                 entry = iter->data;
534                 _DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
535                 if (entry->bfobscured == FALSE)
536                         return TRUE;
537         }
538
539         return FALSE;
540 }
541
542 static GSList *__find_win(unsigned int win)
543 {
544         GSList *iter;
545         struct win_node *t;
546
547         for (iter = g_winnode_list; iter; iter = g_slist_next(iter)) {
548                 t = iter->data;
549                 if (t && t->win == win)
550                         return iter;
551         }
552
553         return NULL;
554 }
555
556 static bool __add_win(unsigned int win, unsigned int surf)
557 {
558         struct win_node *t;
559         GSList *f;
560
561         _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
562
563         f = __find_win(win);
564         if (f) {
565                 errno = ENOENT;
566                 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
567                 return FALSE;
568         }
569
570         t = calloc(1, sizeof(struct win_node));
571         if (t == NULL)
572                 return FALSE;
573
574         t->win = win;
575         t->surf = surf;
576         t->bfobscured = FALSE;
577
578         g_winnode_list = g_slist_append(g_winnode_list, t);
579
580         return TRUE;
581 }
582
583 static bool __delete_win(unsigned int win)
584 {
585         GSList *f;
586
587         f = __find_win(win);
588         if (!f) {
589                 errno = ENOENT;
590                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n",
591                                 win);
592                 return FALSE;
593         }
594
595         free(f->data);
596         g_winnode_list = g_slist_delete_link(g_winnode_list, f);
597
598         return TRUE;
599 }
600
601 static bool __update_win(unsigned int win, unsigned int surf, bool bfobscured)
602 {
603         GSList *f;
604         struct win_node *t;
605
606         _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
607              bfobscured);
608
609         f = __find_win(win);
610         if (!f) {
611                 errno = ENOENT;
612                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
613                 return FALSE;
614         }
615
616         t = (struct win_node *)f->data;
617         t->win = win;
618         if (surf != 0)
619                 t->surf = surf;
620         t->bfobscured = bfobscured;
621
622         return TRUE;
623 }
624
625 static Eina_Bool __show_cb(void *data, int type, void *event)
626 {
627         Ecore_Wl_Event_Window_Show *ev;
628
629         ev = event;
630         if (ev->parent_win != 0) {
631                 /* This is child window. Skip!!! */
632                 return ECORE_CALLBACK_PASS_ON;
633         }
634
635         _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x, %d\n", ev->win, ev->data[0]);
636
637         if (!__find_win((unsigned int)ev->win))
638                 __add_win((unsigned int)ev->win, (unsigned int)ev->data[0]);
639         else
640                 __update_win((unsigned int)ev->win, (unsigned int)ev->data[0], FALSE);
641
642         if (ev->data[0] != 0)
643                 appcore_group_attach();
644         return ECORE_CALLBACK_RENEW;
645 }
646
647 static Eina_Bool __hide_cb(void *data, int type, void *event)
648 {
649         Ecore_Wl_Event_Window_Hide *ev;
650         int bvisibility = 0;
651
652         ev = event;
653
654         _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
655
656         if (__find_win((unsigned int)ev->win)) {
657                 __delete_win((unsigned int)ev->win);
658                 bvisibility = __check_visible();
659                 if (!bvisibility && b_active == TRUE) {
660                         _DBG(" Go to Pasue state \n");
661                         b_active = FALSE;
662                         __do_app(AE_PAUSE, data, NULL);
663                 }
664         }
665
666         return ECORE_CALLBACK_RENEW;
667 }
668
669 static Eina_Bool __lower_cb(void *data, int type, void *event)
670 {
671         Ecore_Wl_Event_Window_Lower *ev;
672         ev = event;
673         if (!ev) return ECORE_CALLBACK_RENEW;
674         _DBG("ECORE_WL_EVENT_WINDOW_LOWER window id:%u\n", ev->win);
675         appcore_group_lower();
676         return ECORE_CALLBACK_RENEW;
677 }
678
679 static Eina_Bool __visibility_cb(void *data, int type, void *event)
680 {
681         Ecore_Wl_Event_Window_Visibility_Change *ev;
682         int bvisibility = 0;
683         ev = event;
684         __update_win((unsigned int)ev->win, 0, ev->fully_obscured);
685         bvisibility = __check_visible();
686
687         _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
688
689         if (bvisibility && b_active == FALSE) {
690                 _DBG(" Go to Resume state\n");
691                 b_active = TRUE;
692                 __do_app(AE_RESUME, data, NULL);
693
694         } else if (!bvisibility && b_active == TRUE) {
695                 _DBG(" Go to Pasue state \n");
696                 b_active = FALSE;
697                 __do_app(AE_PAUSE, data, NULL);
698         } else
699                 _DBG(" No change state \n");
700
701         return ECORE_CALLBACK_RENEW;
702
703 }
704
705 static void __add_climsg_cb(struct ui_priv *ui)
706 {
707         _ret_if(ui == NULL);
708         ui->hshow =
709                 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_SHOW, __show_cb, ui);
710         ui->hhide =
711                 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_HIDE, __hide_cb, ui);
712         ui->hvchange =
713                 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
714                                 __visibility_cb, ui);
715         ui->hlower =
716                 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_LOWER,
717                                 __lower_cb, ui);
718 }
719
720 static int __before_loop(struct ui_priv *ui, int *argc, char ***argv)
721 {
722         int r;
723         char *hwacc = NULL;
724         struct appcore *ac = NULL;
725         bundle *b;
726         const char *bg_launch;
727
728         if (argc == NULL || argv == NULL) {
729                 _ERR("argc/argv is NULL");
730                 errno = EINVAL;
731                 return -1;
732         }
733
734 #if !(GLIB_CHECK_VERSION(2, 36, 0))
735         g_type_init();
736 #endif
737         elm_init(*argc, *argv);
738
739         hwacc = getenv("HWACC");
740         if (hwacc == NULL) {
741                 _DBG("elm_config_accel_preference_set is not called");
742         } else if (strcmp(hwacc, "USE") == 0) {
743                 elm_config_accel_preference_set("hw");
744                 _DBG("elm_config_accel_preference_set : hw");
745         } else if (strcmp(hwacc, "NOT_USE") == 0) {
746                 elm_config_accel_preference_set("none");
747                 _DBG("elm_config_accel_preference_set : none");
748         } else {
749                 _DBG("elm_config_accel_preference_set is not called");
750         }
751
752         r = appcore_init(ui->name, &efl_ops, *argc, *argv);
753         _retv_if(r == -1, -1);
754
755         if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT) {
756                 appcore_get_app_core(&ac);
757                 ui->app_core = ac;
758                 SECURE_LOGD("[__SUSPEND__] appcore initialized, appcore addr: #%x", ac);
759         }
760
761         b = bundle_import_from_argv(*argc, *argv);
762         if (b) {
763                 bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
764                 if (bg_launch && strcmp(bg_launch, "enable") == 0)
765                         __set_bg_state();
766
767                 bundle_free(b);
768         }
769
770         LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:appcore_init:done]", ui->name);
771         if (ui->ops && ui->ops->create) {
772                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:CREATE");
773                 r = ui->ops->create(ui->ops->data);
774                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
775                 if (r < 0) {
776                         _ERR("create() return error");
777                         appcore_exit();
778                         if (ui->ops && ui->ops->terminate) {
779                                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
780                                         "APPCORE:TERMINATE");
781                                 ui->ops->terminate(ui->ops->data);
782                                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
783                         }
784                         errno = ECANCELED;
785                         return -1;
786                 }
787                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]",
788                     ui->name);
789         }
790         ui->state = AS_CREATED;
791
792         __add_climsg_cb(ui);
793
794         return 0;
795 }
796
797 static void __after_loop(struct ui_priv *ui)
798 {
799         appcore_unset_rotation_cb();
800         appcore_exit();
801
802         if (ui->state == AS_RUNNING) {
803                 _DBG("[APP %d] PAUSE before termination", _pid);
804                 if (ui->ops && ui->ops->pause) {
805                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
806                                         "APPCORE:PAUSE");
807                         ui->ops->pause(ui->ops->data);
808                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
809                 }
810         }
811
812         if (ui->ops && ui->ops->terminate) {
813                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:TERMINATE");
814                 ui->ops->terminate(ui->ops->data);
815                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
816         }
817
818         ui->state = AS_DYING;
819
820         if (ui->hshow)
821                 ecore_event_handler_del(ui->hshow);
822         if (ui->hhide)
823                 ecore_event_handler_del(ui->hhide);
824         if (ui->hvchange)
825                 ecore_event_handler_del(ui->hvchange);
826         if (ui->hlower)
827                 ecore_event_handler_del(ui->hlower);
828
829         __appcore_timer_del(ui);
830         __finish_wl();
831
832         elm_shutdown();
833
834         /* Check loader case */
835         if (getenv("AUL_LOADER_INIT")) {
836                 unsetenv("AUL_LOADER_INIT");
837                 elm_shutdown();
838         }
839 }
840
841 static int __set_data(struct ui_priv *ui, const char *name,
842                     struct appcore_ops *ops)
843 {
844         if (ui->name) {
845                 _ERR("Mainloop already started");
846                 errno = EINPROGRESS;
847                 return -1;
848         }
849
850         if (name == NULL || name[0] == '\0') {
851                 _ERR("Invalid name");
852                 errno = EINVAL;
853                 return -1;
854         }
855
856         if (ops == NULL) {
857                 _ERR("ops is NULL");
858                 errno = EINVAL;
859                 return -1;
860         }
861
862         ui->name = strdup(name);
863         _retv_if(ui->name == NULL, -1);
864
865         ui->ops = ops;
866         ui->mfcb = __appcore_efl_memory_flush_cb;
867         _pid = getpid();
868
869         /* WM_ROTATE */
870         ui->wm_rot_supported = 0;
871         ui->rot_started = 0;
872         ui->rot_cb = NULL;
873         ui->rot_cb_data = NULL;
874         ui->rot_mode = APPCORE_RM_UNKNOWN;
875
876         if (_APPFW_FEATURE_BACKGROUND_MANAGEMENT) {
877                 ui->app_core = NULL;
878                 ui->prepare_to_suspend = __appcore_efl_prepare_to_suspend;
879                 ui->exit_from_suspend = __appcore_efl_exit_from_suspend;
880         }
881
882         return 0;
883 }
884
885 static void __unset_data(struct ui_priv *ui)
886 {
887         if (ui->name)
888                 free((void *)ui->name);
889
890         memset(ui, 0, sizeof(struct ui_priv));
891 }
892
893 EXPORT_API int appcore_efl_init(const char *name, int *argc, char ***argv,
894                      struct appcore_ops *ops)
895 {
896         int r;
897
898         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", name);
899
900         r = __set_data(&priv, name, ops);
901         _retv_if(r == -1, -1);
902
903         r = __before_loop(&priv, argc, argv);
904         if (r == -1) {
905                 aul_status_update(STATUS_DYING);
906                 __unset_data(&priv);
907                 return -1;
908         }
909
910         return 0;
911 }
912
913 EXPORT_API void appcore_efl_fini(void)
914 {
915         aul_status_update(STATUS_DYING);
916
917         __after_loop(&priv);
918
919         __unset_data(&priv);
920 }
921
922 EXPORT_API int appcore_efl_main(const char *name, int *argc, char ***argv,
923                                 struct appcore_ops *ops)
924 {
925         int r;
926
927         r = appcore_efl_init(name, argc, argv, ops);
928         _retv_if(r == -1, -1);
929
930         elm_run();
931
932         appcore_efl_fini();
933
934         return 0;
935 }
936
937 EXPORT_API int appcore_set_system_resource_reclaiming(bool enable)
938 {
939         resource_reclaiming = enable;
940
941         return 0;
942 }
943
944 EXPORT_API int appcore_set_app_state(int state)
945 {
946         priv.state = state;
947
948         tmp_val = 1;
949
950         return 0;
951 }
952
953 EXPORT_API int appcore_set_preinit_window_name(const char *win_name)
954 {
955         int ret = -1;
956         void *preinit_window = NULL;
957         const Evas *e = NULL;
958
959         if (!win_name) {
960                 _ERR("invalid parameter");
961                 return ret;
962         }
963
964         preinit_window = elm_win_precreated_object_get();
965         if (!preinit_window) {
966                 _ERR("Failed to get preinit window");
967                 return ret;
968         }
969
970         e = evas_object_evas_get((const Evas_Object *)preinit_window);
971         if (e) {
972                 Ecore_Evas *ee = ecore_evas_ecore_evas_get(e);
973                 if (ee) {
974                         ecore_evas_name_class_set(ee, win_name, win_name);
975                         ret = 0;
976                 }
977         }
978
979         return ret;
980 }
981
982 EXPORT_API unsigned int appcore_get_main_window(void)
983 {
984         struct win_node *entry = NULL;
985
986         if (g_winnode_list != NULL) {
987                 entry = g_winnode_list->data;
988                 return (unsigned int) entry->win;
989         }
990
991         return 0;
992 }
993
994 EXPORT_API unsigned int appcore_get_main_surface(void)
995 {
996         struct win_node *entry = NULL;
997
998         if (g_winnode_list != NULL) {
999                 entry = g_winnode_list->data;
1000                 return (unsigned int) entry->surf;
1001         }
1002
1003         return 0;
1004 }
1005
1006 tizen_profile_t _get_tizen_profile()
1007 {
1008         static tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
1009         if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
1010                 return profile;
1011
1012         char *profileName;
1013         system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
1014         switch (*profileName) {
1015         case 'm':
1016         case 'M':
1017                 profile = TIZEN_PROFILE_MOBILE;
1018                 break;
1019         case 'w':
1020         case 'W':
1021                 profile = TIZEN_PROFILE_WEARABLE;
1022                 break;
1023         case 't':
1024         case 'T':
1025                 profile = TIZEN_PROFILE_TV;
1026                 break;
1027         case 'i':
1028         case 'I':
1029                 profile = TIZEN_PROFILE_IVI;
1030                 break;
1031         default: // common or unTIZEN_nown ==> ALL ARE COMMON.
1032                 profile = TIZEN_PROFILE_COMMON;
1033         }
1034         free(profileName);
1035
1036         return profile;
1037 }