X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fappcore-efl.c;h=1378463713861717b40555e8a8e1366c40f946c1;hb=refs%2Fchanges%2F45%2F101345%2F1;hp=9d9f21f54c79227beb1feb428fd5146e9d3bc748;hpb=9ced94b3e72d6794cf1e3ab0ba7925262b94b88b;p=platform%2Fcore%2Fappfw%2Fapp-core.git diff --git a/src/appcore-efl.c b/src/appcore-efl.c index 9d9f21f..1378463 100644 --- a/src/appcore-efl.c +++ b/src/appcore-efl.c @@ -1,9 +1,5 @@ /* - * app-core - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jayoun Lee , Sewook Park , Jaeho Lee + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ #include @@ -31,6 +26,9 @@ #if defined(WAYLAND) #include +#include +#include +#include #elif defined(X11) #include #include @@ -44,9 +42,12 @@ #include #include #include -#include +#include #include #include +#include +#include +#include #include "appcore-internal.h" #include "appcore-efl.h" @@ -55,15 +56,6 @@ static pid_t _pid; static bool resource_reclaiming = TRUE; static int tmp_val = 0; -/* cgroup command type */ -enum proc_status_type { - PROC_STATUS_LAUNCH, - PROC_STATUS_RESUME, - PROC_STATUS_TERMINATE, - PROC_STATUS_FOREGRD, - PROC_STATUS_BACKGRD, -}; - struct ui_priv { const char *name; enum app_state state; @@ -71,10 +63,18 @@ struct ui_priv { Ecore_Event_Handler *hshow; Ecore_Event_Handler *hhide; Ecore_Event_Handler *hvchange; +#if defined(WAYLAND) + Ecore_Event_Handler *hlower; +#endif Ecore_Event_Handler *hcmsg; /* WM_ROTATE */ Ecore_Timer *mftimer; /* Ecore Timer for memory flushing */ + struct appcore *app_core; +#ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT + void (*prepare_to_suspend) (void *data); + void (*exit_from_suspend) (void *data); +#endif struct appcore_ops *ops; void (*mfcb) (void); /* Memory Flushing Callback */ @@ -85,6 +85,7 @@ struct ui_priv { void *rot_cb_data; enum appcore_rm rot_mode; bundle *pending_data; + char *below_app; }; static struct ui_priv priv; @@ -98,6 +99,7 @@ static const char *_ae_name[AE_MAX] = { [AE_RESET] = "RESET", [AE_LOWMEM_POST] = "LOWMEM_POST", [AE_MEM_FLUSH] = "MEM_FLUSH", + [AE_UPDATE_REQUESTED] = "UPDATE_REQUESTED", }; static const char *_as_name[] = { @@ -113,55 +115,161 @@ static bool first_launch = TRUE; struct win_node { unsigned int win; -#ifdef WAYLAND +#if defined(WAYLAND) unsigned int surf; #endif bool bfobscured; }; +#if defined(X11) static struct ui_wm_rotate wm_rotate; +#endif static Eina_Bool __visibility_cb(void *data, int type, void *event); +static GSList *g_winnode_list; -static void _send_to_resourced(enum proc_status_type type) +static struct wl_display *dsp; +static struct wl_registry *reg; +static struct tizen_policy *tz_policy; +static bool bg_state = false; + +static void __wl_listener_cb(void *data, struct wl_registry *reg, + uint32_t id, const char *interface, uint32_t ver) { - DBusConnection *conn; - DBusMessage* msg; - DBusError dbus_error; + if (interface && !strcmp(interface, "tizen_policy")) { + if (!tz_policy) + tz_policy = wl_registry_bind(reg, id, + &tizen_policy_interface, 1); + } +} - dbus_error_init(&dbus_error); +static void __wl_listener_remove_cb(void *data, struct wl_registry *reg, + unsigned int id) +{ + /* do nothing */ +} - conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error); - if (!conn) { - _ERR("dbus_bus_get failed : [%s]", dbus_error.message); - dbus_error_free(&dbus_error); - return; +static const struct wl_registry_listener reg_listener = { + __wl_listener_cb, + __wl_listener_remove_cb +}; + +static int __init_wl(void) +{ + _DBG("initialize wayland"); + dsp = wl_display_connect(NULL); + if (dsp == NULL) { + _ERR("Failed to connect wl display"); + return -1; } - msg = dbus_message_new_signal("/Org/Tizen/ResourceD/Process", - "org.tizen.resourced.process", - "ProcStatus"); - if (!msg) { - _ERR("dbus_message_new_signal is failed"); - return; + reg = wl_display_get_registry(dsp); + if (reg == NULL) { + _ERR("Failed to get registry"); + wl_display_disconnect(dsp); + return -1; + } + + wl_registry_add_listener(reg, ®_listener, NULL); + wl_display_roundtrip(dsp); + + if (!tz_policy) { + _ERR("Failed to get tizen policy interface"); + wl_registry_destroy(reg); + wl_display_disconnect(dsp); + return -1; + } + + return 0; +} + +static void __finish_wl(void) +{ + if (tz_policy) { + tizen_policy_destroy(tz_policy); + tz_policy = NULL; + } + + if (reg) { + wl_registry_destroy(reg); + reg = NULL; } - if (!dbus_message_append_args(msg, - DBUS_TYPE_INT32, &type, - DBUS_TYPE_INT32, &_pid, - DBUS_TYPE_INVALID)) { - _ERR("dbus_message_append_args is failed. type = %d, pid = %d", - type, _pid); - dbus_message_unref(msg); + if (dsp) { + wl_display_disconnect(dsp); + dsp = NULL; + } +} + +static void __set_bg_state(void) +{ + if (__init_wl() < 0) + return; + + tizen_policy_set_background_state(tz_policy, getpid()); + wl_display_roundtrip(dsp); + bg_state = true; + _DBG("bg state: %d", bg_state); +} + +static void __unset_bg_state(void) +{ + if (!tz_policy) return; + + tizen_policy_unset_background_state(tz_policy, getpid()); + wl_display_roundtrip(dsp); + bg_state = false; + _DBG("bg state: %d", bg_state); + __finish_wl(); +} + +#ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT +static void __appcore_efl_prepare_to_suspend(void *data) +{ + struct ui_priv *ui = (struct ui_priv *)data; + struct sys_op *op = NULL; + int suspend = APPCORE_SUSPENDED_STATE_WILL_ENTER_SUSPEND; + + if (ui->app_core && !ui->app_core->allowed_bg && !ui->app_core->suspended_state) { + op = &ui->app_core->sops[SE_SUSPENDED_STATE]; + if (op && op->func) + op->func((void *)&suspend, op->data); /* calls c-api handler */ + + ui->app_core->suspended_state = true; } + _DBG("[__SUSPEND__]"); +} + +static void __appcore_efl_exit_from_suspend(void *data) +{ + struct ui_priv *ui = (struct ui_priv *)data; + struct sys_op *op = NULL; + int suspend = APPCORE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND; - if (!dbus_connection_send(conn, msg, NULL)) - _ERR("dbus_connection_send is failed"); + if (ui->app_core && !ui->app_core->allowed_bg && ui->app_core->suspended_state) { + op = &ui->app_core->sops[SE_SUSPENDED_STATE]; + if (op && op->func) + op->func((void *)&suspend, op->data); /* calls c-api handler */ - dbus_message_unref(msg); + ui->app_core->suspended_state = false; + } + _DBG("[__SUSPEND__]"); } +#endif -static GSList *g_winnode_list; +static void __appcore_efl_update_requested(void *data) +{ + struct ui_priv *ui = (struct ui_priv *)data; + struct sys_op *op; + int dummy = 0; + + if (ui->app_core) { + op = &ui->app_core->sops[SE_UPDATE_REQUESTED]; + if (op && op->func) + op->func((void *)&dummy, op->data); + } + _DBG("[__UPDATE_REQUESTED__]"); +} #if defined(MEMORY_FLUSH_ACTIVATE) static Eina_Bool __appcore_memory_flush_cb(void *data) @@ -169,7 +277,15 @@ static Eina_Bool __appcore_memory_flush_cb(void *data) struct ui_priv *ui = (struct ui_priv *)data; appcore_flush_memory(); - ui->mftimer = NULL; + if (ui) + ui->mftimer = NULL; + +#ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT + if (ui && ui->prepare_to_suspend) { + _DBG("[__SUSPEND__] flush case"); + ui->prepare_to_suspend(ui); + } +#endif return ECORE_CALLBACK_CANCEL; } @@ -214,7 +330,7 @@ static void __appcore_efl_memory_flush_cb(void) _DBG("[APP %d] __appcore_efl_memory_flush_cb()", _pid); elm_cache_all_flush(); } -#ifdef WAYLAND +#if defined(WAYLAND) static void wl_raise_win(void) { Ecore_Wl_Window *win; @@ -250,6 +366,8 @@ static void __do_app(enum app_event event, void *data, bundle * b) { int r = -1; struct ui_priv *ui = data; + const char *below_app; + const char *bg_launch; _DBG("[APP %d] Event: %d", _pid, event); _ret_if(ui == NULL || event >= AE_MAX); @@ -306,14 +424,43 @@ static void __do_app(enum app_event event, void *data, bundle * b) _DBG("[APP %d] RESET", _pid); ui->pending_data = bundle_dup(b); LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]", ui->name); - if (ui->ops->reset) + + if (ui->below_app) { + free(ui->below_app); + ui->below_app = NULL; + } + + below_app = bundle_get_val(b, AUL_SVC_K_RELOCATE_BELOW); + if (below_app) + ui->below_app = strdup(below_app); +#ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT + if (ui->exit_from_suspend) { + _DBG("[__SUSPEND__] reset case"); + ui->exit_from_suspend(ui); + } +#endif + + if (ui->ops->reset) { + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, + "APPCORE:RESET"); r = ui->ops->reset(b, ui->ops->data); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + } LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]", ui->name); if (first_launch) { +#ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT + if (ui->app_core->allowed_bg) + __appcore_timer_add(ui); +#endif first_launch = FALSE; } else { _INFO("[APP %d] App already running, raise the window", _pid); + if (bg_state) { + bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH); + if (!bg_launch || strcmp(bg_launch, "enable")) + __unset_bg_state(); + } #ifdef X11 x_raise_win(getpid()); #else @@ -326,34 +473,60 @@ static void __do_app(enum app_event event, void *data, bundle * b) case AE_PAUSE: if (ui->state == AS_RUNNING) { _DBG("[APP %d] PAUSE", _pid); - if (ui->ops->pause) + if (ui->ops->pause) { + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, + "APPCORE:PAUSE"); r = ui->ops->pause(ui->ops->data); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + } ui->state = AS_PAUSED; if (r >= 0 && resource_reclaiming == TRUE) __appcore_timer_add(ui); +#ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT + else if (r >= 0 && resource_reclaiming == FALSE + && ui->prepare_to_suspend) { + _DBG("[__SUSPEND__] pause case"); + ui->prepare_to_suspend(ui); + } +#endif } /* TODO : rotation stop */ /* r = appcore_pause_rotation_cb(); */ aul_status_update(STATUS_BG); - _send_to_resourced(PROC_STATUS_BACKGRD); break; case AE_RESUME: LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]", ui->name); +#ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT + if (ui->exit_from_suspend) { + _DBG("[__SUSPEND__] resume case"); + ui->exit_from_suspend(ui); + } + if (ui->app_core->allowed_bg) + __appcore_timer_del(ui); +#endif + if (ui->state == AS_PAUSED || ui->state == AS_CREATED) { _DBG("[APP %d] RESUME", _pid); if (ui->state == AS_CREATED) { - appcore_group_reset(ui->pending_data); bundle_free(ui->pending_data); ui->pending_data = NULL; - } else { - appcore_group_resume(); } - if (ui->ops->resume) + if (ui->ops->resume) { + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, + "APPCORE:RESUME"); ui->ops->resume(ui->ops->data); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + } ui->state = AS_RUNNING; + + if (ui->below_app) { + aul_app_group_activate_below(ui->below_app); + free(ui->below_app); + ui->below_app = NULL; + } } /*TODO : rotation start*/ /* r = appcore_resume_rotation_cb(); */ @@ -362,7 +535,6 @@ static void __do_app(enum app_event event, void *data, bundle * b) LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:Launching:done]", ui->name); aul_status_update(STATUS_VISIBLE); - _send_to_resourced(PROC_STATUS_FOREGRD); break; case AE_TERMINATE_BGAPP: if (ui->state == AS_PAUSED) { @@ -376,6 +548,9 @@ static void __do_app(enum app_event event, void *data, bundle * b) _DBG("[APP %d] is another state", _pid); } break; + case AE_UPDATE_REQUESTED: + __appcore_efl_update_requested(ui); + break; default: /* do nothing */ break; @@ -629,8 +804,6 @@ static Eina_Bool __show_cb(void *data, int type, void *event) #elif defined(X11) Ecore_X_Event_Window_Show *ev; - int ret; - Ecore_X_Window parent; ev = event; @@ -646,6 +819,7 @@ static Eina_Bool __show_cb(void *data, int type, void *event) } #endif + appcore_group_attach(); return ECORE_CALLBACK_RENEW; } @@ -675,6 +849,18 @@ static Eina_Bool __hide_cb(void *data, int type, void *event) return ECORE_CALLBACK_RENEW; } +#if defined(WAYLAND) +static Eina_Bool __lower_cb(void *data, int type, void *event) +{ + Ecore_Wl_Event_Window_Lower *ev; + ev = event; + if (!ev) return ECORE_CALLBACK_RENEW; + _DBG("ECORE_WL_EVENT_WINDOW_LOWER window id:%u\n", ev->win); + appcore_group_lower(); + return ECORE_CALLBACK_RENEW; +} +#endif + static Eina_Bool __visibility_cb(void *data, int type, void *event) { #if defined(WAYLAND) @@ -710,7 +896,7 @@ static Eina_Bool __visibility_cb(void *data, int type, void *event) } -#ifdef X11 +#if defined(X11) /* WM_ROTATE */ static Eina_Bool __cmsg_cb(void *data, int type, void *event) { @@ -764,25 +950,28 @@ static void __add_climsg_cb(struct ui_priv *ui) _ret_if(ui == NULL); #if defined(WAYLAND) ui->hshow = - ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_SHOW, __show_cb, ui); + ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_SHOW, __show_cb, ui); ui->hhide = - ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_HIDE, __hide_cb, ui); + ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_HIDE, __hide_cb, ui); ui->hvchange = - ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE, - __visibility_cb, ui); + ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE, + __visibility_cb, ui); + ui->hlower = + ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_LOWER, + __lower_cb, ui); #elif defined(X11) ui->hshow = - ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, __show_cb, ui); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, __show_cb, ui); ui->hhide = - ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, __hide_cb, ui); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, __hide_cb, ui); ui->hvchange = - ecore_event_handler_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE, - __visibility_cb, ui); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE, + __visibility_cb, ui); /* Add client message callback for WM_ROTATE */ if (!__check_wm_rotation_support()) { ui->hcmsg = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, - __cmsg_cb, ui); + __cmsg_cb, ui); ui->wm_rot_supported = 1; appcore_set_wm_rotation(&wm_rotate); } @@ -793,6 +982,11 @@ static int __before_loop(struct ui_priv *ui, int *argc, char ***argv) { int r; char *hwacc = NULL; +#if _APPFW_FEATURE_BACKGROUND_MANAGEMENT + struct appcore *ac = NULL; +#endif + bundle *b; + const char *bg_launch; if (argc == NULL || argv == NULL) { _ERR("argc/argv is NULL"); @@ -821,14 +1015,35 @@ static int __before_loop(struct ui_priv *ui, int *argc, char ***argv) r = appcore_init(ui->name, &efl_ops, *argc, *argv); _retv_if(r == -1, -1); +#if _APPFW_FEATURE_BACKGROUND_MANAGEMENT + appcore_get_app_core(&ac); + ui->app_core = ac; + SECURE_LOGD("[__SUSPEND__] appcore initialized, appcore addr: #%x", ac); +#endif + + b = bundle_import_from_argv(*argc, *argv); + if (b) { + bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH); + if (bg_launch && strcmp(bg_launch, "enable") == 0) + __set_bg_state(); + + bundle_free(b); + } + LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:appcore_init:done]", ui->name); if (ui->ops && ui->ops->create) { + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:CREATE"); r = ui->ops->create(ui->ops->data); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); if (r < 0) { _ERR("create() return error"); appcore_exit(); - if (ui->ops && ui->ops->terminate) + if (ui->ops && ui->ops->terminate) { + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, + "APPCORE:TERMINATE"); ui->ops->terminate(ui->ops->data); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + } errno = ECANCELED; return -1; } @@ -849,12 +1064,19 @@ static void __after_loop(struct ui_priv *ui) if (ui->state == AS_RUNNING) { _DBG("[APP %d] PAUSE before termination", _pid); - if (ui->ops && ui->ops->pause) + if (ui->ops && ui->ops->pause) { + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, + "APPCORE:PAUSE"); ui->ops->pause(ui->ops->data); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + } } - if (ui->ops && ui->ops->terminate) + if (ui->ops && ui->ops->terminate) { + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:TERMINATE"); ui->ops->terminate(ui->ops->data); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + } ui->state = AS_DYING; @@ -864,6 +1086,10 @@ static void __after_loop(struct ui_priv *ui) ecore_event_handler_del(ui->hhide); if (ui->hvchange) ecore_event_handler_del(ui->hvchange); +#if defined(WAYLAND) + if (ui->hlower) + ecore_event_handler_del(ui->hlower); +#endif __appcore_timer_del(ui); @@ -905,6 +1131,12 @@ static int __set_data(struct ui_priv *ui, const char *name, ui->rot_cb_data = NULL; ui->rot_mode = APPCORE_RM_UNKNOWN; +#ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT + ui->app_core = NULL; + ui->prepare_to_suspend = __appcore_efl_prepare_to_suspend; + ui->exit_from_suspend = __appcore_efl_exit_from_suspend; +#endif + return 0; } @@ -916,6 +1148,7 @@ static void __unset_data(struct ui_priv *ui) memset(ui, 0, sizeof(struct ui_priv)); } +#if defined(X11) /* WM_ROTATE */ static int __wm_set_rotation_cb(int (*cb) (void *event_info, enum appcore_rm, void *), void *data) { @@ -985,9 +1218,10 @@ static struct ui_wm_rotate wm_rotate = { __wm_pause_rotation_cb, __wm_resume_rotation_cb }; +#endif -EXPORT_API int appcore_efl_main(const char *name, int *argc, char ***argv, - struct appcore_ops *ops) +EXPORT_API int appcore_efl_init(const char *name, int *argc, char ***argv, + struct appcore_ops *ops) { int r; @@ -998,17 +1232,34 @@ EXPORT_API int appcore_efl_main(const char *name, int *argc, char ***argv, r = __before_loop(&priv, argc, argv); if (r == -1) { + aul_status_update(STATUS_DYING); __unset_data(&priv); return -1; } - elm_run(); + return 0; +} +EXPORT_API void appcore_efl_fini(void) +{ aul_status_update(STATUS_DYING); __after_loop(&priv); __unset_data(&priv); +} + +EXPORT_API int appcore_efl_main(const char *name, int *argc, char ***argv, + struct appcore_ops *ops) +{ + int r; + + r = appcore_efl_init(name, argc, argv, ops); + _retv_if(r == -1, -1); + + elm_run(); + + appcore_efl_fini(); return 0; } @@ -1029,6 +1280,35 @@ EXPORT_API int appcore_set_app_state(int state) return 0; } +EXPORT_API int appcore_set_preinit_window_name(const char *win_name) +{ + int ret = -1; + void *preinit_window = NULL; + const Evas *e = NULL; + + if (!win_name) { + _ERR("invalid parameter"); + return ret; + } + + preinit_window = elm_win_precreated_object_get(); + if (!preinit_window) { + _ERR("Failed to get preinit window"); + return ret; + } + + e = evas_object_evas_get((const Evas_Object *)preinit_window); + if (e) { + Ecore_Evas *ee = ecore_evas_ecore_evas_get(e); + if (ee) { + ecore_evas_name_class_set(ee, win_name, win_name); + ret = 0; + } + } + + return ret; +} + EXPORT_API unsigned int appcore_get_main_window(void) { struct win_node *entry = NULL; @@ -1041,7 +1321,7 @@ EXPORT_API unsigned int appcore_get_main_window(void) return 0; } -#ifdef WAYLAND +#if defined(WAYLAND) EXPORT_API unsigned int appcore_get_main_surface(void) { struct win_node *entry = NULL;