Remove a ui_app_get_default_window api
[platform/core/api/application.git] / src / app_main.c
1 /*
2  * Copyright (c) 2011 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 <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24
25 #include <bundle.h>
26 #include <appcore-common.h>
27 #include <appcore-efl.h>
28 #include <aul.h>
29 #include <dlog.h>
30
31 #include <Elementary.h>
32
33 #include <app_internal.h>
34 #include <app_control_internal.h>
35 #include <tizen_error.h>
36
37 #include "app_extension.h"
38
39 #ifdef LOG_TAG
40 #undef LOG_TAG
41 #endif
42
43 #define LOG_TAG "CAPI_APPFW_APPLICATION"
44
45 typedef enum {
46         APP_STATE_NOT_RUNNING, /* The application has been launched or was running but was terminated */
47         APP_STATE_CREATING, /* The application is initializing the resources on app_create_cb callback */
48         APP_STATE_RUNNING, /* The application is running in the foreground and background */
49 } app_state_e;
50
51 typedef struct {
52         char *package;
53         char *app_name;
54         app_state_e state;
55         app_event_callback_s *callback;
56         void *data;
57 } app_context_s;
58
59 typedef app_context_s *app_context_h;
60
61 static int app_appcore_create(void *data);
62 static int app_appcore_pause(void *data);
63 static int app_appcore_resume(void *data);
64 static int app_appcore_terminate(void *data);
65 static int app_appcore_reset(bundle *appcore_bundle, void *data);
66
67 static int app_appcore_low_memory(void *event, void *data);
68 static int app_appcore_low_battery(void *event, void *data);
69 static int app_appcore_rotation_event(void *event, enum appcore_rm rm, void *data);
70 static int app_appcore_lang_changed(void *event, void *data);
71 static int app_appcore_region_changed(void *event, void *data);
72
73 static void app_set_appcore_event_cb(app_context_h app_context);
74 static void app_unset_appcore_event_cb(void);
75
76 int app_main(int argc, char **argv, app_event_callback_s *callback, void *user_data)
77 {
78         return app_efl_main(&argc, &argv, callback, user_data);
79 }
80
81 int app_efl_main(int *argc, char ***argv, app_event_callback_s *callback, void *user_data)
82 {
83         app_context_s app_context = {
84                 .package = NULL,
85                 .app_name = NULL,
86                 .state = APP_STATE_NOT_RUNNING,
87                 .callback = callback,
88                 .data = user_data
89         };
90
91         struct appcore_ops appcore_context = {
92                 .data = &app_context,
93                 .create = app_appcore_create,
94                 .terminate = app_appcore_terminate,
95                 .pause = app_appcore_pause,
96                 .resume = app_appcore_resume,
97                 .reset = app_appcore_reset,
98         };
99
100         if (argc == NULL || argv == NULL || callback == NULL)
101                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
102
103         if (callback->create == NULL)
104                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "app_create_cb() callback must be registered");
105
106         if (app_context.state != APP_STATE_NOT_RUNNING)
107                 return app_error(APP_ERROR_ALREADY_RUNNING, __FUNCTION__, NULL);
108
109         if (app_get_id(&(app_context.package)) != APP_ERROR_NONE)
110                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package");
111
112         if (app_get_package_app_name(app_context.package, &(app_context.app_name)) != APP_ERROR_NONE) {
113                 free(app_context.package);
114                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package's app name");
115         }
116
117         app_context.state = APP_STATE_CREATING;
118
119         appcore_efl_main(app_context.app_name, argc, argv, &appcore_context);
120
121         free(app_context.package);
122         free(app_context.app_name);
123
124         return APP_ERROR_NONE;
125 }
126
127 void app_exit(void)
128 {
129         app_efl_exit();
130 }
131
132 void app_efl_exit(void)
133 {
134         elm_exit();
135 }
136
137 int app_appcore_create(void *data)
138 {
139         app_context_h app_context = data;
140         app_create_cb create_cb;
141         char locale_dir[TIZEN_PATH_MAX] = {0, };
142
143         if (app_context == NULL)
144                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
145
146         app_set_appcore_event_cb(app_context);
147
148         snprintf(locale_dir, TIZEN_PATH_MAX, "%s/%s" PATH_FMT_RES_DIR
149                         PATH_FMT_LOCALE_DIR, PATH_FMT_APP_ROOT, app_context->package);
150         if (access(locale_dir, R_OK) != 0) {
151                 snprintf(locale_dir, TIZEN_PATH_MAX, "%s/%s" PATH_FMT_RO_RES_DIR
152                                 PATH_FMT_RO_LOCALE_DIR, PATH_FMT_RO_APP_ROOT, app_context->package);
153         }
154         appcore_set_i18n(app_context->app_name, locale_dir);
155
156         create_cb = app_context->callback->create;
157         if (create_cb == NULL || create_cb(app_context->data) == false)
158                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "app_create_cb() returns false");
159
160         app_context->state = APP_STATE_RUNNING;
161
162         return APP_ERROR_NONE;
163 }
164
165 int app_appcore_terminate(void *data)
166 {
167         app_context_h app_context = data;
168         app_terminate_cb terminate_cb;
169
170         if (app_context == NULL)
171                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
172
173         terminate_cb = app_context->callback->terminate;
174
175         if (terminate_cb != NULL)
176                 terminate_cb(app_context->data);
177
178         app_unset_appcore_event_cb();
179
180         app_finalizer_execute();
181
182         return APP_ERROR_NONE;
183 }
184
185 int app_appcore_pause(void *data)
186 {
187         app_context_h app_context = data;
188         app_pause_cb pause_cb;
189
190         if (app_context == NULL)
191                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
192
193         pause_cb = app_context->callback->pause;
194         if (pause_cb != NULL)
195                 pause_cb(app_context->data);
196
197         return APP_ERROR_NONE;
198 }
199
200 int app_appcore_resume(void *data)
201 {
202         app_context_h app_context = data;
203         app_resume_cb resume_cb;
204
205         if (app_context == NULL)
206                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
207
208         resume_cb = app_context->callback->resume;
209         if (resume_cb != NULL)
210                 resume_cb(app_context->data);
211
212         return APP_ERROR_NONE;
213 }
214
215 int app_appcore_reset(bundle *appcore_bundle, void *data)
216 {
217         app_context_h app_context = data;
218         app_control_cb callback;
219         app_control_h app_control;
220
221         if (app_context == NULL)
222                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
223
224         if (app_control_create_event(appcore_bundle, &app_control) != APP_ERROR_NONE)
225                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create a service handle from the bundle");
226
227         callback = app_context->callback->app_control;
228         if (callback != NULL)
229                 callback(app_control, app_context->data);
230
231         app_control_destroy(app_control);
232
233         return APP_ERROR_NONE;
234 }
235
236 int app_appcore_low_memory(void *event_info, void *data)
237 {
238         app_context_h app_context = data;
239         app_low_memory_cb low_memory_cb;
240
241         if (app_context == NULL)
242                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
243
244         low_memory_cb = app_context->callback->low_memory;
245         if (low_memory_cb != NULL)
246                 low_memory_cb(app_context->data);
247
248         return APP_ERROR_NONE;
249 }
250
251 int app_appcore_low_battery(void *event_info, void *data)
252 {
253         app_context_h app_context = data;
254         app_low_battery_cb low_battery_cb;
255
256         if (app_context == NULL)
257                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
258
259         low_battery_cb = app_context->callback->low_battery;
260         if (low_battery_cb != NULL)
261                 low_battery_cb(app_context->data);
262
263         return APP_ERROR_NONE;
264 }
265
266 int app_appcore_rotation_event(void *event_info, enum appcore_rm rm, void *data)
267 {
268         app_context_h app_context = data;
269         app_device_orientation_cb device_orientation_cb;
270
271         if (app_context == NULL)
272                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
273
274         device_orientation_cb = app_context->callback->device_orientation;
275         if (device_orientation_cb != NULL) {
276                 app_device_orientation_e dev_orientation;
277
278                 dev_orientation = app_convert_appcore_rm(rm);
279
280                 device_orientation_cb(dev_orientation, app_context->data);
281         }
282
283         return APP_ERROR_NONE;
284 }
285
286 int app_appcore_lang_changed(void *event_info, void *data)
287 {
288         app_context_h app_context = data;
289         app_language_changed_cb lang_changed_cb;
290
291         if (app_context == NULL)
292                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
293
294         lang_changed_cb = app_context->callback->language_changed;
295         if (lang_changed_cb != NULL)
296                 lang_changed_cb(app_context->data);
297
298         return APP_ERROR_NONE;
299 }
300
301 int app_appcore_region_changed(void *event_info, void *data)
302 {
303         app_context_h app_context = data;
304         app_region_format_changed_cb region_changed_cb;
305
306         if (app_context == NULL)
307                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
308
309         region_changed_cb = app_context->callback->region_format_changed;
310         if (region_changed_cb != NULL)
311                 region_changed_cb(app_context->data);
312
313         return APP_ERROR_NONE;
314 }
315
316 void app_set_appcore_event_cb(app_context_h app_context)
317 {
318         if (app_context->callback->low_memory != NULL)
319                 appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, app_appcore_low_memory, app_context);
320
321         if (app_context->callback->low_battery != NULL)
322                 appcore_set_event_callback(APPCORE_EVENT_LOW_BATTERY, app_appcore_low_battery, app_context);
323
324         if (app_context->callback->device_orientation != NULL)
325                 appcore_set_rotation_cb(app_appcore_rotation_event, app_context);
326
327         if (app_context->callback->language_changed != NULL)
328                 appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, app_appcore_lang_changed, app_context);
329
330         if (app_context->callback->region_format_changed != NULL)
331                 appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, app_appcore_region_changed, app_context);
332 }
333
334 void app_unset_appcore_event_cb(void)
335 {
336         appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, NULL, NULL);
337         appcore_set_event_callback(APPCORE_EVENT_LOW_BATTERY, NULL, NULL);
338         appcore_unset_rotation_cb();
339         appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, NULL, NULL);
340         appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, NULL, NULL);
341 }
342
343 #define UI_APP_EVENT_MAX 6
344 static Eina_List *handler_list[UI_APP_EVENT_MAX] = {NULL, };
345 static int handler_initialized = 0;
346 static int appcore_initialized = 0;
347
348 struct ui_app_context {
349         char *package;
350         char *app_name;
351         app_state_e state;
352         ui_app_lifecycle_callback_s *callback;
353         void *data;
354 };
355
356 static void _free_handler_list(void)
357 {
358         int i;
359         app_event_handler_h handler;
360
361         for (i = 0; i < UI_APP_EVENT_MAX; i++) {
362                 EINA_LIST_FREE(handler_list[i], handler)
363                         if (handler)
364                                 free(handler);
365         }
366
367         eina_shutdown();
368 }
369
370 static int _ui_app_appcore_low_memory(void *event_info, void *data)
371 {
372         Eina_List *l;
373         app_event_handler_h handler;
374         struct app_event_info event;
375
376         LOGI("_app_appcore_low_memory");
377
378         event.type = APP_EVENT_LOW_MEMORY;
379         event.value = event_info;
380
381         EINA_LIST_FOREACH(handler_list[APP_EVENT_LOW_MEMORY], l, handler) {
382                 handler->cb(&event, handler->data);
383         }
384
385         return APP_ERROR_NONE;
386 }
387
388 static int _ui_app_appcore_low_battery(void *event_info, void *data)
389 {
390         Eina_List *l;
391         app_event_handler_h handler;
392         struct app_event_info event;
393
394         LOGI("_ui_app_appcore_low_battery");
395
396         event.type = APP_EVENT_LOW_BATTERY;
397         event.value = event_info;
398
399         EINA_LIST_FOREACH(handler_list[APP_EVENT_LOW_BATTERY], l, handler) {
400                 handler->cb(&event, handler->data);
401         }
402
403         return APP_ERROR_NONE;
404 }
405
406 static int _ui_app_appcore_rotation_event(void *event_info, enum appcore_rm rm, void *data)
407 {
408         Eina_List *l;
409         app_event_handler_h handler;
410         struct app_event_info event;
411
412         LOGI("_ui_app_appcore_rotation_event");
413
414         event.type = APP_EVENT_DEVICE_ORIENTATION_CHANGED;
415         event.value = event_info;
416
417         EINA_LIST_FOREACH(handler_list[APP_EVENT_DEVICE_ORIENTATION_CHANGED], l, handler) {
418                 handler->cb(&event, handler->data);
419         }
420
421         return APP_ERROR_NONE;
422 }
423
424 static int _ui_app_appcore_lang_changed(void *event_info, void *data)
425 {
426         Eina_List *l;
427         app_event_handler_h handler;
428         struct app_event_info event;
429
430         LOGI("_ui_app_appcore_lang_changed");
431
432         event.type = APP_EVENT_LANGUAGE_CHANGED;
433         event.value = event_info;
434
435         EINA_LIST_FOREACH(handler_list[APP_EVENT_LANGUAGE_CHANGED], l, handler) {
436                 handler->cb(&event, handler->data);
437         }
438
439         return APP_ERROR_NONE;
440 }
441
442 static int _ui_app_appcore_region_changed(void *event_info, void *data)
443 {
444         Eina_List *l;
445         app_event_handler_h handler;
446         struct app_event_info event;
447
448         if (event_info == NULL) {
449                 LOGI("receive empty event, ignore it");
450                 return APP_ERROR_NONE;
451         }
452
453         LOGI("_ui_app_appcore_region_changed");
454
455         event.type = APP_EVENT_REGION_FORMAT_CHANGED;
456         event.value = event_info;
457
458         EINA_LIST_FOREACH(handler_list[APP_EVENT_REGION_FORMAT_CHANGED], l, handler) {
459                 handler->cb(&event, handler->data);
460         }
461
462         return APP_ERROR_NONE;
463 }
464
465 static int _ui_app_appcore_suspended_state_changed(void *event_info, void *data)
466 {
467         Eina_List *l;
468         app_event_handler_h handler;
469         struct app_event_info event;
470
471         LOGI("_ui_app_appcore_suspended_state_changed");
472         LOGI("[__SUSPEND__] suspended state: %d (0: suspend, 1: wake)", *(int*)event_info);
473
474         event.type = APP_EVENT_SUSPENDED_STATE_CHANGED;
475         event.value = event_info;
476
477         EINA_LIST_FOREACH(handler_list[APP_EVENT_SUSPENDED_STATE_CHANGED], l, handler) {
478                 handler->cb(&event, handler->data);
479         }
480
481         return APP_ERROR_NONE;
482 }
483
484 static void _ui_app_appcore_set_event_cb(app_event_type_e event_type)
485 {
486         switch (event_type) {
487         case APP_EVENT_LOW_MEMORY:
488                 appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, _ui_app_appcore_low_memory, NULL);
489                 break;
490         case APP_EVENT_LOW_BATTERY:
491                 appcore_set_event_callback(APPCORE_EVENT_LOW_BATTERY, _ui_app_appcore_low_battery, NULL);
492                 break;
493         case APP_EVENT_LANGUAGE_CHANGED:
494                 appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, _ui_app_appcore_lang_changed, NULL);
495                 break;
496         case APP_EVENT_DEVICE_ORIENTATION_CHANGED:
497                 appcore_set_rotation_cb(_ui_app_appcore_rotation_event, NULL);
498                 break;
499         case APP_EVENT_REGION_FORMAT_CHANGED:
500                 appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, _ui_app_appcore_region_changed, NULL);
501                 break;
502         case APP_EVENT_SUSPENDED_STATE_CHANGED:
503                 LOGI("[__SUSPEND__]");
504                 appcore_set_event_callback(APPCORE_EVENT_SUSPENDED_STATE_CHANGE, _ui_app_appcore_suspended_state_changed, NULL);
505                 break;
506         default:
507                 break;
508         }
509 }
510
511 static void _ui_app_appcore_unset_event_cb(app_event_type_e event_type)
512 {
513         switch (event_type) {
514         case APP_EVENT_LOW_MEMORY:
515                 appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, NULL, NULL);
516                 break;
517         case APP_EVENT_LOW_BATTERY:
518                 appcore_set_event_callback(APPCORE_EVENT_LOW_BATTERY, NULL, NULL);
519                 break;
520         case APP_EVENT_LANGUAGE_CHANGED:
521                 appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, NULL, NULL);
522                 break;
523         case APP_EVENT_DEVICE_ORIENTATION_CHANGED:
524                 appcore_unset_rotation_cb();
525                 break;
526         case APP_EVENT_REGION_FORMAT_CHANGED:
527                 appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, NULL, NULL);
528                 break;
529         case APP_EVENT_SUSPENDED_STATE_CHANGED:
530                 LOGI("[__SUSPEND__]");
531                 appcore_set_event_callback(APPCORE_EVENT_SUSPENDED_STATE_CHANGE, NULL, NULL);
532                 break;
533         default:
534                 break;
535         }
536 }
537
538 static void _ui_app_set_appcore_event_cb(void)
539 {
540         _ui_app_appcore_set_event_cb(APP_EVENT_LOW_MEMORY);
541         _ui_app_appcore_set_event_cb(APP_EVENT_LANGUAGE_CHANGED);
542         _ui_app_appcore_set_event_cb(APP_EVENT_REGION_FORMAT_CHANGED);
543
544         if (eina_list_count(handler_list[APP_EVENT_LOW_BATTERY]) > 0)
545                 _ui_app_appcore_set_event_cb(APP_EVENT_LOW_BATTERY);
546         if (eina_list_count(handler_list[APP_EVENT_DEVICE_ORIENTATION_CHANGED]) > 0)
547                 _ui_app_appcore_set_event_cb(APP_EVENT_DEVICE_ORIENTATION_CHANGED);
548         if (eina_list_count(handler_list[APP_EVENT_SUSPENDED_STATE_CHANGED]) > 0)
549                 _ui_app_appcore_set_event_cb(APP_EVENT_SUSPENDED_STATE_CHANGED);
550 }
551
552 static void _ui_app_unset_appcore_event_cb(void)
553 {
554         _ui_app_appcore_unset_event_cb(APP_EVENT_LOW_MEMORY);
555         _ui_app_appcore_unset_event_cb(APP_EVENT_LANGUAGE_CHANGED);
556         _ui_app_appcore_unset_event_cb(APP_EVENT_REGION_FORMAT_CHANGED);
557
558         if (eina_list_count(handler_list[APP_EVENT_LOW_BATTERY]) > 0)
559                 _ui_app_appcore_unset_event_cb(APP_EVENT_LOW_BATTERY);
560         if (eina_list_count(handler_list[APP_EVENT_DEVICE_ORIENTATION_CHANGED]) > 0)
561                 _ui_app_appcore_unset_event_cb(APP_EVENT_DEVICE_ORIENTATION_CHANGED);
562         if (eina_list_count(handler_list[APP_EVENT_SUSPENDED_STATE_CHANGED]) > 0)
563                 _ui_app_appcore_unset_event_cb(APP_EVENT_SUSPENDED_STATE_CHANGED);
564 }
565
566 static int _ui_app_appcore_create(void *data)
567 {
568         LOGI("app_appcore_create");
569         struct ui_app_context *app_context = data;
570         app_create_cb create_cb;
571
572         if (app_context == NULL)
573                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
574
575         appcore_initialized = 1;
576         _ui_app_set_appcore_event_cb();
577
578         create_cb = app_context->callback->create;
579
580         if (create_cb == NULL || create_cb(app_context->data) == false)
581                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "app_create_cb() returns false");
582
583         app_context->state = APP_STATE_RUNNING;
584
585         return APP_ERROR_NONE;
586 }
587
588 static int _ui_app_appcore_terminate(void *data)
589 {
590         LOGI("app_appcore_terminate");
591         struct ui_app_context *app_context = data;
592         app_terminate_cb terminate_cb;
593
594         if (app_context == NULL)
595                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
596
597         terminate_cb = app_context->callback->terminate;
598
599         if (terminate_cb != NULL)
600                 terminate_cb(app_context->data);
601
602         _ui_app_unset_appcore_event_cb();
603
604         app_finalizer_execute();
605
606         if (handler_initialized) {
607                 _free_handler_list();
608                 handler_initialized = 0;
609         }
610
611         return APP_ERROR_NONE;
612 }
613
614 static int _ui_app_appcore_pause(void *data)
615 {
616         LOGI("app_appcore_pause");
617         struct ui_app_context *app_context = data;
618         app_pause_cb pause_cb;
619
620         if (app_context == NULL)
621                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
622
623         pause_cb = app_context->callback->pause;
624
625         if (pause_cb != NULL)
626                 pause_cb(app_context->data);
627
628         return APP_ERROR_NONE;
629 }
630
631 static int _ui_app_appcore_resume(void *data)
632 {
633         LOGI("app_appcore_resume");
634         struct ui_app_context *app_context = data;
635         app_resume_cb resume_cb;
636
637         if (app_context == NULL)
638                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
639
640         resume_cb = app_context->callback->resume;
641
642         if (resume_cb != NULL)
643                 resume_cb(app_context->data);
644
645         return APP_ERROR_NONE;
646 }
647
648
649 static int _ui_app_appcore_reset(bundle *appcore_bundle, void *data)
650 {
651         LOGI("app_appcore_reset");
652         struct ui_app_context *app_context = data;
653         app_control_cb callback;
654         app_control_h app_control;
655         int ret;
656
657         if (app_context == NULL)
658                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
659
660         if (appcore_bundle) {
661                 if (app_control_create_event(appcore_bundle, &app_control) != APP_ERROR_NONE)
662                         return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create an app_control handle from the bundle");
663         } else {
664                 ret = app_control_create(&app_control);
665                 if (ret != APP_ERROR_NONE)
666                         return app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create an app_control");
667         }
668
669         callback = app_context->callback->app_control;
670
671         if (callback != NULL)
672                 callback(app_control, app_context->data);
673
674         app_control_destroy(app_control);
675
676         return APP_ERROR_NONE;
677 }
678
679 int ui_app_main(int argc, char **argv, ui_app_lifecycle_callback_s *callback, void *user_data)
680 {
681         struct ui_app_context app_context = {
682                 .package = NULL,
683                 .app_name = NULL,
684                 .state = APP_STATE_NOT_RUNNING,
685                 .callback = callback,
686                 .data = user_data
687         };
688
689         struct appcore_ops appcore_context = {
690                 .data = &app_context,
691                 .create = _ui_app_appcore_create,
692                 .terminate = _ui_app_appcore_terminate,
693                 .pause = _ui_app_appcore_pause,
694                 .resume = _ui_app_appcore_resume,
695                 .reset = _ui_app_appcore_reset,
696         };
697
698         if (argc < 1 || argv == NULL || callback == NULL)
699                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
700
701         if (callback->create == NULL)
702                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "app_create_cb() callback must be registered");
703
704         if (app_context.state != APP_STATE_NOT_RUNNING)
705                 return app_error(APP_ERROR_ALREADY_RUNNING, __FUNCTION__, NULL);
706
707         if (app_get_id(&(app_context.package)) != APP_ERROR_NONE)
708                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package");
709
710         if (app_get_package_app_name(app_context.package, &(app_context.app_name)) != APP_ERROR_NONE) {
711                 free(app_context.package);
712                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package's app name");
713         }
714
715         app_context.state = APP_STATE_CREATING;
716
717         LOGI("app_efl_main");
718         appcore_efl_main(app_context.app_name, &argc, &argv, &appcore_context);
719
720         free(app_context.package);
721         free(app_context.app_name);
722
723         return APP_ERROR_NONE;
724 }
725
726 void ui_app_exit(void)
727 {
728         app_efl_exit();
729 }
730
731 int ui_app_add_event_handler(app_event_handler_h *event_handler, app_event_type_e event_type, app_event_cb callback, void *user_data)
732 {
733         app_event_handler_h handler;
734         Eina_List *l_itr;
735
736         if (!handler_initialized) {
737                 eina_init();
738                 handler_initialized = 1;
739         }
740
741         if (event_handler == NULL || callback == NULL)
742                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "null parameter");
743
744         if (event_type < APP_EVENT_LOW_MEMORY || event_type > APP_EVENT_SUSPENDED_STATE_CHANGED)
745                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid event type");
746
747         EINA_LIST_FOREACH(handler_list[event_type], l_itr, handler) {
748                 if (handler->cb == callback)
749                         return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "already registered");
750         }
751
752         handler = calloc(1, sizeof(struct app_event_handler));
753         if (!handler)
754                 return app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create handler");
755
756         handler->type = event_type;
757         handler->cb = callback;
758         handler->data = user_data;
759
760         if (appcore_initialized && eina_list_count(handler_list[event_type]) == 0)
761                 _ui_app_appcore_set_event_cb(event_type);
762
763         handler_list[event_type] = eina_list_append(handler_list[event_type], handler);
764
765         *event_handler = handler;
766
767         return APP_ERROR_NONE;
768 }
769
770 int ui_app_remove_event_handler(app_event_handler_h event_handler)
771 {
772         app_event_handler_h handler;
773         app_event_type_e type;
774         Eina_List *l_itr;
775         Eina_List *l_next;
776
777         if (event_handler == NULL)
778                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "handler is null");
779
780         if (!handler_initialized) {
781                 LOGI("handler list is not initialized");
782                 return APP_ERROR_NONE;
783         }
784
785         type = event_handler->type;
786         if (type < APP_EVENT_LOW_MEMORY || type > APP_EVENT_SUSPENDED_STATE_CHANGED)
787                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid handler");
788
789         EINA_LIST_FOREACH_SAFE(handler_list[type], l_itr, l_next, handler) {
790                 if (handler == event_handler) {
791                         free(handler);
792                         handler_list[type] = eina_list_remove_list(handler_list[type], l_itr);
793
794                         if (appcore_initialized && eina_list_count(handler_list[type]) == 0)
795                                 _ui_app_appcore_unset_event_cb(type);
796
797                         return APP_ERROR_NONE;
798                 }
799         }
800
801         return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "cannot find such handler");
802 }
803