#include <sys/socket.h> // for accept
#include <sys/stat.h> // for mkdir
#include <sys/eventfd.h> // for eventfd
-#include <sys/epoll.h> // for epoll apis
#include <sys/timerfd.h> // for timerfd
#include <unistd.h> // for access, sleep
#include <stdbool.h>
+#include <linux/netlink.h>
+#include <linux/connector.h>
#include <ctype.h>
-#ifndef LOCALTEST
-#include <attr/xattr.h> // for fsetxattr
-#include <sys/smack.h>
-#endif
-
-#include <linux/input.h>
-#include <dirent.h>
#include <fcntl.h>
+
+#include <assert.h>
+
+#include <Ecore.h>
+
#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 "smack.h"
+#include "us_interaction_msg.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];
-
-// return bytes size of readed data
-// return 0 if no data readed or error occurred
-static int _file_read(FILE *fp, char *buffer, int size)
-{
- int ret = 0;
-
- if (fp != NULL && size > 0) {
- ret = fread((void *)buffer, sizeof(char), size, fp);
- buffer[ret] = '\0';
- } else {
- // fp is null
- if (size > 0)
- buffer[0] = '\0';
- ret = 0; // error case
- }
-
- return ret;
-}
-
-// get input id of given input device
-static int get_input_id(char *inputname)
-{
- static int query_cmd_type = 0; // 1 if /lib/udev/input_id, 2 if udevadm
- FILE *cmd_fp = NULL;
- char buffer[BUF_SIZE];
- char command[MAX_FILENAME];
- int ret = -1;
-
- // determine input_id query command
- if (unlikely(query_cmd_type == 0)) {
- if (access("/lib/udev/input_id", F_OK) == 0) {
- // there is /lib/udev/input_id
- query_cmd_type = 1;
- } else {
- // there is not /lib/udev/input_id
- query_cmd_type = 2;
- }
- }
- // make command string
- if (query_cmd_type == 1) {
- sprintf(command, "/lib/udev/input_id /class/input/%s",
- inputname);
- } else {
- sprintf(command,
- "udevadm info --name=input/%s --query=property",
- inputname);
- }
-
- // run command
- cmd_fp = popen(command, "r");
- if (_file_read(cmd_fp, buffer, BUF_SIZE) < 0) {
- LOGE("Failed to read input_id\n");
- if (cmd_fp != NULL)
- pclose(cmd_fp);
- return ret;
- }
- // determine input id
- if (strstr(buffer, INPUT_ID_STR_KEY)) {
- // key
- ret = INPUT_ID_KEY;
- } else if (strstr(buffer, INPUT_ID_STR_TOUCH)) {
- // touch
- ret = INPUT_ID_TOUCH;
- } else if (strstr(buffer, INPUT_ID_STR_KEYBOARD)) {
- // keyboard
- ret = INPUT_ID_KEY;
- } else if (strstr(buffer, INPUT_ID_STR_TABLET)) {
- // touch (emulator)
- ret = INPUT_ID_TOUCH;
- }
-
- 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) {
- while ((d = readdir(dp)) != NULL) {
- if (!strncmp(d->d_name, "event", 5)) {
- // start with "event"
- // event file
- if (input_id == get_input_id(d->d_name)) {
- sprintf(dev[count].fileName,
- "/dev/input/%s", d->d_name);
- dev[count].fd =
- open(dev[count].fileName,
- O_RDWR | O_NONBLOCK);
- count++;
- }
- }
- }
-
- closedir(dp);
- }
- 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()
+uint64_t get_total_alloc_size(void)
{
int i;
uint64_t allocsize = 0;
// 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()
+static int start_app_launch_timer(int apps_count)
{
int res = 0;
- struct epoll_event ev;
+
+ assert(apps_count >= 0 && "negative apps count");
+
+ if (apps_count == 0)
+ return res;
manager.app_launch_timerfd =
timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
if (manager.app_launch_timerfd > 0) {
struct itimerspec ctime;
- ctime.it_value.tv_sec = MAX_APP_LAUNCH_TIME;
+ ctime.it_value.tv_sec = MAX_APP_LAUNCH_TIME * apps_count;
ctime.it_value.tv_nsec = 0;
ctime.it_interval.tv_sec = 0;
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");
return res;
}
-//stop application launch timer
-static int stop_app_launch_timer()
+static inline void inc_apps_to_run()
{
- 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;
+ manager.apps_to_run++;
+}
+
+static inline void dec_apps_to_run()
+{
+ if (manager.apps_to_run > 0)
+ manager.apps_to_run--;
}
-int kill_app_by_info(const struct app_info_t *app_info)
+static inline int get_apps_to_run()
+{
+ return manager.apps_to_run;
+}
+
+static int kill_app_by_info(const struct app_info_t *app_info)
{
int res = 0;
if (exec_app_tizen(app_info->app_id, app_info->exe_path)) {
LOGE("Cannot exec tizen app %s\n", app_info->app_id);
res = -1;
+ } else {
+ inc_apps_to_run();
}
break;
case APP_TYPE_RUNNING:
if (exec_app_common(app_info->exe_path)) {
LOGE("Cannot exec common app %s\n", app_info->exe_path);
res = -1;
+ } else {
+ inc_apps_to_run();
}
break;
default:
break;
}
- if (res == 0 && app_info->app_type != APP_TYPE_RUNNING)
- if (start_app_launch_timer() < 0)
- res = -1;
-
LOGI("ret=%d\n", res);
return res;
}
-int launch_timer_start()
+// 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;
+}
+
+static int launch_timer_start(void)
{
- static struct epoll_event ev;
int res = 0;
manager.connect_timeout_timerfd =
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 {
return res;
}
-static void epoll_add_input_events();
-static void epoll_del_input_events();
-
-int prepare_profiling()
+int prepare_profiling(void)
{
struct app_list_t *app = NULL;
const struct app_info_t *app_info = NULL;
}
-int start_profiling()
+int start_profiling(void)
{
struct app_list_t *app = NULL;
const struct app_info_t *app_info = NULL;
LOGW("Failed to create directory for screenshot : %s\n",
strerror(errno));
-#ifndef LOCALTEST
- smack_lsetlabel(SCREENSHOT_DIR, "*", SMACK_LABEL_ACCESS);
-#endif
+ set_label_for_all(SCREENSHOT_DIR);
if (samplingStart() < 0) {
LOGE("Cannot start sampling\n");
}
if (IS_OPT_SET(FL_RECORDING))
- epoll_add_input_events();
+ add_input_events();
- if (exec_app(app_info)) {
- LOGE("Cannot exec app\n");
+ while (app_info != NULL) {
+ if (exec_app(app_info)) {
+ LOGE("Cannot exec app\n");
+ res = -1;
+ goto recording_stop;
+ }
+ app_info = app_info_get_next(&app);
+ }
+
+ if (start_app_launch_timer(get_apps_to_run()) < 0) {
res = -1;
goto recording_stop;
}
recording_stop:
if (IS_OPT_SET(FL_RECORDING))
- epoll_del_input_events();
+ del_input_events();
samplingStop();
exit:
void stop_profiling(void)
{
if (IS_OPT_SET(FL_RECORDING))
- epoll_del_input_events();
+ del_input_events();
samplingStop();
}
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;
}
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) {
- // send to only first main target proces
- LOGI("TERMINATE send exit msg (socket %d) "
- "by terminate_all_target()\n",
- manager.target[i].socket);
- break;
- }
- }
- }
-}
-
-// 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)
{
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,
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
// 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)
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) {
if (manager.target[index].socket >= 0) {
/* accept succeed */
- fd_setup_smack_attributes(manager.target[index].socket);
+ fd_setup_attributes(manager.target[index].socket);
/* send config message to target process */
log.type = MSG_OPTION;
- log.length = sprintf(log.data, "%lu",
- (unsigned long int)prof_session.conf.use_features0);
+ log.length = sprintf(log.data, "%llu",
+ prof_session.conf.use_features0);
if (0 > send(manager.target[index].socket, &log,
sizeof(log.type) + sizeof(log.length) + log.length,
MSG_NOSIGNAL))
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",
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;
}
// 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;
}
- if (manager.app_launch_timerfd >= 0) {
- LOGI("release launch timer\n");
+ dec_apps_to_run();
+
+ if ((manager.app_launch_timerfd > 0) && (get_apps_to_run() == 0)) {
if (stop_app_launch_timer() < 0)
LOGE("cannot stop app launch timer\n");
}
}
}
-// 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;
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;
}
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");
+ }
+
+ return ECORE_CALLBACK_RENEW;
+}
- // 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));
- }
+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 int kernel_handler(void)
{
- int i;
+ int res, size, ret;
+ socklen_t optlen;
+ struct nlmsghdr *nlh;
+ struct cn_msg *msg;
+ ssize_t len;
+
+ /* Get buffer size */
+ optlen = sizeof(size);
+
+ /* We're using SOCK_DGRAM, so, get it maximum size */
+ res = getsockopt(manager.kernel_socket, SOL_SOCKET, SO_SNDBUF, &size,
+ &optlen);
+
+ if (res == -1) {
+ LOGE("Get maximum buffer size failed\n");
+ return -1;
+ }
+
+ /* Alloc mem for nlh message struct and receive it */
+ nlh = malloc(size);
+ if (nlh == NULL)
+ return -1;
+ len = recv(manager.kernel_socket, nlh, size, 0);
+ if ((len <= 0) || (nlh->nlmsg_len == 0)) {
+ ret = -1;
+ goto free_and_end;
+ }
+
+ /* nlh data field contains connectors message */
+ msg = NLMSG_DATA(nlh);
+ if (msg->len == 0) {
+ ret = -1;
+ goto free_and_end;
+ }
+
+ /* Insert your message handler here */
+
+ ret = 0;
- // 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));
+free_and_end:
+ free(nlh);
+
+ return ret;
}
-static bool initialize_epoll_events(void)
+
+static Ecore_Fd_Handler *host_connect_handler;
+static Ecore_Fd_Handler *target_connect_handler;
+static Ecore_Fd_Handler *kernel_connect_handler;
+
+static Eina_Bool host_connect_cb(void *data, Ecore_Fd_Handler *fd_handler)
{
- struct epoll_event ev;
+ // connect request from host
+ int result = hostServerHandler();
+ if (result < 0) {
+ LOGE("Internal DA framework error (hostServerHandler)\n");
+ }
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool target_connect_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+ if (targetServerHandler() < 0) {
+ // critical error
+ terminate_error("Internal DA framework error, "
+ "Please re-run the profiling "
+ "(targetServerHandler)\n", 1);
+ }
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool kernel_connect_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+ if (kernel_handler() < 0) {
+ LOGE("Internal DA framework error (kernel_handler)\n");
+ }
- if ((manager.efd = epoll_create1(0)) < 0) {
- LOGE("epoll creation 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;
}
- // 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");
+
+ 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;
}
- 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");
+
+ kernel_connect_handler =
+ ecore_main_fd_handler_add(manager.kernel_socket,
+ ECORE_FD_READ,
+ kernel_connect_cb,
+ NULL,
+ NULL, NULL);
+ if (!kernel_connect_handler) {
+ LOGE("Kernel socket add error\n");
return false;
}
+
return true;
}
// return 0 for normal case
-int daemonLoop()
+int daemonLoop(void)
{
int return_value = 0;
- struct epoll_event *events = malloc(EPOLL_SIZE * sizeof(*events));
- _get_fds(g_key_dev, INPUT_ID_KEY);
- _get_fds(g_touch_dev, INPUT_ID_TOUCH);
+ 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;
}
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");
- continue;
- }
- }
- 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;
}