From: Nikita Kalyazin Date: Tue, 31 Dec 2013 09:13:20 +0000 (+0400) Subject: [REFACTOR] replace epoll with ecore X-Git-Tag: Tizen_SDK_2.3~92 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F61%2F14261%2F6;p=platform%2Fcore%2Fsystem%2Fswap-manager.git [REFACTOR] replace epoll with ecore also extracted input events code to a separate file. Change-Id: If6ad2be1a305add9988287447547565a9d6e3d23 Signed-off-by: Nikita Kalyazin --- diff --git a/daemon/Makefile b/daemon/Makefile index f615e39..0cbb803 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -17,8 +17,8 @@ ifeq (arm, $(findstring arm, $(shell uname -sm))) endif COMMON_LIBS := -lglib-2.0 -lpthread -TARGET_LIBS := $(COMMON_LIBS) -lvconf -lsmack -lcapi-system-info -CFLAGS := -Wall -pthread -g -O0 +TARGET_LIBS := $(COMMON_LIBS) -lvconf -lsmack -lcapi-system-info -lecore -leina -lpthread +CFLAGS := -Wall -pthread -g -O0 -I/usr/include/ecore-1 -I/usr/include/eina-1 -I/usr/include/eina-1/eina DAEMON_SRCS = \ buffer.c \ @@ -37,7 +37,8 @@ DAEMON_SRCS = \ transfer_thread.c \ utils.c \ da_protocol_check.c \ - md5.c + md5.c \ + input_events.c DAEMON_OBJS = $(patsubst %.c,%.o, $(DAEMON_SRCS)) diff --git a/daemon/daemon.c b/daemon/daemon.c index 9260006..0f0412c 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -40,7 +40,6 @@ #include // for accept #include // for mkdir #include // for eventfd -#include // for epoll apis #include // for timerfd #include // for access, sleep #include @@ -50,151 +49,28 @@ #include // for fsetxattr #include -#include -#include #include #include +#include + #include "daemon.h" #include "sys_stat.h" #include "utils.h" #include "da_protocol.h" #include "da_inst.h" #include "da_data.h" +#include "input_events.h" #include "debug.h" #define DA_WORK_DIR "/home/developer/sdk_tools/da/" #define DA_READELF_PATH "/home/developer/sdk_tools/da/readelf" #define SCREENSHOT_DIR "/tmp/da" -#define EPOLL_SIZE 10 #define MAX_APP_LAUNCH_TIME 60 #define MAX_CONNECT_TIMEOUT_TIME 5*60 -#define MAX_DEVICE 10 -#define MAX_FILENAME 128 -#define BUF_SIZE 1024 -#define ARRAY_END (-11) - -input_dev g_key_dev[MAX_DEVICE]; -input_dev g_touch_dev[MAX_DEVICE]; - -const char *input_key_devices[] = { - /* target: Emulator, kernel: 3.4, all buttons */ - "Maru Virtio Hwkey", - /* target: M0, kernel: 3.0, buttons: volume +/-, home, power */ - "gpio-keys", - /* target: M0, kernel: 3.0, buttons: menu, back */ - "melfas-touchkey", - /* target: M0, kernel: 3.10, buttons: menu, back */ - "MELFAS MCS Touchkey", - /* target: M0, kernel: 3.10, buttons: volume +/-, home, power */ - "gpio-keys.5", - NULL //array tail -}; - -const char *input_touch_devices[] = { - /* target: Emulator, kernel: 3.0 */ - "Maru Virtio Touchscreen", - /* target: M0, kernel: 3.0 */ - "sec_touchscreen", - /* target: M0, kernel: 3.10 */ - "MELPAS MMS114 Touchscreen", - NULL //array tail -}; - - -static int check_input(char *inputname, int input_id) -{ - int ret = -1; - FILE *cmd_fp = NULL; - char buffer[BUF_SIZE]; - char command[MAX_FILENAME]; - char **name_arr; - size_t bytes_count; - - sprintf(command, "/sys/class/input/%s/device/name", inputname); - // run command - cmd_fp = fopen(command, "r"); - if (cmd_fp == NULL) - goto exit; - - buffer[0] = '\0'; - bytes_count = fread(buffer, 1, BUF_SIZE, cmd_fp); - if (bytes_count <= 1) { - LOGE("Failed to read input_id\n"); - goto exit; - } else { - buffer[bytes_count - 1] = '\0'; - } - - if (input_id == INPUT_ID_KEY) - name_arr = input_key_devices; - else if (input_id == INPUT_ID_TOUCH) - name_arr = input_touch_devices; - else - goto exit; - - while (*name_arr != NULL) { - if (strcmp(buffer, *name_arr) == 0) { - ret = 0; - goto exit; - } - name_arr++; - } - -exit: - if (cmd_fp != NULL) - pclose(cmd_fp); - return ret; -} - -// get filename and fd of given input type devices -static void _get_fds(input_dev *dev, int input_id) -{ - DIR *dp; - struct dirent *d; - int count = 0; - - dp = opendir("/sys/class/input"); - - if (dp == NULL) - goto exit; - - while ((d = readdir(dp)) != NULL) { - if (!strncmp(d->d_name, "event", 5)) { - // start with "event" - // event file - if (!check_input(d->d_name, input_id)) { - sprintf(dev[count].fileName, - "/dev/input/%s", d->d_name); - dev[count].fd = open(dev[count].fileName, - O_RDWR | O_NONBLOCK); - count++; - } - } - } - - closedir(dp); - -exit: - dev[count].fd = ARRAY_END; // end of input_dev array -} - -//static -void _device_write(input_dev *dev, struct input_event *in_ev) -{ - int i; - for (i = 0; dev[i].fd != ARRAY_END; i++) { - if (dev[i].fd >= 0) { - write(dev[i].fd, in_ev, sizeof(struct input_event)); - LOGI("write(%d, %d, %d)\n", - dev[i].fd, (int)in_ev, sizeof(struct input_event)); - } - } -} - uint64_t get_total_alloc_size() { int i; @@ -239,11 +115,30 @@ static void setEmptyTargetSlot(int index) // start and terminate control functions // ============================================================================= +static Ecore_Fd_Handler *launch_timer_handler; + +//stop application launch timer +static int stop_app_launch_timer() +{ + close(manager.app_launch_timerfd); + manager.app_launch_timerfd = -1; + + return 0; +} + +static Eina_Bool launch_timer_cb(void *data, Ecore_Fd_Handler *fd_handler) +{ + LOGE("Failed to launch application\n"); + if (stop_app_launch_timer() < 0) + LOGE("cannot stop app launch timer\n"); + + return ECORE_CALLBACK_CANCEL; +} + //start application launch timer function static int start_app_launch_timer(int apps_count) { int res = 0; - struct epoll_event ev; assert(apps_count >= 0 && "negative apps count"); @@ -260,19 +155,18 @@ static int start_app_launch_timer(int apps_count) ctime.it_interval.tv_nsec = 0; if (timerfd_settime(manager.app_launch_timerfd, 0, &ctime, NULL) < 0) { LOGE("fail to set app launch timer\n"); - close(manager.app_launch_timerfd); - manager.app_launch_timerfd = -1; + stop_app_launch_timer(); res = -1; } else { - // add event fd to epoll list - ev.events = EPOLLIN; - ev.data.fd = manager.app_launch_timerfd; - if (epoll_ctl(manager.efd, EPOLL_CTL_ADD, - manager.app_launch_timerfd, &ev) < 0) { - // fail to add event fd - LOGE("fail to add app launch timer fd to epoll list\n"); - close(manager.app_launch_timerfd); - manager.app_launch_timerfd = -1; + launch_timer_handler = + ecore_main_fd_handler_add(manager.app_launch_timerfd, + ECORE_FD_READ, + launch_timer_cb, + NULL, + NULL, NULL); + if (!launch_timer_handler) { + LOGE("fail to add app launch timer fd to \n"); + stop_app_launch_timer(); res = -2; } else { LOGI("application launch time started\n"); @@ -286,17 +180,6 @@ static int start_app_launch_timer(int apps_count) return res; } -//stop application launch timer -static int stop_app_launch_timer() -{ - if (0 > epoll_ctl(manager.efd, EPOLL_CTL_DEL, - manager.app_launch_timerfd, NULL)) - LOGW("fail to EPOLL DEL of app launch timerfd\n"); - close(manager.app_launch_timerfd); - manager.app_launch_timerfd = -1; - return 0; -} - static inline void inc_apps_to_run() { manager.apps_to_run++; @@ -382,9 +265,80 @@ static int exec_app(const struct app_info_t *app_info) return res; } +// just send stop message to all target process +static void terminate_all_target() +{ + int i; + ssize_t sendlen; + msg_target_t sendlog; + + sendlog.type = MSG_STOP; + sendlog.length = 0; + + for (i = 0; i < MAX_TARGET_COUNT; i++) { + if (manager.target[i].socket != -1) { + sendlen = send(manager.target[i].socket, &sendlog, + sizeof(sendlog.type) + + sizeof(sendlog.length), MSG_NOSIGNAL); + if (sendlen != -1) { + LOGI("TERMINATE send exit msg (socket %d) " + "by terminate_all_target()\n", + manager.target[i].socket); + } + } + } +} + +// terminate all target and wait for threads +void terminate_all() +{ + int i; + terminate_all_target(); + + // wait for all other thread exit + for (i = 0; i < MAX_TARGET_COUNT; i++) { + if (manager.target[i].recv_thread != -1) { + LOGI("join recv thread [%d] is started\n", i); + pthread_join(manager.target[i].recv_thread, NULL); + LOGI("join recv thread %d. done\n", i); + } + } +} + +// terminate all profiling by critical error +// TODO: don't send data to host +static void terminate_error(char *errstr, int send_to_host) +{ + LOGE("termination all with err '%s'\n", errstr); + struct msg_data_t *msg = NULL; + if (send_to_host != 0) { + msg = gen_message_error(errstr); + if (msg) { + write_to_buf(msg); + free_msg_data(msg); + } else { + LOGI("cannot generate error message\n"); + } + } + terminate_all(); +} + +static Ecore_Fd_Handler *connect_timer_handler; + +static Eina_Bool connect_timer_cb(void *data, Ecore_Fd_Handler *fd_handler) +{ + terminate_error("no incoming connections", 1); + close(manager.connect_timeout_timerfd); + manager.connect_timeout_timerfd = -1; + LOGE("No connection in %d sec. shutdown.\n", + MAX_CONNECT_TIMEOUT_TIME); + ecore_main_loop_quit(); + + return ECORE_CALLBACK_CANCEL; +} + int launch_timer_start() { - static struct epoll_event ev; int res = 0; manager.connect_timeout_timerfd = @@ -400,14 +354,14 @@ int launch_timer_start() close(manager.connect_timeout_timerfd); manager.connect_timeout_timerfd = -1; } else { - // add event fd to epoll list - ev.events = EPOLLIN; - ev.data.fd = manager.connect_timeout_timerfd; - if (epoll_ctl(manager.efd, EPOLL_CTL_ADD, - manager.connect_timeout_timerfd, &ev) < 0) - { - // fail to add event fd - LOGE("fail to add app connection timeout timer fd to epoll list\n"); + connect_timer_handler = + ecore_main_fd_handler_add(manager.connect_timeout_timerfd, + ECORE_FD_READ, + connect_timer_cb, + NULL, + NULL, NULL); + if (!connect_timer_handler) { + LOGE("fail to add app connection timeout timer fd\n"); close(manager.connect_timeout_timerfd); manager.connect_timeout_timerfd = -1; } else { @@ -422,9 +376,6 @@ int launch_timer_start() return res; } -static void epoll_add_input_events(); -static void epoll_del_input_events(); - int prepare_profiling() { struct app_list_t *app = NULL; @@ -477,7 +428,7 @@ int start_profiling() } if (IS_OPT_SET(FL_RECORDING)) - epoll_add_input_events(); + add_input_events(); while (app_info != NULL) { if (exec_app(app_info)) { @@ -497,7 +448,7 @@ int start_profiling() recording_stop: if (IS_OPT_SET(FL_RECORDING)) - epoll_del_input_events(); + del_input_events(); samplingStop(); exit: @@ -508,7 +459,7 @@ int start_profiling() void stop_profiling(void) { if (IS_OPT_SET(FL_RECORDING)) - epoll_del_input_events(); + del_input_events(); samplingStop(); } @@ -520,12 +471,12 @@ static void reconfigure_recording(struct conf_t conf) uint64_t to_disable = (new_features ^ old_features) & old_features; if (IS_OPT_SET_IN(FL_RECORDING, to_disable)) { - epoll_del_input_events(); + del_input_events(); prof_session.conf.use_features0 &= ~FL_RECORDING; } if (IS_OPT_SET_IN(FL_RECORDING, to_enable)) { - epoll_add_input_events(); + add_input_events(); prof_session.conf.use_features0 |= FL_RECORDING; } @@ -545,95 +496,7 @@ int reconfigure(struct conf_t conf) return 0; } -// just send stop message to all target process -static void terminate_all_target() -{ - int i; - ssize_t sendlen; - msg_target_t sendlog; - - sendlog.type = MSG_STOP; - sendlog.length = 0; - - for (i = 0; i < MAX_TARGET_COUNT; i++) { - if (manager.target[i].socket != -1) { - sendlen = send(manager.target[i].socket, &sendlog, - sizeof(sendlog.type) + - sizeof(sendlog.length), MSG_NOSIGNAL); - if (sendlen != -1) { - LOGI("TERMINATE send exit msg (socket %d) " - "by terminate_all_target()\n", - manager.target[i].socket); - } - } - } -} - -// terminate all target and wait for threads -void terminate_all() -{ - int i; - terminate_all_target(); - - // wait for all other thread exit - for (i = 0; i < MAX_TARGET_COUNT; i++) { - if (manager.target[i].recv_thread != -1) { - LOGI("join recv thread [%d] is started\n", i); - pthread_join(manager.target[i].recv_thread, NULL); - LOGI("join recv thread %d. done\n", i); - } - } -} - -// terminate all profiling by critical error -// TODO: don't send data to host -static void terminate_error(char *errstr, int send_to_host) -{ - LOGE("termination all with err '%s'\n", errstr); - struct msg_data_t *msg = NULL; - if (send_to_host != 0) { - msg = gen_message_error(errstr); - if (msg) { - write_to_buf(msg); - free_msg_data(msg); - } else { - LOGI("cannot generate error message\n"); - } - } - terminate_all(); -} - -#define MAX_EVENTS_NUM 10 -static int deviceEventHandler(input_dev *dev, int input_type) -{ - int ret = 0; - ssize_t size = 0; - int count = 0; - struct input_event in_ev[MAX_EVENTS_NUM]; - struct msg_data_t *log; - - if (input_type == INPUT_ID_TOUCH || input_type == INPUT_ID_KEY) { - do { - size = read(dev->fd, &in_ev[count], sizeof(*in_ev)); - if (size > 0) - count++; - } while (count < MAX_EVENTS_NUM && size > 0); - - if (count) { - LOGI("read %d %s events\n", - count, - input_type == INPUT_ID_KEY ? STR_KEY : STR_TOUCH); - log = gen_message_event(in_ev, count, input_type); - printBuf((char *)log, MSG_DATA_HDR_LEN + log->len); - write_to_buf(log); - free_msg_data(log); - } - } else { - LOGW("unknown input_type\n"); - ret = 1; // it is not error - } - return ret; -} +static Ecore_Fd_Handler *target_handlers[MAX_TARGET_COUNT]; static int target_event_pid_handler(int index, uint64_t msg) { @@ -668,7 +531,7 @@ static int target_event_pid_handler(int index, uint64_t msg) return 0; } -static int target_event_stop_handler(int epollfd, int index, uint64_t msg) +static int target_event_stop_handler(int index, uint64_t msg) { LOGI("target close, socket(%d), pid(%d) : (remaining %d target)\n", manager.target[index].socket, manager.target[index].pid, @@ -677,9 +540,7 @@ static int target_event_stop_handler(int epollfd, int index, uint64_t msg) if (index == 0) // main application stop_replay(); - if (0 > epoll_ctl(epollfd, EPOLL_CTL_DEL, - manager.target[index].event_fd, NULL)) - LOGW("fail to EPOLL DEL of event fd(%d)\n", index); + ecore_main_fd_handler_del(target_handlers[index]); setEmptyTargetSlot(index); // all target client are closed @@ -697,7 +558,7 @@ static int target_event_stop_handler(int epollfd, int index, uint64_t msg) // return plus value if non critical error occur // return minus value if critical error occur // return -11 if all target process closed -static int target_event_handler(int epollfd, int index, uint64_t msg) +static int target_event_handler(int index, uint64_t msg) { int err = 0; if (msg & EVENT_PID) @@ -706,20 +567,38 @@ static int target_event_handler(int epollfd, int index, uint64_t msg) return err; if (msg & EVENT_STOP || msg & EVENT_ERROR) - err = target_event_stop_handler(epollfd, index, msg); + err = target_event_stop_handler(index, msg); return err; } +static Eina_Bool target_event_cb(void *data, Ecore_Fd_Handler *fd_handler) +{ + uint64_t u; + ssize_t recvLen; + int index = (int)data; + + recvLen = read(manager.target[index].event_fd, &u, sizeof(uint64_t)); + if (recvLen != sizeof(uint64_t)) { + // maybe closed, but ignoring is more safe then + // removing fd from event loop + } else { + if (-11 == target_event_handler(index, u)) { + LOGI("all target process is closed\n"); + } + } + + return ECORE_CALLBACK_RENEW; +} + /** * return 0 if normal case * return plus value if non critical error occur * return minus value if critical error occur */ -static int targetServerHandler(int efd) +static int targetServerHandler(void) { msg_target_t log; - struct epoll_event ev; int index = getEmptyTargetSlot(); if (index == MAX_TARGET_COUNT) { @@ -744,7 +623,7 @@ static int targetServerHandler(int efd) LOGE("fail to send data to target index(%d)\n", index); // make event fd - manager.target[index].event_fd = eventfd(0, EFD_NONBLOCK); + manager.target[index].event_fd = eventfd(EFD_CLOEXEC, EFD_NONBLOCK); if (manager.target[index].event_fd == -1) { // fail to make event fd LOGE("fail to make event fd for socket (%d)\n", @@ -752,12 +631,14 @@ static int targetServerHandler(int efd) goto TARGET_CONNECT_FAIL; } - // add event fd to epoll list - ev.events = EPOLLIN; - ev.data.fd = manager.target[index].event_fd; - if (epoll_ctl(efd, EPOLL_CTL_ADD, manager.target[index].event_fd, &ev) < 0) { - // fail to add event fd - LOGE("fail to add event fd to epoll list for socket (%d)\n", + target_handlers[index] = + ecore_main_fd_handler_add(manager.target[index].event_fd, + ECORE_FD_READ, + target_event_cb, + (void *)index, + NULL, NULL); + if (!target_handlers[index]) { + LOGE("fail to add event fd for socket (%d)\n", manager.target[index].socket); goto TARGET_CONNECT_FAIL; } @@ -767,9 +648,7 @@ static int targetServerHandler(int efd) // fail to make recv thread LOGE("fail to make recv thread for socket (%d)\n", manager.target[index].socket); - if (0 > epoll_ctl(efd, EPOLL_CTL_DEL, - manager.target[index].event_fd, NULL)) - LOGW("fail to EPOLL DEL of event fd(%d)\n", index); + ecore_main_fd_handler_del(target_handlers[index]); goto TARGET_CONNECT_FAIL; } @@ -801,53 +680,12 @@ static int targetServerHandler(int efd) } } -// return 0 if normal case -// return plus value if non critical error occur -// return minus value if critical error occur -static int hostServerHandler(int efd) -{ - static int hostserverorder = 0; - int csocket; - struct epoll_event ev; - - if (hostserverorder > 1) // control and data socket connected already - return 1; // ignore - - csocket = accept(manager.host_server_socket, NULL, NULL); - - if (csocket >= 0) { - // accept succeed - ev.events = EPOLLIN; - ev.data.fd = csocket; - if (epoll_ctl(efd, EPOLL_CTL_ADD, csocket, &ev) < 0) { - // consider as accept fail - LOGE("Failed to add socket fd to epoll list\n"); - close(csocket); - return -1; - } - - if (hostserverorder == 0) { - manager.host.control_socket = csocket; - unlink_portfile(); - LOGI("host control socket connected = %d\n", csocket); - } else { - manager.host.data_socket = csocket; - LOGI("host data socket connected = %d\n", csocket); - } - - hostserverorder++; - return 0; - } else { - // accept error - LOGE("Failed to accept from host server socket\n"); - return -1; - } -} +static Ecore_Fd_Handler *host_ctrl_handler; +static Ecore_Fd_Handler *host_data_handler; // return plus value if non critical error occur // return minus value if critical error occur // return -11 if socket closed - static int controlSocketHandler(int efd) { ssize_t recv_len; @@ -857,9 +695,6 @@ static int controlSocketHandler(int efd) if (manager.connect_timeout_timerfd >= 0) { LOGI("release connect timeout timer\n"); - if (0 > epoll_ctl(efd, EPOLL_CTL_DEL, - manager.connect_timeout_timerfd, NULL)) - LOGW("fail to EPOLL DEL of timeout timer fd\n"); close(manager.connect_timeout_timerfd); manager.connect_timeout_timerfd = -1; } @@ -893,78 +728,150 @@ static int controlSocketHandler(int efd) return res; } -static void epoll_add_input_events() +static Eina_Bool host_ctrl_cb(void *data, Ecore_Fd_Handler *fd_handler) { - struct epoll_event ev; - int i; + int result = controlSocketHandler(manager.efd); + if (result == -11) { + // socket close + //if the host disconnected. + //In all other cases daemon must report an error and continue the loop + //close connect_timeoutt and host socket and quit + LOGI("Connection closed. Termination. (%d)\n", + manager.host.control_socket); + ecore_main_loop_quit(); + } else if (result < 0) { + LOGE("Control socket handler.\n"); + } - // add device fds to epoll event pool - ev.events = EPOLLIN; - for (i = 0; g_key_dev[i].fd != ARRAY_END; i++) { - if (g_key_dev[i].fd >= 0) { - ev.data.fd = g_key_dev[i].fd; - if (epoll_ctl(manager.efd, - EPOLL_CTL_ADD, g_key_dev[i].fd, &ev) < 0 - && errno != EEXIST) - LOGE("keyboard device file epoll_ctl error: %s\n", strerror(errno)); - } + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool host_data_cb(void *data, Ecore_Fd_Handler *fd_handler) +{ + ssize_t recvLen; + char recvBuf[32]; + + recvLen = recv(manager.host.data_socket, recvBuf, 32, MSG_DONTWAIT); + if (recvLen == 0) { + // close data socket + ecore_main_fd_handler_del(host_data_handler); + close(manager.host.data_socket); + manager.host.data_socket = -1; + // TODO: finish transfer thread } - ev.events = EPOLLIN; - for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++) { - if (g_touch_dev[i].fd >= 0) { - ev.data.fd = g_touch_dev[i].fd; - if (epoll_ctl(manager.efd, - EPOLL_CTL_ADD, - g_touch_dev[i].fd, &ev) < 0 - && errno != EEXIST) - LOGE("touch device file epoll_ctl error: %s\n", strerror(errno)); + LOGI("host message from data socket %d\n", recvLen); + + return ECORE_CALLBACK_RENEW; +} + +// return 0 if normal case +// return plus value if non critical error occur +// return minus value if critical error occur +static int hostServerHandler(void) +{ + static int hostserverorder = 0; + int csocket; + + if (hostserverorder > 1) // control and data socket connected already + return 1; // ignore + + csocket = accept(manager.host_server_socket, NULL, NULL); + + if (csocket >= 0) { + // accept succeed + + if (hostserverorder == 0) { + manager.host.control_socket = csocket; + unlink_portfile(); + LOGI("host control socket connected = %d\n", csocket); + host_ctrl_handler = + ecore_main_fd_handler_add(manager.host.control_socket, + ECORE_FD_READ, + host_ctrl_cb, + NULL, + NULL, NULL); + if (!host_ctrl_handler) { + LOGE("Failed to add host control socket fd\n"); + close(csocket); + return -1; + } + } else { + manager.host.data_socket = csocket; + LOGI("host data socket connected = %d\n", csocket); + + host_data_handler = + ecore_main_fd_handler_add(manager.host.data_socket, + ECORE_FD_READ, + host_data_cb, + NULL, + NULL, NULL); + if (!host_data_handler) { + LOGE("Failed to add host data socket fd\n"); + close(csocket); + return -1; + } } + + hostserverorder++; + return 0; + } else { + // accept error + LOGE("Failed to accept from host server socket\n"); + return -1; } } -static void epoll_del_input_events() +static Ecore_Fd_Handler *host_connect_handler; +static Ecore_Fd_Handler *target_connect_handler; + +static Eina_Bool host_connect_cb(void *data, Ecore_Fd_Handler *fd_handler) { - int i; + // connect request from host + int result = hostServerHandler(); + if (result < 0) { + LOGE("Internal DA framework error (hostServerHandler)\n"); + } - // remove device fds from epoll event pool - for (i = 0; g_key_dev[i].fd != ARRAY_END; i++) - if (g_key_dev[i].fd >= 0) - if (epoll_ctl(manager.efd, - EPOLL_CTL_DEL, g_key_dev[i].fd, NULL) < 0) - LOGE("keyboard device file epoll_ctl error: %s\n", strerror(errno)); - - for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++) - if (g_touch_dev[i].fd >= 0) - if (epoll_ctl(manager.efd, - EPOLL_CTL_DEL, - g_touch_dev[i].fd, NULL) < 0) - LOGE("touch device file epoll_ctl error: %s\n", strerror(errno)); + return ECORE_CALLBACK_RENEW; } -static bool initialize_epoll_events(void) +static Eina_Bool target_connect_cb(void *data, Ecore_Fd_Handler *fd_handler) { - struct epoll_event ev; - - if ((manager.efd = epoll_create1(0)) < 0) { - LOGE("epoll creation error\n"); - return false; + if (targetServerHandler() < 0) { + // critical error + terminate_error("Internal DA framework error, " + "Please re-run the profiling " + "(targetServerHandler)\n", 1); } - // add server sockets to epoll event pool - ev.events = EPOLLIN; - ev.data.fd = manager.host_server_socket; - if (epoll_ctl(manager.efd, EPOLL_CTL_ADD, - manager.host_server_socket, &ev) < 0) { - LOGE("Host server socket epoll_ctl error\n"); + + return ECORE_CALLBACK_RENEW; +} + +static bool initialize_events(void) +{ + host_connect_handler = + ecore_main_fd_handler_add(manager.host_server_socket, + ECORE_FD_READ, + host_connect_cb, + NULL, + NULL, NULL); + if (!host_connect_handler) { + LOGE("Host server socket add error\n"); return false; } - ev.events = EPOLLIN; - ev.data.fd = manager.target_server_socket; - if (epoll_ctl(manager.efd, EPOLL_CTL_ADD, - manager.target_server_socket, &ev) < 0) { - LOGE("Target server socket epoll_ctl error\n"); + + target_connect_handler = + ecore_main_fd_handler_add(manager.target_server_socket, + ECORE_FD_READ, + target_connect_cb, + NULL, + NULL, NULL); + if (!target_connect_handler) { + LOGE("Target server socket add error\n"); return false; } + return true; } @@ -972,27 +879,15 @@ static bool initialize_epoll_events(void) int daemonLoop() { int return_value = 0; - struct epoll_event *events = malloc(EPOLL_SIZE * sizeof(*events)); - _get_fds(g_key_dev, INPUT_ID_KEY); - if (g_key_dev[0].fd == ARRAY_END) { - LOGE("No key devices found.\n"); - return_value = -1; - goto END_EVENT; - } - _get_fds(g_touch_dev, INPUT_ID_TOUCH); - if (g_touch_dev[0].fd == ARRAY_END) { - LOGE("No touch devices found.\n"); - return_value = -1; - goto END_EVENT; - } + ecore_init(); - if (!events) { - LOGE("Out of memory when allocate epoll event pool\n"); + if (init_input_events() == -1) { return_value = -1; goto END_EVENT; } - if (!initialize_epoll_events()) { + + if (!initialize_events()) { return_value = -1; goto END_EFD; } @@ -1005,151 +900,12 @@ int daemonLoop() init_prof_session(&prof_session); - // handler loop - while (1) { - int i, k; - ssize_t recvLen; - // number of occured events - int numevent = epoll_wait(manager.efd, events, EPOLL_SIZE, -1); - if (numevent <= 0) { - LOGE("Failed to epoll_wait : num of event(%d), errno(%d)\n", numevent, errno); - continue; - } - - for (i = 0; i < numevent; i++) { - // check for request from event fd - for (k = 0; k < MAX_TARGET_COUNT; k++) { - if (manager.target[k].socket != -1 && - events[i].data.fd == manager.target[k].event_fd) { - uint64_t u; - recvLen = read(manager.target[k].event_fd, &u, sizeof(uint64_t)); - if (recvLen != sizeof(uint64_t)) { - // maybe closed, but ignoring is more safe then - // removing fd from epoll list - } else { - if (-11 == target_event_handler(manager.efd, k, u)) - LOGI("all target process is closed\n"); - } - break; - } - } - - if (k != MAX_TARGET_COUNT) - continue; - - // check for request from device fd - for (k = 0; g_touch_dev[k].fd != ARRAY_END; k++) { - if (g_touch_dev[k].fd >= 0 && - events[i].data.fd == g_touch_dev[k].fd) { - if (deviceEventHandler(&g_touch_dev[k], - INPUT_ID_TOUCH) < 0) { - LOGE("Internal DA framework error, " - "Please re-run the profiling (touch dev)\n"); - continue; - } - break; - } - } - - if (g_touch_dev[k].fd != ARRAY_END) - continue; - - for (k = 0; g_key_dev[k].fd != ARRAY_END; k++) { - if (g_key_dev[k].fd >= 0 && - events[i].data.fd == g_key_dev[k].fd) { - if (deviceEventHandler(&g_key_dev[k], INPUT_ID_KEY) < 0) { - LOGE("Internal DA framework error, " - "Please re-run the profiling (key dev)\n"); - continue; - } - break; - } - } - - if (g_key_dev[k].fd != ARRAY_END) - continue; - - // connect request from target - if (events[i].data.fd == manager.target_server_socket) { - if (targetServerHandler(manager.efd) < 0) { - // critical error - terminate_error("Internal DA framework error, " - "Please re-run the profiling " - "(targetServerHandler)\n", 1); - continue; - } - } else if (events[i].data.fd == manager.host_server_socket) { - // connect request from host - int result = hostServerHandler(manager.efd); - if (result < 0) { - LOGE("Internal DA framework error (hostServerHandler)\n"); - continue; - } - } else if (events[i].data.fd == manager.host.control_socket) { - // control message from host - int result = controlSocketHandler(manager.efd); - if (result == -11) { - // socket close - //if the host disconnected. - //In all other cases daemon must report an error and continue the loop - //close connect_timeoutt and host socket and quit - LOGI("Connection closed. Termination. (%d)\n", - manager.host.control_socket); - return_value = 0; - goto END_EFD; - } else if (result < 0) { - LOGE("Control socket handler.\n"); - } - } else if (events[i].data.fd == manager.host.data_socket) { - char recvBuf[32]; - recvLen = recv(manager.host.data_socket, recvBuf, 32, MSG_DONTWAIT); - if (recvLen == 0) { - // close data socket - if (0 > epoll_ctl(manager.efd, - EPOLL_CTL_DEL, - manager.host.data_socket, - NULL)) - LOGW("fail to EPOLL DEL of host data socket\n"); - close(manager.host.data_socket); - manager.host.data_socket = -1; - // TODO: finish transfer thread - } - - LOGI("host message from data socket %d\n", - recvLen); - } else if (events[i].data.fd == manager.app_launch_timerfd) { - // check for application launch timerfd - // send to host timeout error message for launching application - LOGE("Failed to launch application\n"); - if (stop_app_launch_timer() < 0) - LOGE("cannot stop app launch timer\n"); - continue; - } else if (events[i].data.fd == manager.connect_timeout_timerfd) { - // check for connection timeout timerfd - // send to host timeout error message for launching application - terminate_error("no incoming connections", 1); - if (0 > epoll_ctl(manager.efd, EPOLL_CTL_DEL, - manager.connect_timeout_timerfd, - NULL)) - LOGW("fail to EPOLL DEL of timeout timer fd\n"); - close(manager.connect_timeout_timerfd); - manager.connect_timeout_timerfd = -1; - LOGE("No connection in %d sec. shutdown.\n", - MAX_CONNECT_TIMEOUT_TIME); - goto END_EFD; - } else { - // unknown socket - // never happened - LOGW("Unknown socket fd (%d)\n", - events[i].data.fd); - } - } - } + ecore_main_loop_begin(); + ecore_shutdown(); END_EFD: LOGI("close efd\n"); close(manager.efd); END_EVENT: - free(events); return return_value; } diff --git a/daemon/daemon.h b/daemon/daemon.h index a1cae0a..cbefc1b 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -54,16 +54,6 @@ extern "C" { #define MAX_DEVICE 10 #define MAX_FILENAME 128 -#define INPUT_ID_TOUCH 0 -#define INPUT_ID_KEY 1 -#define STR_TOUCH "TOUCH" -#define STR_KEY "KEY" -#define INPUT_ID_STR_KEY "ID_INPUT_KEY=1" -#define INPUT_ID_STR_TOUCH "ID_INPUT_TOUCHSCREEN=1" -#define INPUT_ID_STR_KEYBOARD "ID_INPUT_KEYBOARD=1" -#define INPUT_ID_STR_TABLET "ID_INPUT_TABLET=1" - - /* enum ErrorCode { @@ -199,16 +189,6 @@ typedef struct char appPath[128]; // application executable path } __da_manager; - -typedef struct _input_dev -{ - int fd; - char fileName[MAX_FILENAME]; -} input_dev; - -extern input_dev g_key_dev[MAX_DEVICE]; -extern input_dev g_touch_dev[MAX_DEVICE]; - extern __da_manager manager; void initialize_log(); @@ -230,8 +210,6 @@ void stop_profiling(); int reconfigure(); int sendACKCodeToHost(enum HostMessageType resp, int msgcode); void terminate_all(); -void _device_write(input_dev *dev, struct input_event* in_ev); - #ifdef __cplusplus } diff --git a/daemon/input_events.c b/daemon/input_events.c new file mode 100644 index 0000000..df2a108 --- /dev/null +++ b/daemon/input_events.c @@ -0,0 +1,322 @@ +/* + * DA manager + * + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * + * Jaewon Lim + * Woojin Jung + * Juyoung Kim + * Cherepanov Vitaliy + * Nikita Kalyazin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * 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. + * + * Contributors: + * - S-Core Co., Ltd + * - Samsung RnD Institute Russia + * + */ + + +#include +#include + +#include "debug.h" +#include "da_data.h" +#include "input_events.h" + +#define MAX_DEVICE 10 +#define ARRAY_END (-11) +#define BUF_SIZE 1024 +#define MAX_FILENAME 128 + +#define INPUT_ID_TOUCH 0 +#define INPUT_ID_KEY 1 +#define STR_TOUCH "TOUCH" +#define STR_KEY "KEY" +#define INPUT_ID_STR_KEY "ID_INPUT_KEY=1" +#define INPUT_ID_STR_TOUCH "ID_INPUT_TOUCHSCREEN=1" +#define INPUT_ID_STR_KEYBOARD "ID_INPUT_KEYBOARD=1" +#define INPUT_ID_STR_TABLET "ID_INPUT_TABLET=1" + +typedef struct _input_dev +{ + int fd; + char fileName[MAX_FILENAME]; +} input_dev; + +static input_dev g_key_dev[MAX_DEVICE]; +static input_dev g_touch_dev[MAX_DEVICE]; + +static Ecore_Fd_Handler *key_handlers[MAX_DEVICE]; +static Ecore_Fd_Handler *touch_handlers[MAX_DEVICE]; + +enum status_t { s_stopped, s_running }; +static enum status_t status = s_stopped; + +static const char *input_key_devices[] = { + /* target: Emulator, kernel: 3.4, all buttons */ + "Maru Virtio Hwkey", + /* target: M0, kernel: 3.0, buttons: volume +/-, home, power */ + "gpio-keys", + /* target: M0, kernel: 3.0, buttons: menu, back */ + "melfas-touchkey", + /* target: M0, kernel: 3.10, buttons: menu, back */ + "MELFAS MCS Touchkey", + /* target: M0, kernel: 3.10, buttons: volume +/-, home, power */ + "gpio-keys.5", + NULL +}; + +static const char *input_touch_devices[] = { + /* target: Emulator, kernel: 3.0 */ + "Maru Virtio Touchscreen", + /* target: M0, kernel: 3.0 */ + "sec_touchscreen", + /* target: M0, kernel: 3.10 */ + "MELPAS MMS114 Touchscreen", + NULL +}; + +static int check_input(char *inputname, int input_id) +{ + int ret = -1; + FILE *cmd_fp = NULL; + char buffer[BUF_SIZE]; + char command[MAX_FILENAME]; + char **name_arr; + size_t bytes_count; + + sprintf(command, "/sys/class/input/%s/device/name", inputname); + // run command + cmd_fp = fopen(command, "r"); + if (cmd_fp == NULL) + goto exit; + + buffer[0] = '\0'; + bytes_count = fread(buffer, 1, BUF_SIZE, cmd_fp); + if (bytes_count <= 1) { + LOGE("Failed to read input_id\n"); + goto exit; + } else { + buffer[bytes_count - 1] = '\0'; + } + + if (input_id == INPUT_ID_KEY) + name_arr = input_key_devices; + else if (input_id == INPUT_ID_TOUCH) + name_arr = input_touch_devices; + else + goto exit; + + while (*name_arr != NULL) { + if (strcmp(buffer, *name_arr) == 0) { + ret = 0; + goto exit; + } + name_arr++; + } + +exit: + if (cmd_fp != NULL) + pclose(cmd_fp); + return ret; +} + +// get filename and fd of given input type devices +static void _get_fds(input_dev *dev, int input_id) +{ + DIR *dp; + struct dirent *d; + int count = 0; + + dp = opendir("/sys/class/input"); + + if (dp == NULL) + goto exit; + + while ((d = readdir(dp)) != NULL) { + if (!strncmp(d->d_name, "event", 5)) { + // start with "event" + // event file + if (!check_input(d->d_name, input_id)) { + sprintf(dev[count].fileName, + "/dev/input/%s", d->d_name); + dev[count].fd = open(dev[count].fileName, + O_RDWR | O_NONBLOCK); + count++; + } + } + } + + closedir(dp); + +exit: + dev[count].fd = ARRAY_END; // end of input_dev array +} + +#define MAX_EVENTS_NUM 10 +static int deviceEventHandler(input_dev *dev, int input_type) +{ + int ret = 0; + ssize_t size = 0; + int count = 0; + struct input_event in_ev[MAX_EVENTS_NUM]; + struct msg_data_t *log; + + if (input_type == INPUT_ID_TOUCH || input_type == INPUT_ID_KEY) { + do { + size = read(dev->fd, &in_ev[count], sizeof(*in_ev)); + if (size > 0) + count++; + } while (count < MAX_EVENTS_NUM && size > 0); + + if (count) { + LOGI("read %d %s events\n", + count, + input_type == INPUT_ID_KEY ? STR_KEY : STR_TOUCH); + log = gen_message_event(in_ev, count, input_type); + printBuf((char *)log, MSG_DATA_HDR_LEN + log->len); + write_to_buf(log); + free_msg_data(log); + } + } else { + LOGW("unknown input_type\n"); + ret = 1; // it is not error + } + return ret; +} + +static Eina_Bool touch_event_cb(void *data, Ecore_Fd_Handler *fd_handler) +{ + input_dev *touch_dev = (input_dev *)data; + + if (deviceEventHandler(touch_dev, INPUT_ID_TOUCH) < 0) { + LOGE("Internal DA framework error, " + "Please re-run the profiling (touch dev)\n"); + /* TODO: ??? */ + } + + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool key_event_cb(void *data, Ecore_Fd_Handler *fd_handler) +{ + input_dev *key_dev = (input_dev *)data; + + if (deviceEventHandler(key_dev, INPUT_ID_KEY) < 0) { + LOGE("Internal DA framework error, " + "Please re-run the profiling (key dev)\n"); + /* TODO: ??? */ + } + + return ECORE_CALLBACK_RENEW; +} + +void add_input_events(void) +{ + int i; + + if (status == s_running) + return; + + for (i = 0; g_key_dev[i].fd != ARRAY_END; i++) { + if (g_key_dev[i].fd > 0) { + key_handlers[i] = + ecore_main_fd_handler_add(g_key_dev[i].fd, + ECORE_FD_READ, + key_event_cb, + &g_key_dev[i], + NULL, NULL); + if (!key_handlers[i]) + LOGE("keyboard device file handler add error\n"); + } + } + + for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++) { + if (g_touch_dev[i].fd > 0) { + touch_handlers[i] = + ecore_main_fd_handler_add(g_touch_dev[i].fd, + ECORE_FD_READ, + touch_event_cb, + &g_touch_dev[i], + NULL, NULL); + if (!touch_handlers[i]) + LOGE("touch device file handler add error\n"); + } + } + + status = s_running; +} + +void del_input_events(void) +{ + int i; + + if (status == s_stopped) + return; + + for (i = 0; g_key_dev[i].fd != ARRAY_END; i++) + if (g_key_dev[i].fd > 0) + ecore_main_fd_handler_del(key_handlers[i]); + + for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++) + if (g_touch_dev[i].fd > 0) + ecore_main_fd_handler_del(touch_handlers[i]); + + status = s_stopped; +} + +static void _device_write(input_dev dev[], struct input_event *in_ev) +{ + int i; + for (i = 0; dev[i].fd != ARRAY_END; i++) { + if (dev[i].fd >= 0) { + write(dev[i].fd, in_ev, sizeof(struct input_event)); + LOGI("write(%d, %d, %d)\n", + dev[i].fd, (int)in_ev, sizeof(struct input_event)); + } + } +} + +void write_input_event(int id, struct input_event *ev) +{ + switch (id) { + case INPUT_ID_TOUCH: + _device_write(g_touch_dev, ev); + break; + case INPUT_ID_KEY: + _device_write(g_key_dev, ev); + break; + default: + LOGE("unknown input id (%d)\n", id); + } +} + +int init_input_events(void) +{ + _get_fds(g_key_dev, INPUT_ID_KEY); + if (g_key_dev[0].fd == ARRAY_END) { + LOGE("No key devices found.\n"); + return -1; + } + _get_fds(g_touch_dev, INPUT_ID_TOUCH); + if (g_touch_dev[0].fd == ARRAY_END) { + LOGE("No touch devices found.\n"); + return -1; + } + + return 0; +} diff --git a/daemon/input_events.h b/daemon/input_events.h new file mode 100644 index 0000000..8064cd5 --- /dev/null +++ b/daemon/input_events.h @@ -0,0 +1,35 @@ +/* + * DA manager + * + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * + * Jaewon Lim + * Woojin Jung + * Juyoung Kim + * Nikita Kalyazin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * 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. + * + * Contributors: + * - S-Core Co., Ltd + * - Samsung RnD Institute Russia + * + */ + + +int init_input_events(void); +void add_input_events(void); +void del_input_events(void); +void write_input_event(int id, struct input_event *ev); diff --git a/daemon/threads.c b/daemon/threads.c index e3be0f8..9d5c5d4 100644 --- a/daemon/threads.c +++ b/daemon/threads.c @@ -48,6 +48,7 @@ #include "da_data.h" #include "debug.h" #include "buffer.h" +#include "input_events.h" static void* recvThread(void* data) { @@ -379,22 +380,7 @@ static void *replay_thread(void *arg) LOGI_th_rep("%d) sleep %d\n", i, ms); usleep(ms); - /* filter touch and key events here - and process them separately */ - switch (pevent->id) - { - case INPUT_ID_TOUCH: - LOGI_th_rep("event -> %s\n", INPUT_ID_STR_TOUCH); - _device_write(g_touch_dev, &pevent->ev); - break; - - case INPUT_ID_KEY: - LOGI_th_rep("event -> %s\n", INPUT_ID_STR_KEY); - _device_write(g_key_dev, &pevent->ev); - break; - default: - LOGE("event -> UNKNOWN INPUT ID"); - } + write_input_event(pevent->id, &pevent->ev); prev_event_offset = event_offset; diff --git a/packaging/swap-manager.spec b/packaging/swap-manager.spec index 54f66f9..cf57710 100644 --- a/packaging/swap-manager.spec +++ b/packaging/swap-manager.spec @@ -14,6 +14,7 @@ BuildRequires: capi-system-info-devel BuildRequires: capi-system-runtime-info-devel BuildRequires: capi-telephony-network-info-devel BuildRequires: capi-telephony-call-devel +BuildRequires: pkgconfig(ecore) Requires: sdbd %description