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