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