exclude code from coverage measurement
[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 6
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 void _ui_app_appcore_set_event_cb(app_event_type_e event_type)
495 {
496         switch (event_type) {
497         case APP_EVENT_LOW_MEMORY:
498                 appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, _ui_app_appcore_low_memory, NULL);
499                 break;
500         case APP_EVENT_LOW_BATTERY:
501                 appcore_set_event_callback(APPCORE_EVENT_LOW_BATTERY, _ui_app_appcore_low_battery, NULL);
502                 break;
503         case APP_EVENT_LANGUAGE_CHANGED:
504                 appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, _ui_app_appcore_lang_changed, NULL);
505                 break;
506         case APP_EVENT_DEVICE_ORIENTATION_CHANGED:
507                 appcore_set_rotation_cb(_ui_app_appcore_rotation_event, NULL);
508                 break;
509         case APP_EVENT_REGION_FORMAT_CHANGED:
510                 appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, _ui_app_appcore_region_changed, NULL);
511                 break;
512         case APP_EVENT_SUSPENDED_STATE_CHANGED:
513                 LOGI("[__SUSPEND__]");
514                 appcore_set_event_callback(APPCORE_EVENT_SUSPENDED_STATE_CHANGE, _ui_app_appcore_suspended_state_changed, NULL);
515                 break;
516         default:
517                 break;
518         }
519 }
520
521 static void _ui_app_appcore_unset_event_cb(app_event_type_e event_type)
522 {
523         switch (event_type) {
524         case APP_EVENT_LOW_MEMORY:
525                 appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, NULL, NULL);
526                 break;
527         case APP_EVENT_LOW_BATTERY:
528                 appcore_set_event_callback(APPCORE_EVENT_LOW_BATTERY, NULL, NULL);
529                 break;
530         case APP_EVENT_LANGUAGE_CHANGED:
531                 appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, NULL, NULL);
532                 break;
533         case APP_EVENT_DEVICE_ORIENTATION_CHANGED:
534                 appcore_unset_rotation_cb();
535                 break;
536         case APP_EVENT_REGION_FORMAT_CHANGED:
537                 appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, NULL, NULL);
538                 break;
539         case APP_EVENT_SUSPENDED_STATE_CHANGED:
540                 LOGI("[__SUSPEND__]");
541                 appcore_set_event_callback(APPCORE_EVENT_SUSPENDED_STATE_CHANGE, NULL, NULL);
542                 break;
543         default:
544                 break;
545         }
546 }
547
548 static void _ui_app_set_appcore_event_cb(void)
549 {
550         _ui_app_appcore_set_event_cb(APP_EVENT_LOW_MEMORY);
551         _ui_app_appcore_set_event_cb(APP_EVENT_LANGUAGE_CHANGED);
552         _ui_app_appcore_set_event_cb(APP_EVENT_REGION_FORMAT_CHANGED);
553
554         if (eina_list_count(handler_list[APP_EVENT_LOW_BATTERY]) > 0)
555                 _ui_app_appcore_set_event_cb(APP_EVENT_LOW_BATTERY);
556         if (eina_list_count(handler_list[APP_EVENT_DEVICE_ORIENTATION_CHANGED]) > 0)
557                 _ui_app_appcore_set_event_cb(APP_EVENT_DEVICE_ORIENTATION_CHANGED);
558         if (eina_list_count(handler_list[APP_EVENT_SUSPENDED_STATE_CHANGED]) > 0)
559                 _ui_app_appcore_set_event_cb(APP_EVENT_SUSPENDED_STATE_CHANGED);
560 }
561
562 static void _ui_app_unset_appcore_event_cb(void)
563 {
564         _ui_app_appcore_unset_event_cb(APP_EVENT_LOW_MEMORY);
565         _ui_app_appcore_unset_event_cb(APP_EVENT_LANGUAGE_CHANGED);
566         _ui_app_appcore_unset_event_cb(APP_EVENT_REGION_FORMAT_CHANGED);
567
568         if (eina_list_count(handler_list[APP_EVENT_LOW_BATTERY]) > 0)
569                 _ui_app_appcore_unset_event_cb(APP_EVENT_LOW_BATTERY);
570         if (eina_list_count(handler_list[APP_EVENT_DEVICE_ORIENTATION_CHANGED]) > 0)
571                 _ui_app_appcore_unset_event_cb(APP_EVENT_DEVICE_ORIENTATION_CHANGED);
572         if (eina_list_count(handler_list[APP_EVENT_SUSPENDED_STATE_CHANGED]) > 0)
573                 _ui_app_appcore_unset_event_cb(APP_EVENT_SUSPENDED_STATE_CHANGED);
574 }
575
576 static int _ui_app_appcore_create(void *data)
577 {
578         LOGI("app_appcore_create");
579         struct ui_app_context *app_context = data;
580         app_create_cb create_cb;
581
582         if (app_context == NULL)
583                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
584
585         appcore_initialized = 1;
586         _ui_app_set_appcore_event_cb();
587
588         create_cb = app_context->callback->create;
589
590         if (create_cb == NULL || create_cb(app_context->data) == false)
591                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "app_create_cb() returns false");
592
593         app_state = APP_STATE_RUNNING;
594
595         return APP_ERROR_NONE;
596 }
597
598 static int _ui_app_appcore_terminate(void *data)
599 {
600         LOGI("app_appcore_terminate");
601         struct ui_app_context *app_context = data;
602         app_terminate_cb terminate_cb;
603
604         if (app_context == NULL)
605                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
606
607         terminate_cb = app_context->callback->terminate;
608
609         if (terminate_cb != NULL)
610                 terminate_cb(app_context->data);
611
612         _ui_app_unset_appcore_event_cb();
613
614         app_finalizer_execute();
615
616         if (handler_initialized) {
617                 _free_handler_list();
618                 handler_initialized = 0;
619         }
620
621         return APP_ERROR_NONE;
622 }
623
624 /* LCOV_EXCL_START */
625 static int _ui_app_appcore_pause(void *data)
626 {
627         LOGI("app_appcore_pause");
628         struct ui_app_context *app_context = data;
629         app_pause_cb pause_cb;
630
631         if (app_context == NULL)
632                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
633
634         pause_cb = app_context->callback->pause;
635
636         if (pause_cb != NULL)
637                 pause_cb(app_context->data);
638
639         return APP_ERROR_NONE;
640 }
641 /* LCOV_EXCL_STOP */
642
643 /* LCOV_EXCL_START */
644 static int _ui_app_appcore_resume(void *data)
645 {
646         LOGI("app_appcore_resume");
647         struct ui_app_context *app_context = data;
648         app_resume_cb resume_cb;
649
650         if (app_context == NULL)
651                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
652
653         resume_cb = app_context->callback->resume;
654
655         if (resume_cb != NULL)
656                 resume_cb(app_context->data);
657
658         return APP_ERROR_NONE;
659 }
660 /* LCOV_EXCL_STOP */
661
662 static int _ui_app_appcore_reset(bundle *appcore_bundle, void *data)
663 {
664         LOGI("app_appcore_reset");
665         struct ui_app_context *app_context = data;
666         app_control_cb callback;
667         app_control_h app_control;
668         int ret;
669
670         if (app_context == NULL)
671                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
672
673         if (appcore_bundle) {
674                 if (app_control_create_event(appcore_bundle, &app_control) != APP_ERROR_NONE)
675                         return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create an app_control handle from the bundle");
676         } else {
677                 ret = app_control_create(&app_control);
678                 if (ret != APP_ERROR_NONE)
679                         return app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create an app_control");
680         }
681
682         callback = app_context->callback->app_control;
683
684         if (callback != NULL)
685                 callback(app_control, app_context->data);
686
687         app_control_destroy(app_control);
688
689         return APP_ERROR_NONE;
690 }
691
692 static int __create_ui_app_context(ui_app_lifecycle_callback_s *callback, void *user_data, struct ui_app_context **handle)
693 {
694         struct ui_app_context *app_context;
695         int ret;
696
697         app_context = (struct ui_app_context *)calloc(1, sizeof(struct ui_app_context));
698         if (app_context == NULL)
699                 return app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
700
701         ret = app_get_id(&app_context->package);
702         if (ret != APP_ERROR_NONE) {
703                 free(app_context);
704                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package");
705         }
706
707         ret = app_get_package_app_name(app_context->package, &app_context->app_name);
708         if (ret != APP_ERROR_NONE) {
709                 free(app_context->package);
710                 free(app_context);
711                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package's app name");
712         }
713
714         app_context->callback = (ui_app_lifecycle_callback_s *)malloc(sizeof(ui_app_lifecycle_callback_s));
715         if (app_context->callback == NULL) {
716                 free(app_context->app_name);
717                 free(app_context->package);
718                 free(app_context);
719                 return app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
720         }
721         memcpy(app_context->callback, callback, sizeof(ui_app_lifecycle_callback_s));
722
723         app_context->data = user_data;
724
725         *handle = app_context;
726
727         return APP_ERROR_NONE;
728 }
729
730 static void __destroy_ui_app_context(struct ui_app_context *handle)
731 {
732         if (handle == NULL)
733                 return;
734
735         if (handle->callback) {
736                 free(handle->callback);
737                 handle->callback = NULL;
738         }
739
740         if (handle->app_name) {
741                 free(handle->app_name);
742                 handle->app_name = NULL;
743         }
744
745         if (handle->package) {
746                 free(handle->package);
747                 handle->package = NULL;
748         }
749
750         free(handle);
751 }
752
753 static int __create_appcore_context(struct ui_app_context *app_context, struct appcore_ops **handle)
754 {
755         struct appcore_ops *appcore_context;
756
757         appcore_context = (struct appcore_ops *)malloc(sizeof(struct appcore_ops));
758         if (appcore_context == NULL)
759                 return app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
760
761         appcore_context->data = app_context;
762         appcore_context->create = _ui_app_appcore_create;
763         appcore_context->terminate = _ui_app_appcore_terminate;
764         appcore_context->pause = _ui_app_appcore_pause;
765         appcore_context->resume = _ui_app_appcore_resume;
766         appcore_context->reset = _ui_app_appcore_reset;
767
768         *handle = appcore_context;
769
770         return APP_ERROR_NONE;
771 }
772
773 static void __destroy_appcore_context(struct appcore_ops *handle)
774 {
775         if (handle == NULL)
776                 return;
777
778         __destroy_ui_app_context((struct ui_app_context *)handle->data);
779         free(handle);
780 }
781
782 int ui_app_init(int argc, char **argv, ui_app_lifecycle_callback_s *callback, void *user_data, appcore_context_h *handle)
783 {
784         struct ui_app_context *app_context = NULL;
785         struct appcore_ops *appcore_context = NULL;
786         int ret;
787
788         if (argc < 1 || argv == NULL || callback == NULL || handle == NULL)
789                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
790
791         if (callback->create == NULL)
792                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "app_create_cb() callback must be registered");
793
794         if (app_state != APP_STATE_NOT_RUNNING)
795                 return app_error(APP_ERROR_ALREADY_RUNNING, __FUNCTION__, NULL);
796
797         ret = __create_ui_app_context(callback, user_data, &app_context);
798         if (ret != APP_ERROR_NONE)
799                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
800
801         ret = __create_appcore_context(app_context, &appcore_context);
802         if (ret != APP_ERROR_NONE) {
803                 __destroy_ui_app_context(app_context);
804                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
805         }
806
807         app_state = APP_STATE_CREATING;
808
809         LOGI("app_efl_init");
810         ret = appcore_efl_init(app_context->app_name, &argc, &argv, appcore_context);
811         if (ret != APP_ERROR_NONE) {
812                 app_state = APP_STATE_NOT_RUNNING;
813                 __destroy_appcore_context(appcore_context);
814                 return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
815         }
816
817         *handle = appcore_context;
818
819         return APP_ERROR_NONE;
820 }
821
822 void ui_app_fini(appcore_context_h handle)
823 {
824         appcore_efl_fini();
825
826         app_state = APP_STATE_NOT_RUNNING;
827
828         __destroy_appcore_context(handle);
829 }
830
831 int ui_app_main(int argc, char **argv, ui_app_lifecycle_callback_s *callback, void *user_data)
832 {
833         appcore_context_h handle = NULL;
834         int ret;
835
836         ret = ui_app_init(argc, argv, callback, user_data, &handle);
837         if (ret != APP_ERROR_NONE)
838                 return app_error(ret, __FUNCTION__, NULL);
839
840         LOGI("run ui_app_main");
841         elm_run();
842
843         ui_app_fini(handle);
844
845         return APP_ERROR_NONE;
846 }
847
848 void ui_app_exit(void)
849 {
850         app_efl_exit();
851 }
852
853 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)
854 {
855         app_event_handler_h handler;
856         Eina_List *l_itr;
857
858         if (!handler_initialized) {
859                 eina_init();
860                 handler_initialized = 1;
861         }
862
863         if (event_handler == NULL || callback == NULL)
864                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "null parameter");
865
866         if (event_type < APP_EVENT_LOW_MEMORY || event_type > APP_EVENT_SUSPENDED_STATE_CHANGED)
867                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid event type");
868
869         EINA_LIST_FOREACH(handler_list[event_type], l_itr, handler) {
870                 if (handler->cb == callback)
871                         return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "already registered");
872         }
873
874         handler = calloc(1, sizeof(struct app_event_handler));
875         if (!handler)
876                 return app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create handler");
877
878         handler->type = event_type;
879         handler->cb = callback;
880         handler->data = user_data;
881
882         if (appcore_initialized && eina_list_count(handler_list[event_type]) == 0)
883                 _ui_app_appcore_set_event_cb(event_type);
884
885         handler_list[event_type] = eina_list_append(handler_list[event_type], handler);
886
887         *event_handler = handler;
888
889         return APP_ERROR_NONE;
890 }
891
892 int ui_app_remove_event_handler(app_event_handler_h event_handler)
893 {
894         app_event_handler_h handler;
895         app_event_type_e type;
896         Eina_List *l_itr;
897         Eina_List *l_next;
898
899         if (event_handler == NULL)
900                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "handler is null");
901
902         if (!handler_initialized) {
903                 LOGI("handler list is not initialized");
904                 return APP_ERROR_NONE;
905         }
906
907         type = event_handler->type;
908         if (type < APP_EVENT_LOW_MEMORY || type > APP_EVENT_SUSPENDED_STATE_CHANGED)
909                 return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid handler");
910
911         EINA_LIST_FOREACH_SAFE(handler_list[type], l_itr, l_next, handler) {
912                 if (handler == event_handler) {
913                         free(handler);
914                         handler_list[type] = eina_list_remove_list(handler_list[type], l_itr);
915
916                         if (appcore_initialized && eina_list_count(handler_list[type]) == 0)
917                                 _ui_app_appcore_unset_event_cb(type);
918
919                         return APP_ERROR_NONE;
920                 }
921         }
922
923         return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "cannot find such handler");
924 }
925