4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include <sys/types.h>
23 #include <sys/socket.h>
31 #include <X11/Xatom.h>
33 #include <X11/Xutil.h>
34 #include <X11/extensions/Xcomposite.h>
35 #include <X11/extensions/XShm.h>
38 #include <proc_stat.h>
43 #include <Ecore_Evas.h>
45 #include <Ecore_Input_Evas.h>
46 #include <Elementary.h>
47 #include <glib-object.h>
52 #include "appcore-internal.h"
53 #include "appcore-efl.h"
54 #include "virtual_canvas.h"
55 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
56 #include <vconf/vconf.h>
59 #define SYSMAN_MAXSTR 100
60 #define SYSMAN_MAXARG 16
61 #define SYSNOTI_SOCKET_PATH "/tmp/sn"
62 #define RETRY_READ_COUNT 10
63 #define MAX_PACKAGE_STR_SIZE 512
65 #define PREDEF_BACKGRD "backgrd"
66 #define PREDEF_FOREGRD "foregrd"
79 char *argv[SYSMAN_MAXARG];
84 static bool resource_reclaiming = TRUE;
85 static bool prelaunching = FALSE;
93 Ecore_Event_Handler *hshow;
94 Ecore_Event_Handler *hhide;
95 Ecore_Event_Handler *hvchange;
96 Ecore_Event_Handler *hcmsg; /* WM_ROTATE */
98 Ecore_Timer *mftimer; /* Ecore Timer for memory flushing */
100 struct appcore_ops *ops;
101 void (*mfcb) (void); /* Memory Flushing Callback */
104 int wm_rot_supported;
106 int (*rot_cb) (void *event_info, enum appcore_rm, void *);
108 enum appcore_rm rot_mode;
111 static struct ui_priv priv;
113 static const char *_ae_name[AE_MAX] = {
114 [AE_UNKNOWN] = "UNKNOWN",
115 [AE_CREATE] = "CREATE",
116 [AE_TERMINATE] = "TERMINATE",
117 [AE_PAUSE] = "PAUSE",
118 [AE_RESUME] = "RESUME",
119 [AE_RESET] = "RESET",
120 [AE_LOWMEM_POST] = "LOWMEM_POST",
121 [AE_MEM_FLUSH] = "MEM_FLUSH",
124 static const char *_as_name[] = {
126 [AS_CREATED] = "CREATED",
127 [AS_RUNNING] = "RUNNING",
128 [AS_PAUSED] = "PAUSED",
129 [AS_DYING] = "DYING",
132 static int b_active = -1;
133 static bool first_launch = 1;
134 static int is_legacy_lifecycle = 0;
141 static struct ui_wm_rotate wm_rotate;
143 static inline int send_int(int fd, int val)
145 return write(fd, &val, sizeof(int));
148 static inline int send_str(int fd, char *str)
154 ret = write(fd, &len, sizeof(int));
157 if (len > SYSMAN_MAXSTR)
159 write(fd, &len, sizeof(int));
160 ret = write(fd, str, len);
165 static int sysnoti_send(struct sysnoti *msg)
172 struct sockaddr_un clientaddr;
175 client_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
176 if (client_sockfd == -1) {
177 _ERR("%s: socket create failed\n", __FUNCTION__);
180 bzero(&clientaddr, sizeof(clientaddr));
181 clientaddr.sun_family = AF_UNIX;
182 strncpy(clientaddr.sun_path, SYSNOTI_SOCKET_PATH, sizeof(clientaddr.sun_path) - 1);
183 client_len = sizeof(clientaddr);
185 if (connect(client_sockfd, (struct sockaddr *)&clientaddr, client_len) <
187 _ERR("%s: connect failed\n", __FUNCTION__);
188 close(client_sockfd);
192 send_int(client_sockfd, msg->pid);
193 send_int(client_sockfd, msg->cmd);
194 send_str(client_sockfd, msg->type);
195 send_str(client_sockfd, msg->path);
196 send_int(client_sockfd, msg->argc);
197 for (i = 0; i < msg->argc; i++)
198 send_str(client_sockfd, msg->argv[i]);
200 while (retry_count < RETRY_READ_COUNT) {
201 r = read(client_sockfd, &result, sizeof(int));
203 if (errno == EINTR) {
204 _ERR("Re-read for error(EINTR)");
208 _ERR("Read fail for str length");
215 if (retry_count == RETRY_READ_COUNT) {
216 _ERR("Read retry failed");
219 close(client_sockfd);
223 void __trm_app_info_send_socket(char *write_buf)
225 const char trm_socket_for_app_info[] = "/dev/socket/app_info";
228 struct sockaddr_un addr;
230 _DBG("__trm_app_info_send_socket");
232 if (access(trm_socket_for_app_info, F_OK) != 0) {
237 socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
243 memset(&addr, 0, sizeof(addr));
244 sprintf(addr.sun_path, "%s", trm_socket_for_app_info);
245 addr.sun_family = AF_LOCAL;
247 ret = connect(socket_fd, (struct sockaddr *) &addr ,sizeof(sa_family_t) + strlen(trm_socket_for_app_info) );
253 send(socket_fd, write_buf, strlen(write_buf), MSG_DONTWAIT | MSG_NOSIGNAL);
261 #ifdef _APPFW_FEATURE_CPU_BOOST
262 static void __stop_cpu_boost(void)
264 const char trm_sock_for_cpu_boost[] = "/dev/socket/scenario_info";
267 struct sockaddr_un addr;
268 const char command[] = "AppLaunchUnlock";
270 _DBG("__stop_cpu_boost enter");
272 if (access(trm_sock_for_cpu_boost, F_OK) != 0) {
273 _ERR("access() failed, errno: %d (%s)", errno, strerror(errno));
277 sock_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
279 _ERR("socket() failed, errno: %d (%s)", errno, strerror(errno));
283 memset(&addr, 0, sizeof(addr));
284 sprintf(addr.sun_path, "%s", trm_sock_for_cpu_boost);
285 addr.sun_family = AF_LOCAL;
287 ret = connect(sock_fd, (struct sockaddr *) &addr, sizeof(sa_family_t) + strlen(trm_sock_for_cpu_boost));
289 _ERR("connect() failed, errno: %d (%s)", errno, strerror(errno));
294 ret = send(sock_fd, command, strlen(command), MSG_DONTWAIT | MSG_NOSIGNAL);
296 _ERR("send() failed, errno: %d (%s)", errno, strerror(errno));
302 _DBG("__stop_cpu_boost ok");
309 static int _call_predef_action(const char *type, int num, ...)
318 if (type == NULL || num > SYSMAN_MAXARG) {
323 msg = malloc(sizeof(struct sysnoti));
326 /* Do something for not enought memory error */
331 msg->cmd = CALL_SYSMAN_ACTION;
332 msg->type = (char *)type;
336 va_start(argptr, num);
337 for (i = 0; i < num; i++) {
338 args = va_arg(argptr, char *);
343 ret = sysnoti_send(msg);
349 static int _inform_foregrd(void)
352 snprintf(buf, sizeof(buf), "%d", getpid());
353 return _call_predef_action(PREDEF_FOREGRD, 1, buf);
356 static int _inform_backgrd(void)
359 snprintf(buf, sizeof(buf), "%d", getpid());
360 return _call_predef_action(PREDEF_BACKGRD, 1, buf);
365 char appid[APPID_MAX];
367 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
369 static void _capture_and_make_file(Ecore_X_Window win, int pid, const char *package);
372 static bool __check_skip(Ecore_X_Window xwin);
375 static int WIN_COMP(gconstpointer data1, gconstpointer data2)
377 struct win_node *a = (struct win_node *)data1;
378 struct win_node *b = (struct win_node *)data2;
379 return (int)((a->win)-(b->win));
382 GSList *g_winnode_list = NULL;
384 #if defined(MEMORY_FLUSH_ACTIVATE)
385 static Eina_Bool __appcore_memory_flush_cb(void *data)
387 struct ui_priv *ui = (struct ui_priv *)data;
389 appcore_flush_memory();
392 return ECORE_CALLBACK_CANCEL;
395 static int __appcore_low_memory_post_cb(struct ui_priv *ui)
397 if (ui->state == AS_PAUSED) {
398 // appcore_flush_memory();
406 static void __appcore_timer_add(struct ui_priv *ui)
408 ui->mftimer = ecore_timer_add(5, __appcore_memory_flush_cb, ui);
411 static void __appcore_timer_del(struct ui_priv *ui)
414 ecore_timer_del(ui->mftimer);
421 static int __appcore_low_memory_post_cb(ui_priv *ui)
426 #define __appcore_timer_add(ui) 0
427 #define __appcore_timer_del(ui) 0
431 static void __appcore_efl_memory_flush_cb(void)
433 //_DBG("[APP %d] __appcore_efl_memory_flush_cb()", _pid);
434 elm_cache_all_flush();
437 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
438 static Eina_Bool __appcore_mimiapp_capture_cb(void *data)
441 struct win_node *entry = NULL;
443 for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
445 if(__check_skip(entry->win) == FALSE)
451 _capture_and_make_file(entry->win, getpid(), appid);
455 return ECORE_CALLBACK_CANCEL;
459 static void __do_app(enum app_event event, void *data, bundle * b)
462 struct ui_priv *ui = data;
463 char trm_buf[MAX_PACKAGE_STR_SIZE];
464 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
465 const char *miniapp = NULL;
468 _ret_if(ui == NULL || event >= AE_MAX);
469 _DBG("[APP %d] Event: %s State: %s", _pid, _ae_name[event],
470 _as_name[ui->state]);
472 if (event == AE_MEM_FLUSH) {
477 if (event == AE_LOWMEM_POST) {
478 if (__appcore_low_memory_post_cb(ui) == 0)
482 if (!(ui->state == AS_PAUSED && event == AE_PAUSE))
483 __appcore_timer_del(ui);
485 if (event == AE_TERMINATE) {
486 _DBG("[APP %d] TERMINATE", _pid);
487 ui->state = AS_DYING;
492 _ret_if(ui->ops == NULL);
496 _DBG("[APP %d] RESET", _pid);
497 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]",
500 r = ui->ops->reset(b, ui->ops->data);
501 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]", ui->name);
505 is_legacy_lifecycle = aul_get_support_legacy_lifecycle();
507 _INFO("Legacy lifecycle: %d", is_legacy_lifecycle);
508 if (!is_legacy_lifecycle) {
509 _INFO("[APP %d] Initial Launching, call the resume_cb", _pid);
511 r = ui->ops->resume(ui->ops->data);
514 _INFO("Legacy lifecycle: %d", is_legacy_lifecycle);
515 if (!is_legacy_lifecycle) {
516 _INFO("[APP %d] App already running, raise the window", _pid);
517 x_raise_win(getpid());
519 if (ui->state == AS_PAUSED) {
520 _INFO("[APP %d] Call the resume_cb", _pid);
522 r = ui->ops->resume(ui->ops->data);
527 ui->state = AS_RUNNING;
529 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
530 miniapp = bundle_get_val(b, "http://tizen.org/appcontrol/data/miniapp");
531 if(miniapp && strncmp(miniapp, "on", 2) == 0) {
532 ecore_timer_add(0.5, __appcore_mimiapp_capture_cb, NULL);
537 if (ui->state == AS_RUNNING) {
538 _DBG("[APP %d] PAUSE", _pid);
540 r = ui->ops->pause(ui->ops->data);
541 ui->state = AS_PAUSED;
542 if(r >= 0 && resource_reclaiming == TRUE)
543 __appcore_timer_add(ui);
545 /* TODO : rotation stop */
546 //r = appcore_pause_rotation_cb();
548 snprintf(trm_buf, MAX_PACKAGE_STR_SIZE, "appinfo_pause:[PID]%d", getpid());
549 __trm_app_info_send_socket(trm_buf);
551 proc_group_change_status(PROC_CGROUP_SET_BACKGRD, getpid(), NULL);
556 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]",
558 if (ui->state == AS_PAUSED) {
559 _DBG("[APP %d] RESUME", _pid);
561 r = ui->ops->resume(ui->ops->data);
562 ui->state = AS_RUNNING;
564 /*TODO : rotation start*/
565 //r = appcore_resume_rotation_cb();
566 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]",
568 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:Launching:done]",
571 #ifdef _GATE_TEST_ENABLE
572 if(strncmp(ui->name, "wrt-client", 10) != 0) {
573 LOG(LOG_DEBUG, "GATE-M", "<GATE-M>APP_FULLY_LOADED_%s<GATE-M>", ui->name);
578 proc_group_change_status(PROC_CGROUP_SET_FOREGRD, getpid(), NULL);
580 snprintf(trm_buf, MAX_PACKAGE_STR_SIZE,"appinfo_resume:[PID]%d", getpid());
581 __trm_app_info_send_socket(trm_buf);
582 #ifdef _APPFW_FEATURE_CPU_BOOST
594 static struct ui_ops efl_ops = {
600 static bool __check_visible(void)
603 struct win_node *entry = NULL;
605 for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
607 //_DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
608 if(entry->bfobscured == FALSE)
614 static bool __check_skip(Ecore_X_Window xwin)
617 Ecore_X_Window_State *state;
620 ret = ecore_x_netwm_window_state_get(xwin, &state, &num);
621 _DBG("ret(%d), win(%x), state(%x), num(%d)", ret, xwin, state, num);
623 for (i = 0; i < num; i++) {
624 _DBG("state[%d] : %d", i, state[i]);
626 case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
630 case ECORE_X_WINDOW_STATE_SKIP_PAGER:
644 static bool __exist_win(unsigned int win)
646 struct win_node temp;
651 f = g_slist_find_custom(g_winnode_list, &temp, WIN_COMP);
660 static bool __add_win(unsigned int win)
665 t = calloc(1, sizeof(struct win_node));
670 t->bfobscured = TRUE;
672 _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
674 f = g_slist_find_custom(g_winnode_list, t, WIN_COMP);
678 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
683 g_winnode_list = g_slist_append(g_winnode_list, t);
689 static bool __delete_win(unsigned int win)
691 struct win_node temp;
696 f = g_slist_find_custom(g_winnode_list, &temp, WIN_COMP);
699 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n",
705 g_winnode_list = g_slist_delete_link(g_winnode_list, f);
710 static bool __update_win(unsigned int win, bool bfobscured)
712 struct win_node temp;
717 _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
722 f = g_slist_find_custom(g_winnode_list, &temp, WIN_COMP);
726 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
731 g_winnode_list = g_slist_delete_link(g_winnode_list, f);
733 t = calloc(1, sizeof(struct win_node));
738 t->bfobscured = bfobscured;
740 g_winnode_list = g_slist_append(g_winnode_list, t);
747 static Ecore_X_Atom _WM_WINDOW_ROTATION_SUPPORTED = 0;
748 static Ecore_X_Atom _WM_WINDOW_ROTATION_CHANGE_REQUEST = 0;
750 static int __check_wm_rotation_support(void)
752 _DBG("Disable window manager rotation");
755 Ecore_X_Window root, win, win2;
758 if (!_WM_WINDOW_ROTATION_SUPPORTED) {
759 _WM_WINDOW_ROTATION_SUPPORTED =
760 ecore_x_atom_get("_E_WINDOW_ROTATION_SUPPORTED");
763 if (!_WM_WINDOW_ROTATION_CHANGE_REQUEST) {
764 _WM_WINDOW_ROTATION_CHANGE_REQUEST =
765 ecore_x_atom_get("_E_WINDOW_ROTATION_CHANGE_REQUEST");
768 root = ecore_x_window_root_first_get();
769 ret = ecore_x_window_prop_xid_get(root,
770 _WM_WINDOW_ROTATION_SUPPORTED,
773 if ((ret == 1) && (win))
775 ret = ecore_x_window_prop_xid_get(win,
776 _WM_WINDOW_ROTATION_SUPPORTED,
779 if ((ret == 1) && (win2 == win))
787 static void __set_wm_rotation_support(unsigned int win, unsigned int set)
790 struct win_node *entry = NULL;
793 for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
796 ecore_x_window_prop_card32_set(entry->win,
797 _WM_WINDOW_ROTATION_SUPPORTED,
802 ecore_x_window_prop_card32_set(win,
803 _WM_WINDOW_ROTATION_SUPPORTED,
808 Ecore_X_Atom atom_parent;
809 Ecore_X_Atom xsend_Atom;
811 static Eina_Bool __show_cb(void *data, int type, void *event)
813 Ecore_X_Event_Window_Show *ev;
815 Ecore_X_Window parent;
819 ret = ecore_x_window_prop_window_get(ev->win, atom_parent, &parent, 1);
822 // This is child window. Skip!!!
823 return ECORE_CALLBACK_PASS_ON;
826 _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x\n", ev->win);
828 if (!__exist_win((unsigned int)ev->win)) {
830 if ((priv.wm_rot_supported) && (1 == priv.rot_started)) {
831 __set_wm_rotation_support(ev->win, 1);
833 __add_win((unsigned int)ev->win);
836 __update_win((unsigned int)ev->win, FALSE);
838 return ECORE_CALLBACK_RENEW;
841 static Eina_Bool __hide_cb(void *data, int type, void *event)
843 Ecore_X_Event_Window_Hide *ev;
848 _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
850 if (__exist_win((unsigned int)ev->win)) {
851 __delete_win((unsigned int)ev->win);
853 bvisibility = __check_visible();
854 if (!bvisibility && b_active != 0) {
855 _DBG(" Go to Pasue state \n");
857 __do_app(AE_PAUSE, data, NULL);
858 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
860 _capture_and_make_file(ev->win, getpid(), appid);
861 } else if ( aul_is_subapp() ) {
862 _capture_and_make_file(ev->win, getpid(), appcore_get_caller_appid());
868 return ECORE_CALLBACK_RENEW;
871 static Eina_Bool __visibility_cb(void *data, int type, void *event)
873 Ecore_X_Event_Window_Visibility_Change *ev;
875 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
881 __update_win((unsigned int)ev->win, ev->fully_obscured);
882 bvisibility = __check_visible();
884 _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
886 if (bvisibility && b_active != 1) {
887 _DBG(" Go to Resume state\n");
890 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
891 vconf_get_int(VCONFKEY_PM_STATE, &lcd_status);
892 if(lcd_status == VCONFKEY_PM_STATE_LCDOFF) {
893 return ECORE_CALLBACK_RENEW;
896 __do_app(AE_RESUME, data, NULL);
897 } else if (!bvisibility && (b_active != 0)) {
898 _DBG(" Go to Pasue state \n");
900 __do_app(AE_PAUSE, data, NULL);
901 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
903 _capture_and_make_file(ev->win, getpid(), appid);
904 } else if ( aul_is_subapp() ) {
905 _capture_and_make_file(ev->win, getpid(), appcore_get_caller_appid());
909 _DBG(" No change state \n");
911 return ECORE_CALLBACK_RENEW;
916 static Eina_Bool __cmsg_cb(void *data, int type, void *event)
918 struct ui_priv *ui = (struct ui_priv *)data;
919 Ecore_X_Event_Client_Message *e = event;
921 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
922 if (e->message_type == xsend_Atom) {
923 _DBG("_E_ILLUME_ATOM_APPCORE_RECAPTURE_REQUEST win(%x)", e->win);
924 _capture_and_make_file(e->win, getpid(), appid);
925 return ECORE_CALLBACK_PASS_ON;
929 if (!ui) return ECORE_CALLBACK_PASS_ON;
930 if (e->format != 32) return ECORE_CALLBACK_PASS_ON;
931 if (e->message_type == _WM_WINDOW_ROTATION_CHANGE_REQUEST) {
932 if ((0 == ui->wm_rot_supported) ||
933 (0 == ui->rot_started) ||
934 (NULL == ui->rot_cb)) {
935 return ECORE_CALLBACK_PASS_ON;
939 switch (e->data.l[1])
941 case 0: rm = APPCORE_RM_PORTRAIT_NORMAL; break;
942 case 90: rm = APPCORE_RM_LANDSCAPE_REVERSE; break;
943 case 180: rm = APPCORE_RM_PORTRAIT_REVERSE; break;
944 case 270: rm = APPCORE_RM_LANDSCAPE_NORMAL; break;
945 default: rm = APPCORE_RM_UNKNOWN; break;
950 if (APPCORE_RM_UNKNOWN != rm) {
951 ui->rot_cb((void *)&rm, rm, ui->rot_cb_data);
955 return ECORE_CALLBACK_PASS_ON;
958 static void __add_climsg_cb(struct ui_priv *ui)
962 atom_parent = ecore_x_atom_get("_E_PARENT_BORDER_WINDOW");
966 _ERR("atom_parent is NULL");
968 xsend_Atom = ecore_x_atom_get("_E_ILLUME_ATOM_APPCORE_RECAPTURE_REQUEST");
972 _ERR("xsend_Atom is NULL");
975 ui->hshow = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, __show_cb, ui);
976 ui->hhide = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, __hide_cb, ui);
977 ui->hvchange = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE, __visibility_cb, ui);
979 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
980 ui->hcmsg = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, __cmsg_cb, ui);
983 /* Add client message callback for WM_ROTATE */
984 if(!__check_wm_rotation_support())
986 //ui->hcmsg = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, __cmsg_cb, ui);
987 ui->wm_rot_supported = 1;
988 appcore_set_wm_rotation(&wm_rotate);
992 static int __before_loop(struct ui_priv *ui, int *argc, char ***argv)
998 if (argc == NULL || argv == NULL) {
999 _ERR("argc/argv is NULL");
1005 elm_init(*argc, *argv);
1007 hwacc = getenv("HWACC");
1009 _DBG("elm_config_preferred_engine_set is not called");
1010 } else if(strcmp(hwacc, "USE") == 0) {
1011 elm_config_preferred_engine_set("opengl_x11");
1012 _DBG("elm_config_preferred_engine_set : opengl_x11");
1013 } else if(strcmp(hwacc, "NOT_USE") == 0) {
1014 elm_config_preferred_engine_set("software_x11");
1015 _DBG("elm_config_preferred_engine_set : software_x11");
1017 _DBG("elm_config_preferred_engine_set is not called");
1019 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
1020 tm_tmp = getenv("TASKMANAGE");
1021 if(tm_tmp == NULL) {
1022 _DBG("taskmanage is null");
1024 } else if(strcmp(tm_tmp, "false") == 0) {
1025 _DBG("taskmanage is false");
1028 _DBG("taskmanage is true %s", tm_tmp);
1032 r = appcore_init(ui->name, &efl_ops, *argc, *argv);
1033 _retv_if(r == -1, -1);
1035 LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:appcore_init:done]", ui->name);
1036 if (ui->ops && ui->ops->create) {
1037 r = ui->ops->create(ui->ops->data);
1039 _ERR("create() return error");
1044 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]",
1047 ui->state = AS_CREATED;
1049 __add_climsg_cb(ui);
1054 static void __after_loop(struct ui_priv *ui)
1056 appcore_unset_rotation_cb();
1059 if (ui->state == AS_RUNNING) {
1060 _DBG("[APP %d] PAUSE before termination", _pid);
1061 if (ui->ops && ui->ops->pause)
1062 ui->ops->pause(ui->ops->data);
1065 if (ui->ops && ui->ops->terminate)
1066 ui->ops->terminate(ui->ops->data);
1069 ecore_event_handler_del(ui->hshow);
1071 ecore_event_handler_del(ui->hhide);
1073 ecore_event_handler_del(ui->hvchange);
1075 __appcore_timer_del(ui);
1079 #ifdef _GATE_TEST_ENABLE
1080 if((ui->name) && (strncmp(ui->name, "wrt-client", 10) != 0)) {
1081 LOG(LOG_DEBUG, "GATE-M", "<GATE-M>APP_CLOSED_%s<GATE-M>", ui->name);
1086 static int __set_data(struct ui_priv *ui, const char *name,
1087 struct appcore_ops *ops)
1090 _ERR("Mainloop already started");
1091 errno = EINPROGRESS;
1095 if (name == NULL || name[0] == '\0') {
1096 _ERR("Invalid name");
1102 _ERR("ops is NULL");
1107 ui->name = strdup(name);
1108 _retv_if(ui->name == NULL, -1);
1112 ui->mfcb = __appcore_efl_memory_flush_cb;
1117 ui->wm_rot_supported = 0;
1118 ui->rot_started = 0;
1120 ui->rot_cb_data = NULL;
1121 ui->rot_mode = APPCORE_RM_UNKNOWN;
1126 static void __unset_data(struct ui_priv *ui)
1129 free((void *)ui->name);
1131 memset(ui, 0, sizeof(struct ui_priv));
1135 static int __wm_set_rotation_cb(int (*cb) (void *event_info, enum appcore_rm, void *), void *data)
1142 if ((priv.wm_rot_supported) && (0 == priv.rot_started)) {
1143 __set_wm_rotation_support(0, 1);
1147 priv.rot_cb_data = data;
1148 priv.rot_started = 1;
1153 static int __wm_unset_rotation_cb(void)
1155 if ((priv.wm_rot_supported) && (1 == priv.rot_started)) {
1156 __set_wm_rotation_support(0, 0);
1160 priv.rot_cb_data = NULL;
1161 priv.rot_started = 0;
1166 static int __wm_get_rotation_state(enum appcore_rm *curr)
1173 *curr = priv.rot_mode;
1178 static int __wm_pause_rotation_cb(void)
1180 if ((1 == priv.rot_started) && (priv.wm_rot_supported)) {
1181 __set_wm_rotation_support(0, 0);
1184 priv.rot_started = 0;
1189 static int __wm_resume_rotation_cb(void)
1191 if ((0 == priv.rot_started) && (priv.wm_rot_supported)) {
1192 __set_wm_rotation_support(0, 1);
1195 priv.rot_started = 1;
1200 static struct ui_wm_rotate wm_rotate = {
1201 __wm_set_rotation_cb,
1202 __wm_unset_rotation_cb,
1203 __wm_get_rotation_state,
1204 __wm_pause_rotation_cb,
1205 __wm_resume_rotation_cb
1208 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
1209 static Window _get_parent_window(Window id)
1216 if (!XQueryTree(ecore_x_display_get(), id, &root, &parent, &children, &num)) {
1227 static Window _find_capture_window(Window id, Visual **visual, int *depth, int *width, int *height)
1229 XWindowAttributes attr;
1231 Window orig_id = id;
1240 if (!XGetWindowAttributes(ecore_x_display_get(), id, &attr)) {
1244 parent = _get_parent_window(id);
1246 if (attr.map_state == IsViewable
1247 && attr.override_redirect == True
1248 && attr.class == InputOutput && parent == attr.root) {
1249 *depth = attr.depth;
1250 *width = attr.width;
1251 *height = attr.height;
1252 *visual = attr.visual;
1255 } while (parent != attr.root && parent != 0);
1257 XGetWindowAttributes(ecore_x_display_get(), orig_id, &attr);
1258 *depth = attr.depth;
1259 *width = attr.width;
1260 *height = attr.height;
1261 *visual = attr.visual;
1267 static char *_capture_window(Window id, Visual *visual, int width, int height, int depth, int *size)
1272 char *captured_img = NULL;
1274 /* (depth >> 3) + 1 == 4 byte */
1276 shmget(IPC_PRIVATE, width * height * ((depth >> 3) + 1),
1284 si.readOnly = False;
1285 si.shmaddr = shmat(si.shmid, NULL, 0);
1287 if (si.shmaddr == (char *)-1) {
1289 shmctl(si.shmid, IPC_RMID, 0);
1293 xim = XShmCreateImage(ecore_x_display_get(), visual, depth, ZPixmap, NULL, &si,
1298 shmctl(si.shmid, IPC_RMID, 0);
1303 img_size = xim->bytes_per_line * xim->height;
1304 xim->data = si.shmaddr;
1306 XSync(ecore_x_display_get(), False);
1307 XShmAttach(ecore_x_display_get(), &si);
1308 XShmGetImage(ecore_x_display_get(), id, xim, 0, 0, 0xFFFFFFFF);
1309 XSync(ecore_x_display_get(), False);
1311 captured_img = calloc(1, img_size);
1313 memcpy(captured_img, xim->data, img_size);
1318 XShmDetach(ecore_x_display_get(), &si);
1323 shmctl(si.shmid, IPC_RMID, 0);
1327 return captured_img;
1331 #define _WND_REQUEST_ANGLE_IDX 0
1332 #define _WND_CURR_ANGLE_IDX 1
1333 int _get_angle(Ecore_X_Window win)
1340 int angle[2] = {-1, -1};
1341 unsigned char* prop_data = NULL;
1343 ret = ecore_x_window_prop_property_get(win,
1344 ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
1345 ECORE_X_ATOM_CARDINAL,
1350 if (prop_data) free(prop_data);
1355 memcpy(&angle, prop_data, sizeof (int) *count);
1359 after= angle[_WND_REQUEST_ANGLE_IDX];
1360 before = angle[_WND_CURR_ANGLE_IDX];
1363 if (-1 == after) after = 0;
1368 static void _rotate_img(Evas_Object *image_object, int angle, int cx, int cy)
1372 _ret_if(NULL == image_object);
1374 em = evas_map_new(4);
1375 _ret_if(NULL == em);
1377 evas_map_util_points_populate_from_object(em, image_object);
1378 evas_map_util_rotate(em, (double) angle, cx, cy);
1380 evas_object_map_set(image_object, em);
1381 evas_object_map_enable_set(image_object, EINA_TRUE);
1386 #define EXTENSION_LEN 128
1387 #define CAPTURE_FILE_PATH "/opt/usr/share/app_capture"
1388 bool _make_capture_file(const char *package, int width, int height, char *img, int angle)
1393 Evas_Object *image_object;
1394 int canvas_width, canvas_height;
1399 _retv_if(NULL == package, false);
1401 len = strlen(package) + EXTENSION_LEN;
1402 filename = malloc(len);
1403 _retv_if(NULL == filename, false);
1404 snprintf(filename, len, CAPTURE_FILE_PATH"/%s.jpg", package);
1406 if (90 == angle || 270 == angle) {
1407 canvas_width = height;
1408 canvas_height = width;
1410 canvas_width = width;
1411 canvas_height = height;
1414 e = virtual_canvas_create(canvas_width, canvas_height);
1415 goto_if(NULL == e, error);
1417 image_object = evas_object_image_add(e);
1418 goto_if(NULL == image_object, error);
1420 evas_object_image_size_set(image_object, width, height);
1421 evas_object_image_data_set(image_object, img);
1422 evas_object_image_data_update_add(image_object, 0, 0, width, height);
1423 evas_object_resize(image_object, width, height);
1424 evas_object_image_filled_set(image_object, EINA_TRUE);
1427 cx = canvas_width - width / 2;
1428 cy = canvas_height / 2;
1429 mx = canvas_width - width;
1437 cy = canvas_height / 2;
1442 evas_object_move(image_object, mx, 0);
1443 _rotate_img(image_object, angle, cx, cy);
1444 evas_object_show(image_object);
1446 if (access(CAPTURE_FILE_PATH, F_OK) != 0) {
1447 r = mkdir(CAPTURE_FILE_PATH, 0777);
1448 goto_if(r < 0, error);
1450 goto_if(false == virtual_canvas_flush_to_file(e, filename, canvas_width, canvas_height), error);
1452 evas_object_del(image_object);
1453 virtual_canvas_destroy(e);
1463 virtual_canvas_destroy(e);
1465 if (!image_object) break;
1466 evas_object_del(image_object);
1472 int __resize8888(const char* pDataIn, char* pDataOut, int inWidth, int inHeight, int outWidth, int outHeight)
1480 char* pOutput = pDataOut;
1481 char* pOut = pDataOut;
1482 const char* pIn = NULL;
1483 int *pColLUT = malloc(sizeof(int) * outWidth);
1485 /* Calculate X Scale factor */
1486 scaleX = inWidth * 256 / outWidth;
1487 /* Calculate Y Scale factor, aspect ratio is not maintained */
1488 scaleY = inHeight * 256 / outHeight;
1489 for (j = 0; j < outWidth; j++)
1491 /* Get input index based on column scale factor */
1492 /* To get more optimization, this is calculated once and
1493 * is placed in a LUT and used for indexing
1495 pColLUT [j] = ((j * scaleX) >> 8) * 4;
1498 for (i = 0; i < outHeight; i++)
1500 /* Get input routWidth index based on routWidth scale factor */
1501 iRow = (i * scaleY >> 8) * inWidth * 4;
1502 /* Loop could be unrolled for more optimization */
1503 for (j = 0; j < (outWidth); j++)
1505 /* Get input index based on column scale factor */
1506 iIndex = iRow + pColLUT [j];
1507 pIn = pDataIn + iIndex;
1519 static void _capture_and_make_file(Ecore_X_Window win, int pid, const char *package)
1522 Window redirected_id;
1524 int width, height, depth;
1525 int width_out, height_out;
1531 redirected_id = _find_capture_window(win, &visual, &depth, &width, &height);
1532 _ret_if(redirected_id == (Window) -1 ||
1533 redirected_id == (Window) 0);
1535 SECURE_LOGD("Capture : win[%x] -> redirected win[%x] for %s[%d]", win, redirected_id, package, pid);
1537 img = _capture_window(redirected_id, visual, width, height, depth, &size);
1538 _ret_if(NULL == img);
1540 width_out = width/2;
1541 height_out = height/2;
1543 if ( width_out < 1 || height_out < 1 ) {
1548 __resize8888(img, img, width, height, width_out, height_out);
1550 angle = _get_angle(win);
1551 if (false == _make_capture_file(package, width_out, height_out, img, angle)) {
1552 _ERR("cannot a capture file for the package of [%s]", package);
1559 extern int aul_status_update(int status);
1561 EXPORT_API int appcore_efl_main(const char *name, int *argc, char ***argv,
1562 struct appcore_ops *ops)
1565 GSList *iter = NULL;
1566 struct win_node *entry = NULL;
1569 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", name);
1572 r = aul_app_get_appid_bypid(pid, appid, APPID_MAX);
1574 _ERR("aul_app_get_appid_bypid fail");
1577 r = __set_data(&priv, name, ops);
1578 _retv_if(r == -1, -1);
1580 r = __before_loop(&priv, argc, argv);
1582 __unset_data(&priv);
1588 aul_status_update(STATUS_DYING);
1590 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
1591 for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
1593 if(__check_skip(entry->win) == FALSE)
1599 _capture_and_make_file(entry->win, pid, appid);
1604 __after_loop(&priv);
1606 __unset_data(&priv);
1611 EXPORT_API int appcore_set_system_resource_reclaiming(bool enable)
1613 resource_reclaiming = enable;
1618 EXPORT_API int appcore_set_app_state(int state)
1625 EXPORT_API int appcore_efl_goto_pause()
1627 _DBG(" Go to Pasue state \n");
1629 __do_app(AE_PAUSE, &priv, NULL);
1634 EXPORT_API int appcore_set_prelaunching(bool value)
1636 prelaunching = value;
1641 #ifdef _APPFW_FEATURE_PROCESS_POOL
1642 EXPORT_API int appcore_set_preinit_window_name(const char* win_name)
1645 void *preinit_window = NULL;
1648 _ERR("invalid input param");
1652 preinit_window = aul_get_preinit_window(win_name);
1653 if(!preinit_window) {
1654 _ERR("no preinit window");
1658 const Evas *e = evas_object_evas_get((const Evas_Object *)preinit_window);
1660 Ecore_Evas *ee = ecore_evas_ecore_evas_get(e);
1662 ecore_evas_name_class_set(ee, win_name, win_name);
1663 _DBG("name class set success : %s", win_name);