/*
-* DA manager
-*
-* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
-*
-* Contact:
-*
-* Jaewon Lim <jaewon81.lim@samsung.com>
-* Woojin Jung <woojin2.jung@samsung.com>
-* Juyoung Kim <j0.kim@samsung.com>
-*
+ * DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim <jaewon81.lim@samsung.com>
+ * Woojin Jung <woojin2.jung@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin <n.kalyazin@samsung.com>
+ *
* 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
-*
-*/
-
+ * 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
+ *
+ */
+#define __STDC_FORMAT_MACROS
#include <stdio.h>
-#include <stdlib.h> // for realpath
-#include <string.h> // for strtok, strcpy, strncpy
-#include <limits.h> // for realpath
+#include <stdlib.h> // for realpath
+#include <string.h> // for strtok, strcpy, strncpy
+#include <limits.h> // for realpath
+#include <inttypes.h>
-#include <errno.h> // for errno
+#include <errno.h> // for errno
#include <sys/types.h> // for accept, mkdir, opendir, readdir
#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 <unistd.h> // for access, sleep
+#include <stdbool.h>
+#include <linux/netlink.h>
+#include <linux/connector.h>
-#ifndef LOCALTEST
-#include <attr/xattr.h> // for fsetxattr
-#include <sys/smack.h>
-#endif
+#include <ctype.h>
-#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"
-#define DA_WORK_DIR "/home/developer/sdk_tools/da/"
+#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_CONNECT_SIZE 12
-#define MAX_APP_LAUNCH_TIME 6
-
-#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"
-
-#define MAX_DEVICE 10
-#define MAX_FILENAME 128
-#define BUF_SIZE 1024
-#define ARRAY_END (-11)
-
-typedef struct _input_dev
-{
- int fd;
- char fileName[MAX_FILENAME];
-} input_dev;
-
-input_dev g_key_dev[MAX_DEVICE];
-input_dev g_touch_dev[MAX_DEVICE];
+#define MAX_APP_LAUNCH_TIME 60
+#define MAX_CONNECT_TIMEOUT_TIME 5*60
-// 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);
- }
- 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");
- _file_read(cmd_fp, buffer, BUF_SIZE);
-
- // 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)
+uint64_t get_total_alloc_size(void)
{
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));
- }
-}
+ uint64_t allocsize = 0;
-long long get_total_alloc_size()
-{
- int i;
- long long allocsize = 0;
-
- for(i = 0; i < MAX_TARGET_COUNT; i++)
- {
- if(manager.target[i].socket != -1 && manager.target[i].allocmem > 0)
+ for (i = 0; i < MAX_TARGET_COUNT; i++) {
+ if (manager.target[i].socket != -1 &&
+ manager.target[i].allocmem > 0)
allocsize += manager.target[i].allocmem;
}
return allocsize;
static int getEmptyTargetSlot()
{
int i;
- for(i = 0; i < MAX_TARGET_COUNT; i++)
- {
- if(manager.target[i].socket == -1)
+ for (i = 0; i < MAX_TARGET_COUNT; i++) {
+ if (manager.target[i].socket == -1)
break;
}
static void setEmptyTargetSlot(int index)
{
- if(index >= 0 && index < MAX_TARGET_COUNT)
- {
+ if (index >= 0 && index < MAX_TARGET_COUNT) {
manager.target[index].pid = -1;
manager.target[index].recv_thread = -1;
manager.target[index].allocmem = 0;
- manager.target[index].starttime = 0;
manager.target[index].initial_log = 0;
- if(manager.target[index].event_fd != -1)
+ if (manager.target[index].event_fd != -1)
close(manager.target[index].event_fd);
manager.target[index].event_fd = -1;
- if(manager.target[index].socket != -1)
+ if (manager.target[index].socket != -1)
close(manager.target[index].socket);
manager.target[index].socket = -1;
}
}
-// ======================================================================================
-// send functions to host
-// ======================================================================================
-
-int pseudoSendDataToHost(struct msg_data_t* log)
-{
- /* uint32_t total_len = MSG_DATA_HDR_LEN; */
-
- /* char *buf = malloc(total_len+log->len); */
- /* char *p = buf; */
- /* memset(p,0,total_len); */
+// =============================================================================
+// start and terminate control functions
+// =============================================================================
- /* pack_int(p,log->id); */
- /* pack_int(p,log->seq_num); */
- /* pack_time(p,log->time); */
- /* pack_int(p,log->len); */
+static Ecore_Fd_Handler *launch_timer_handler;
- /* memcpy(p,log->payload,log->len); */
- /* printBuf(buf,total_len+log->len); */
- /* if (event_fd >0){ */
- /* write(event_fd, buf, total_len+log->len); */
- /* } */
- /* free(buf); */
+//stop application launch timer
+static int stop_app_launch_timer()
+{
+ close(manager.app_launch_timerfd);
+ manager.app_launch_timerfd = -1;
return 0;
}
-int sendDataToHost(msg_t* log)
+static Eina_Bool launch_timer_cb(void *data, Ecore_Fd_Handler *fd_handler)
{
- if (manager.host.data_socket != -1)
- {
- char logstr[DA_MSG_MAX];
- int loglen;
-
- if(log->length != 0)
- loglen = sprintf(logstr, "%d|%d|%s\n", log->type, log->length + 1, log->data);
- else
- loglen = sprintf(logstr, "%d|%d|\n", log->type, log->length + 1);
-
-// loglen = sprintf(logstr, "%d|%s\n", log->type, log->data);
+ LOGE("Failed to launch application\n");
+ if (stop_app_launch_timer() < 0)
+ LOGE("cannot stop app launch timer\n");
- pthread_mutex_lock(&(manager.host.data_socket_mutex));
- send(manager.host.data_socket, logstr, loglen, MSG_NOSIGNAL);
- pthread_mutex_unlock(&(manager.host.data_socket_mutex));
- return 0;
- }
- else
- return 1;
+ return ECORE_CALLBACK_CANCEL;
}
-// msgstr can be NULL
-static int sendACKStrToHost(enum HostMessageType resp, char* msgstr)
+//start application launch timer function
+static int start_app_launch_timer(int apps_count)
{
- if (manager.host.control_socket != -1)
- {
- char logstr[DA_MSG_MAX];
- int loglen;
-
- if(msgstr != NULL)
- loglen = sprintf(logstr, "%d|%d|%s", (int)resp, strlen(msgstr), msgstr);
- else
- loglen = sprintf(logstr, "%d|0|", (int)resp);
-
- send(manager.host.control_socket, logstr, loglen, MSG_NOSIGNAL);
- return 0;
+ int res = 0;
+
+ 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 * 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");
+ stop_app_launch_timer();
+ res = -1;
+ } else {
+ 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");
+ }
+ }
+ } else {
+ LOGE("cannot create launch timer\n");
+ res = -3;
}
- else
- return 1;
-}
-
+ return res;
+}
-static int sendACKCodeToHost(enum HostMessageType resp, int msgcode)
+static inline void inc_apps_to_run()
{
- // FIXME:
- //disabled string protocol
- return 0;
- if (manager.host.control_socket != -1)
- {
- char codestr[16];
- char logstr[DA_MSG_MAX];
- int loglen, codelen;
-
- codelen = sprintf(codestr, "%d", msgcode);
- loglen = sprintf(logstr, "%d|%d|%s", (int)resp, codelen, codestr);
-
- send(manager.host.control_socket, logstr, loglen, MSG_NOSIGNAL);
- return 0;
- }
- else
- return 1;
+ manager.apps_to_run++;
}
-// ========================================================================================
-// start and terminate control functions
-// ========================================================================================
+static inline void dec_apps_to_run()
+{
+ if (manager.apps_to_run > 0)
+ manager.apps_to_run--;
+}
-static int startProfiling(long launchflag)
+static inline int get_apps_to_run()
{
- char execPath[PATH_MAX];
+ return manager.apps_to_run;
+}
- // remove previous screen capture files
- remove_indir(SCREENSHOT_DIR);
- mkdir(SCREENSHOT_DIR, 0777);
-#ifndef LOCALTEST
- smack_lsetlabel(SCREENSHOT_DIR, "*", SMACK_LABEL_ACCESS);
-#endif
- manager.config_flag = launchflag;
-
-#ifdef RUN_APP_LOADER
- strcpy(execPath, manager.appPath);
-#else
- get_executable(manager.appPath, execPath, PATH_MAX);
-#endif
- if(samplingStart() < 0)
- return -1;
+static int kill_app_by_info(const struct app_info_t *app_info)
+{
+ int res = 0;
- if(exec_app(execPath, get_app_type(manager.appPath)) == 0)
- {
- samplingStop();
+ if (app_info == NULL) {
+ LOGE("Cannot exec app. app_info is NULL");
return -1;
}
- LOGI("Timer Started\n");
-
- return 0;
+ switch (app_info->app_type) {
+ case APP_TYPE_TIZEN:
+ res = kill_app(app_info->exe_path);
+ break;
+ case APP_TYPE_RUNNING:
+ // TODO: nothing, it's running
+ LOGI("already started\n");
+ break;
+ case APP_TYPE_COMMON:
+ res = kill_app(app_info->exe_path);
+ break;
+ default:
+ LOGE("Unknown app type %d\n", app_info->app_type);
+ res = -1;
+ break;
+ }
+
+ return res;
}
-// terminate single target
-// just send stop message to target process
-static void terminate_target(int index)
+static int exec_app(const struct app_info_t *app_info)
{
- ssize_t sendlen;
- msg_t sendlog;
- sendlog.type = MSG_STOP;
- sendlog.length = 0;
+ int res = 0;
- if(manager.target[index].socket != -1)
- {
- // result of sending to disconnected socket is not expected
- sendlen = send(manager.target[index].socket, &sendlog, sizeof(sendlog.type) + sizeof(sendlog.length), MSG_NOSIGNAL);
- if(sendlen != -1)
- {
- LOGI("TERMINATE send exit msg (socket %d) by terminate_target()\n", manager.target[index].socket);
+ if (app_info == NULL) {
+ LOGE("Cannot exec app. app_info is NULL");
+ return -1;
+ }
+
+ switch (app_info->app_type) {
+ case APP_TYPE_TIZEN:
+ 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:
+ // TODO: nothing, it's running
+ LOGI("already started\n");
+ break;
+ case APP_TYPE_COMMON:
+ 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:
+ LOGE("Unknown app type %d\n", app_info->app_type);
+ res = -1;
+ break;
}
+
+ LOGI("ret=%d\n", res);
+ return res;
}
// just send stop message to all target process
{
int i;
ssize_t sendlen;
- msg_t sendlog;
+ 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);
+ 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
-static void terminate_all()
+void terminate_all()
{
int i;
terminate_all_target();
- samplingStop();
// wait for all other thread exit
- for(i = 0; i < MAX_TARGET_COUNT; i++)
- {
- if(manager.target[i].recv_thread != -1)
- {
+ 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
-static void terminate_error(char* errstr, int sendtohost)
+// TODO: don't send data to host
+static void terminate_error(char *errstr, int send_to_host)
{
- msg_t log;
-
- LOGE("TERMINATE ERROR: %s\n", errstr);
- if(sendtohost)
- {
- log.type = MSG_ERROR;
- log.length = sprintf(log.data, "%s", errstr);
- sendDataToHost(&log);
+ 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();
}
-// ===========================================================================================
-// message parsing and handling functions
-// ===========================================================================================
+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 parseDeviceMessage(msg_t* log)
+static int launch_timer_start(void)
{
- char eventType[MAX_FILENAME];
- struct input_event in_ev;
- int i, index;
+ int res = 0;
+
+ manager.connect_timeout_timerfd =
+ timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
+ if (manager.connect_timeout_timerfd > 0) {
+ struct itimerspec ctime;
+ ctime.it_value.tv_sec = MAX_CONNECT_TIMEOUT_TIME;
+ ctime.it_value.tv_nsec = 0;
+ ctime.it_interval.tv_sec = 0;
+ ctime.it_interval.tv_nsec = 0;
+ if (timerfd_settime(manager.connect_timeout_timerfd, 0, &ctime, NULL) < 0) {
+ LOGE("fail to set connect timeout timer\n");
+ close(manager.connect_timeout_timerfd);
+ manager.connect_timeout_timerfd = -1;
+ } else {
+ 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 {
+ LOGI("connection timeout timer started\n");
+ }
+ }
+ } else {
+ LOGE("cannot create connection timeout timer\n");
+ }
- if(log == NULL)
- return -1;
+ LOGI("ret=%d\n", res);
+ return res;
+}
- eventType[0] = '\0';
- in_ev.type = 0;
- in_ev.code = 0;
- in_ev.value = 0;
+int prepare_profiling(void)
+{
+ struct app_list_t *app = NULL;
+ const struct app_info_t *app_info = NULL;
- index = 0;
- for(i = 0; i < log->length; i++)
- {
- if(log->data[i] == '\n')
- break;
+ app_info = app_info_get_first(&app);
+ if (app_info == NULL) {
+ LOGE("No app info found\n");
+ return -1;
+ }
- if(log->data[i] == '`') // meet separate
- {
- i++;
- index++;
- continue;
+ //all apps
+ while (app_info != NULL) {
+ if (kill_app_by_info(app_info) != 0) {
+ LOGE("kill app failed\n");
+ return -1;
}
+ app_info = app_info_get_next(&app);
+ }
+ //init rw for systeminfo
+ //init recv send network systeminfo
+ sys_stat_prepare();
+ return 0;
- if(index == 0) // parse eventType
- {
- eventType[i] = log->data[i];
- eventType[i+1] = '\0';
- }
- else if(index == 1) // parse in_ev.type
- {
- in_ev.type = in_ev.type * 10 + (log->data[i] - '0');
- }
- else if(index == 2) // parse in_ev.code
- {
- in_ev.code = in_ev.code * 10 + (log->data[i] - '0');
- }
- else if(index == 3) // parse in_ev.value
- {
- in_ev.value = in_ev.value * 10 + (log->data[i] - '0');
- }
+}
+
+int start_profiling(void)
+{
+ struct app_list_t *app = NULL;
+ const struct app_info_t *app_info = NULL;
+ int res = 0;
+
+ app_info = app_info_get_first(&app);
+ if (app_info == NULL) {
+ LOGE("No app info found\n");
+ return -1;
+ }
+ // remove previous screen capture files
+ remove_indir(SCREENSHOT_DIR);
+ if (mkdir(SCREENSHOT_DIR, 0777) == -1 && errno != EEXIST)
+ LOGW("Failed to create directory for screenshot : %s\n",
+ strerror(errno));
+
+ set_label_for_all(SCREENSHOT_DIR);
+
+ if (samplingStart() < 0) {
+ LOGE("Cannot start sampling\n");
+ res = -1;
+ goto exit;
}
- if(index != 3)
- return -1; // parse error
+ if (IS_OPT_SET(FL_RECORDING))
+ add_input_events();
- if(0 == strncmp(eventType, STR_TOUCH, strlen(STR_TOUCH)))
- {
- _device_write(g_touch_dev, &in_ev);
+ 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);
}
- else if(0 == strncmp(eventType, STR_KEY, strlen(STR_KEY)))
- {
- _device_write(g_key_dev, &in_ev);
+
+ if (start_app_launch_timer(get_apps_to_run()) < 0) {
+ res = -1;
+ goto recording_stop;
}
- return 0;
+ goto exit;
+
+ recording_stop:
+ if (IS_OPT_SET(FL_RECORDING))
+ del_input_events();
+ samplingStop();
+
+ exit:
+ LOGI("return %d\n", res);
+ return res;
}
-// return 0 if normal case
-// return plus value if non critical error occur
-// return minus value if critical error occur
-static int _hostMessageHandler(int efd,struct msg_t* log)
+void stop_profiling(void)
{
-/* int ret = 0; */
-
-/* long flag = 0; */
-/* char *barloc, *tmploc; */
-/* char execPath[PATH_MAX]; */
-
-/* if (log == NULL) */
-/* return 1; */
-
-/* switch (log->type) */
-/* { */
-/* case MSG_REPLAY: */
-/* sendACKStrToHost(MSG_OK, NULL); */
-/* parseDeviceMessage(log); */
-/* break; */
-/* case MSG_VERSION: */
-/* if(strcmp(PROTOCOL_VERSION, log->data) != 0) */
-/* { */
-/* sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_PROTOCOL_VERSION); */
-/* } */
-/* else */
-/* { */
-/* sendACKStrToHost(MSG_OK, NULL); */
-/* } */
-/* break; */
-/* case MSG_START: */
-/* LOGI("MSG_START handling : %s\n", log->data); */
-/* if(log->length == 0) */
-/* { */
-/* sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_MESSAGE_DATA); */
-/* return -1; // wrong message format */
-/* } */
-
-/* // parsing for host start status */
-/* tmploc = log->data; */
-/* barloc = strchr(tmploc, '|'); */
-/* if(barloc == NULL) */
-/* { */
-/* sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_MESSAGE_FORMAT); */
-/* return -1; // wrong message format */
-/* } */
-
-/* // parsing for target launch option flag */
-/* tmploc = barloc + 1; */
-/* barloc = strchr(tmploc, '|'); */
-/* if(barloc != NULL) */
-/* { */
-/* while(tmploc < barloc) */
-/* { */
-/* flag = (flag * 10) + (*tmploc - '0'); */
-/* tmploc++; */
-/* } */
-/* } */
-/* else */
-/* { */
-/* sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_MESSAGE_FORMAT); */
-/* return -1; // wrong message format */
-/* } */
-/* LOGI("launch flag : %lx\n", flag); */
-
-/* // parsing for application package name */
-/* tmploc = barloc + 1; */
-/* strcpy(manager.appPath, tmploc); */
-
-/* get_executable(manager.appPath, execPath, PATH_MAX); // get exact app executable file name */
-/* LOGI("executable app path %s\n", manager.appPath); */
-
-/* #ifdef RUN_APP_LOADER */
-/* kill_app(manager.appPath); */
-/* #else */
-/* kill_app(execPath); */
-/* #endif */
-
-/* { */
-/* char command[PATH_MAX]; */
-/* struct epoll_event ev; */
-
-/* //save app install path */
-/* mkdir(DA_WORK_DIR, 0775); */
-/* sprintf(command, */
-/* "%s -Wwi %s | grep DW_AT_comp_dir > %s", DA_READELF_PATH, */
-/* execPath, DA_INSTALL_PATH); */
-/* LOGI("appInstallCommand %s\n", command); */
-/* system(command); */
-
-/* sprintf(command, */
-/* "%s -h %s | grep Type | cut -d\" \" -f33 > %s", DA_READELF_PATH, */
-/* execPath, DA_BUILD_OPTION); */
-/* LOGI("appInstallCommand %s\n", command); */
-/* system(command); */
-
-/* if(startProfiling(flag) < 0) */
-/* { */
-/* sendACKCodeToHost(MSG_NOTOK, ERR_CANNOT_START_PROFILING); */
-/* return -1; */
-/* } */
-
-/* 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_nsec = 0; */
-/* ctime.it_interval.tv_sec = 0; */
-/* ctime.it_interval.tv_nsec = 0; */
-/* if(0 > timerfd_settime(manager.app_launch_timerfd, 0, &ctime, NULL)) */
-/* { */
-/* LOGE("fail to set app launch timer\n"); */
-/* close(manager.app_launch_timerfd); */
-/* manager.app_launch_timerfd = -1; */
-/* } */
-/* else */
-/* { */
-/* // add event fd to epoll list */
-/* ev.events = EPOLLIN; */
-/* ev.data.fd = manager.app_launch_timerfd; */
-/* if(epoll_ctl(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; */
-/* } */
-/* } */
-/* } */
-/* } */
-/* sendACKStrToHost(MSG_OK, NULL); */
-/* break; */
-/* case MSG_STOP: */
-/* LOGI("MSG_STOP handling\n"); */
-/* sendACKStrToHost(MSG_OK, NULL); */
-/* terminate_all(); */
-/* break; */
-/* case MSG_OPTION: */
-/* if(log->length > 0) */
-/* { */
-/* int i; */
-/* msg_t sendlog; */
-/* manager.config_flag = atoi(log->data); */
-/* sendACKStrToHost(MSG_OK, NULL); */
-
-/* LOGI("MSG_OPTION : str(%s), flag(%x)\n", log->data, manager.config_flag); */
-
-/* sendlog.type = MSG_OPTION; */
-/* sendlog.length = sprintf(sendlog.data, "%u", manager.config_flag); */
-
-/* for(i = 0; i < MAX_TARGET_COUNT; i++) */
-/* { */
-/* if(manager.target[i].socket != -1) */
-/* { */
-/* send(manager.target[i].socket, &sendlog, sizeof(sendlog.type) + sizeof(sendlog.length) + sendlog.length, MSG_NOSIGNAL); */
-/* } */
-/* } */
-/* } */
-/* else */
-/* { */
-/* sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_MESSAGE_DATA); */
-/* ret = 1; */
-/* } */
-/* break; */
-/* case MSG_ISALIVE: */
-/* sendACKStrToHost(MSG_OK, NULL); */
-/* break; */
-/* default: */
-/* LOGW("Unknown msg\n"); */
-/* sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_MESSAGE_TYPE); */
-/* ret = 1; */
-/* break; */
-/* } */
-/* return ret; */
+ if (IS_OPT_SET(FL_RECORDING))
+ del_input_events();
+ samplingStop();
}
-// ========================================================================================
-// socket and event_fd handling functions
-// ========================================================================================
-
-// return 0 if normal case
-// return plus value if non critical error occur
-// return minus value if critical error occur
-static int deviceEventHandler(input_dev* dev, int input_type)
+static void reconfigure_recording(struct conf_t conf)
{
- int ret = 0;
- struct input_event in_ev;
- msg_t log;
-
- if(input_type == INPUT_ID_TOUCH)
- {
- //touch read
- read(dev->fd, &in_ev, sizeof(struct input_event));
- log.type = MSG_RECORD;
- log.length = sprintf(log.data, "%s`,%s`,%ld`,%ld`,%hu`,%hu`,%u",
- STR_TOUCH, dev->fileName, in_ev.time.tv_sec,
- in_ev.time.tv_usec, in_ev.type, in_ev.code, in_ev.value);
- sendDataToHost(&log);
+ uint64_t old_features = prof_session.conf.use_features0;
+ uint64_t new_features = conf.use_features0;
+ uint64_t to_enable = (new_features ^ old_features) & new_features;
+ uint64_t to_disable = (new_features ^ old_features) & old_features;
+
+ if (IS_OPT_SET_IN(FL_RECORDING, to_disable)) {
+ del_input_events();
+ prof_session.conf.use_features0 &= ~FL_RECORDING;
}
- else if(input_type == INPUT_ID_KEY)
- {
- //key read
- read(dev->fd, &in_ev, sizeof(struct input_event));
- log.type = MSG_RECORD;
- log.length = sprintf(log.data, "%s`,%s`,%ld`,%ld`,%hu`,%hu`,%u",
- STR_KEY, dev->fileName, in_ev.time.tv_sec,
- in_ev.time.tv_usec, in_ev.type, in_ev.code, in_ev.value);
- sendDataToHost(&log);
+
+ if (IS_OPT_SET_IN(FL_RECORDING, to_enable)) {
+ add_input_events();
+ prof_session.conf.use_features0 |= FL_RECORDING;
}
- else
- {
- LOGW("unknown input_type\n");
- ret = 1;
+
+}
+
+int reconfigure(struct conf_t conf)
+{
+ reconfigure_recording(conf);
+
+ samplingStop();
+ memcpy(&prof_session.conf, &conf, sizeof(conf));
+ if (samplingStart() < 0) {
+ LOGE("Cannot start sampling\n");
+ return -1;
}
- return ret;
+ return 0;
}
-#define MAX_EVENTS_NUM 10
-static int deviceEventHandlerNew(input_dev* dev, int input_type)
+static Ecore_Fd_Handler *target_handlers[MAX_TARGET_COUNT];
+
+static int target_event_pid_handler(int index, uint64_t msg)
{
- 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 {
-// LOGI(">read %s events\n,", input_type==INPUT_ID_KEY?STR_KEY:STR_TOUCH);
- size = read(dev->fd, &in_ev[count], sizeof(*in_ev) );
-// LOGI("<read %s events : size = %d\n,", input_type==INPUT_ID_KEY?STR_KEY:STR_TOUCH,size);
- if (size >0)
- count++;
- } while (count < MAX_EVENTS_NUM && size > 0);
-
- if(count != 0){
- LOGI("readed %d %s events\n,", count, input_type==INPUT_ID_KEY?STR_KEY:STR_TOUCH);
- /* gen_message_event(&log,&in_ev[0],count,input_type); */
- pseudoSendDataToHost(&log);
- reset_data_msg(&log);
+ struct app_list_t *app = NULL;
+ struct app_info_t *app_info = NULL;
+ if (index == 0) { // main application
+ app_info = app_info_get_first(&app);
+ if (app_info == NULL) {
+ LOGE("No app info found\n");
+ return -1;
}
- }
- else
- {
- LOGW("unknown input_type\n");
- ret = 1;
- }
-/*
- if(input_type == INPUT_ID_TOUCH || input_type == INPUT_ID_KEY)
- {
-
- if (size = read(dev->fd, &in_ev, sizeof(in_ev) ) !=0 )
- {
- LOGI("readed %d touch events\n,", 1);
- gen_message_event(&log,&in_ev,1,input_type);
- pseudoSendDataToHost(&log);
+
+ while (app_info != NULL) {
+ if (is_same_app_process(app_info->exe_path,
+ manager.target[index].pid))
+ break;
+ app_info = app_info_get_next(&app);
+ }
+
+ if (app_info == NULL) {
+ LOGE("pid %d not found in app list\n",
+ manager.target[index].pid);
+ return -1;
+ }
+
+ if (start_replay() != 0) {
+ LOGE("Cannot start replay thread\n");
+ return -1;
}
}
- else
- {
- LOGW("unknown input_type\n");
- ret = 1;
+ manager.target[index].initial_log = 1;
+ return 0;
+}
+
+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,
+ manager.target_count - 1);
+
+ if (index == 0) // main application
+ stop_replay();
+
+ ecore_main_fd_handler_del(target_handlers[index]);
+
+ setEmptyTargetSlot(index);
+ // all target client are closed
+ if (0 == __sync_sub_and_fetch(&manager.target_count, 1)) {
+ LOGI("all targets are stopped\n");
+ if (stop_all() != ERR_NO)
+ LOGE("Stop failed\n");
+ return -11;
}
-*/
- return ret;
+
+ return 0;
}
// return 0 if normal case
// return plus value if non critical error occur
// return minus value if critical error occur
// return -11 if all target process closed
-static int targetEventHandler(int epollfd, int index, uint64_t msg)
+static int target_event_handler(int index, uint64_t msg)
{
- msg_t log;
-
- if(msg & EVENT_PID)
- {
- if(index == 0) // assume index 0 is main application process
- {
- int base_address;
- char tempBuff[DA_MSG_MAX];
- char tempBuff2[DA_MSG_MAX];
- char tempPath[PATH_MAX];
-
- get_executable(manager.appPath, tempPath, PATH_MAX);
- if(realpath(tempPath, tempBuff) == NULL)
- {
- LOGW("Failed to get realpath of app\n");
- strcpy(tempBuff, tempPath);
- }
-
- sprintf(tempPath, "/proc/%d/maps", manager.target[index].pid);
- sprintf(tempBuff2, "cat %s | grep %s | cut -d\"-\" -f1 > %s",
- tempPath, tempBuff, DA_BASE_ADDRESS);
- LOGI("base address command is %s\n", tempBuff2);
-
- do {
- if(access(tempPath, F_OK) != 0)
- return -1;
- if(is_same_app_process(manager.appPath, manager.target[index].pid) == 0)
- return -1;
-
- system(tempBuff2);
- if(get_app_base_address(&base_address) == 1)
- break;
- sleep(0);
- } while(1);
-
- tempPath[0] = '\0';
- get_app_install_path(tempPath, PATH_MAX);
-
-#ifndef LOCALTEST
- get_device_info(tempBuff, DA_MSG_MAX);
-#endif
-
- log.type = MSG_DEVICE;
- if (strlen(tempPath) > 0)
- {
- get_executable(manager.appPath, tempBuff2, DA_MSG_MAX);
- log.length = sprintf(log.data, "%s`,%d`,%Lu`,%d`,%u`,%d`,%s/%s", tempBuff,
- manager.target[index].pid, manager.target[index].starttime,
- is_app_built_pie(), base_address, get_app_type(manager.appPath),
- tempPath, get_app_name(tempBuff2));
- }
- else
- {
- log.length = sprintf(log.data, "%s`,%d`,%Lu`,%d`,%u`,%d`,", tempBuff,
- manager.target[index].pid, manager.target[index].starttime,
- is_app_built_pie(), base_address, get_app_type(manager.appPath));
- }
-
- LOGI("%s\n", log.data);
- }
- else
- {
- log.type = MSG_PID;
- log.length = sprintf(log.data, "%d`,%Lu", manager.target[index].pid, manager.target[index].starttime);
- }
+ int err = 0;
+ if (msg & EVENT_PID)
+ err = target_event_pid_handler(index, msg);
+ if (err)
+ return err;
- sendDataToHost(&log);
- manager.target[index].initial_log = 1;
- }
+ if (msg & EVENT_STOP || msg & EVENT_ERROR)
+ err = target_event_stop_handler(index, msg);
- if(msg & EVENT_STOP || msg & EVENT_ERROR)
- {
- LOGI("target close, socket(%d), pid(%d) : (remaining %d target)\n",
- manager.target[index].socket, manager.target[index].pid, manager.target_count - 1);
+ return err;
+}
- terminate_target(index);
- epoll_ctl(epollfd, EPOLL_CTL_DEL, manager.target[index].event_fd, NULL);
- setEmptyTargetSlot(index);
- if (0 == __sync_sub_and_fetch(&manager.target_count, 1)) // all target client are closed
- {
- log.type = MSG_TERMINATE;
- log.length = 0;
- log.data[0] = '\0';
- sendDataToHost(&log);
- return -11;
+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 0;
+ 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)
+/**
+ * return 0 if normal case
+ * return plus value if non critical error occur
+ * return minus value if critical error occur
+ */
+static int targetServerHandler(void)
{
- msg_t log;
- struct epoll_event ev;
+ msg_target_t log;
int index = getEmptyTargetSlot();
- if(index == MAX_TARGET_COUNT)
- {
+ if (index == MAX_TARGET_COUNT) {
LOGW("Max target number(8) reached, no more target can connected\n");
return 1;
}
- manager.target[index].socket = accept(manager.target_server_socket, NULL, NULL);
+ manager.target[index].socket =
+ accept(manager.target_server_socket, NULL, NULL);
- if(manager.target[index].socket >= 0) // accept succeed
- {
-#ifndef LOCALTEST
- // set smack attribute for certification
- fsetxattr(manager.target[index].socket, "security.SMACK64IPIN", "*", 1, 0);
- fsetxattr(manager.target[index].socket, "security.SMACK64IPOUT", "*", 1, 0);
-#endif /* LOCALTEST */
+ if (manager.target[index].socket >= 0) {
+ /* accept succeed */
+ fd_setup_attributes(manager.target[index].socket);
- // send config message to target process
+ /* send config message to target process */
log.type = MSG_OPTION;
- log.length = sprintf(log.data, "%u", manager.config_flag);
- send(manager.target[index].socket, &log, sizeof(log.type) + sizeof(log.length) + log.length, MSG_NOSIGNAL);
+ 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);
- if(manager.target[index].event_fd == -1)
- {
+ 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", manager.target[index].socket);
+ LOGE("fail to make event fd for socket (%d)\n",
+ manager.target[index].socket);
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", manager.target[index].socket);
+ 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;
}
// make recv thread for target
- if(makeRecvThread(index) != 0)
- {
+ if (makeRecvThread(index) != 0) {
// fail to make recv thread
- LOGE("fail to make recv thread for socket (%d)\n", manager.target[index].socket);
- epoll_ctl(efd, EPOLL_CTL_DEL, manager.target[index].event_fd, NULL);
+ LOGE("fail to make recv thread for socket (%d)\n",
+ manager.target[index].socket);
+ ecore_main_fd_handler_del(target_handlers[index]);
goto TARGET_CONNECT_FAIL;
}
- if(manager.app_launch_timerfd >= 0)
- {
- epoll_ctl(efd, EPOLL_CTL_DEL, manager.app_launch_timerfd, NULL);
- close(manager.app_launch_timerfd);
- manager.app_launch_timerfd = -1;
+ 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");
}
LOGI("target connected = %d(running %d target)\n",
- manager.target[index].socket, manager.target_count + 1);
+ manager.target[index].socket, manager.target_count + 1);
manager.target_count++;
return 0;
- }
- else // accept error
- {
+ } else {
+ // accept error
LOGE("Failed to accept at target server socket\n");
}
-TARGET_CONNECT_FAIL:
- if(manager.target_count == 0) // if this connection is main connection
- {
+ TARGET_CONNECT_FAIL:
+ if (manager.target_count == 0) {
+ // if this connection is main connection
return -1;
- }
- else // if this connection is not main connection then ignore process by error
- {
+ } else {
+ // if this connection is not main connection then ignore process by error
setEmptyTargetSlot(index);
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;
+ struct msg_t msg_head;
+ struct msg_t *msg;
+ int res = 0;
+
+ if (manager.connect_timeout_timerfd >= 0) {
+ LOGI("release connect timeout timer\n");
+ close(manager.connect_timeout_timerfd);
+ manager.connect_timeout_timerfd = -1;
+ }
+ // Receive header
+ recv_len = recv(manager.host.control_socket,
+ &msg_head, MSG_CMD_HDR_LEN, 0);
+ // error or close request from host
+ if (recv_len == -1 || recv_len == 0)
+ return -11;
+ else {
+ msg = malloc(MSG_CMD_HDR_LEN + msg_head.len);
+ if (!msg) {
+ LOGE("Cannot alloc msg\n");
+ sendACKToHost(msg_head.id, ERR_WRONG_MESSAGE_FORMAT, 0, 0);
+ return -1;
+ }
+ msg->id = msg_head.id;
+ msg->len = msg_head.len;
+ if (msg->len > 0) {
+ // Receive payload (if exists)
+ recv_len = recv(manager.host.control_socket,
+ msg->payload, msg->len, MSG_WAITALL);
+ if (recv_len == -1)
+ return -11;
+ }
+ printBuf((char *)msg, MSG_CMD_HDR_LEN + msg->len);
+ res = host_message_handler(msg);
+ free(msg);
+ }
+
+ return res;
+}
+
+static Eina_Bool host_ctrl_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+ 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;
+}
+
+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
+ }
+
+ 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(int efd)
+static int hostServerHandler(void)
{
static int hostserverorder = 0;
int csocket;
- struct epoll_event ev;
- if(hostserverorder > 1) // control and data socket connected already
- return 1; // ignore
+ 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 (csocket >= 0) {
+ // accept succeed
- if(hostserverorder == 0)
- {
+ if (hostserverorder == 0) {
manager.host.control_socket = csocket;
unlink_portfile();
LOGI("host control socket connected = %d\n", csocket);
- }
- else
- {
+ 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
- {
+ } else {
+ // accept error
LOGE("Failed to accept from host server socket\n");
return -1;
}
}
-
-//TODO del it or move to debug section
-void printBuf (char * buf, int len)
+static int kernel_handler(void)
{
- int i,j;
- char local_buf[3*16 + 2*16 + 1];
- char * p1, * p2;
- LOGI("BUFFER:\n");
- for ( i = 0; i < len/16 + 1; i++)
- {
- memset(local_buf, ' ', 5*16);
- p1 = local_buf;
- p2 = local_buf + 3*17;
- for ( j = 0; j < 16; j++)
- if (i*16+j < len )
- {
- sprintf(p1, "%02X ",(unsigned char) *buf);
- p1+=3;
- if (isprint( *buf)){
- sprintf(p2, "%c ",(int)*buf);
- }else{
- sprintf(p2,". ");
- }
- p2+=2;
- buf++;
- }
- *p1 = ' ';
- *p2 = '\0';
- LOGI("%s\n",local_buf);
- }
-}
+ int res, size, ret;
+ socklen_t optlen;
+ struct nlmsghdr *nlh;
+ struct cn_msg *msg;
+ ssize_t len;
-// return 0 if normal case
-// return plus value if non critical error occur
-// return minus value if critical error occur
-// return -11 if socket closed
+ /* Get buffer size */
+ optlen = sizeof(size);
-static int controlSocketHandler(int efd)
-{
- ssize_t recvLen;
- char recvBuf[DA_MSG_MAX];
- msg_t log;
-
- // host log format xxx|length|str
- recvLen = recv(manager.host.control_socket, recvBuf, DA_MSG_MAX, 0);
-
- if (recvLen > 0)
- {
- recvBuf[recvLen] = '\0';
- printBuf(recvBuf,recvLen);
- LOGI("host sent control msg str(%s)\n", recvBuf);
- if(parseHostMessage(&log, recvBuf) < 0)
- {
- // error to parse host message
- sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_MESSAGE_FORMAT);
- return 1;
- }
+ /* We're using SOCK_DGRAM, so, get it maximum size */
+ res = getsockopt(manager.kernel_socket, SOL_SOCKET, SO_SNDBUF, &size,
+ &optlen);
- // host msg command handling
- return hostMessageHandle(&log);
- }
- else // close request from HOST
- {
- return -11;
+ if (res == -1) {
+ LOGE("Get maximum buffer size failed\n");
+ return -1;
}
-}
-// return 0 for normal case
-int daemonLoop()
-{
- int ret = 0; // return value
- int i, k;
- ssize_t recvLen;
-
- struct epoll_event ev, *events;
- int efd; // epoll fd
- int numevent; // number of occured events
-
- _get_fds(g_key_dev, INPUT_ID_KEY);
- _get_fds(g_touch_dev, INPUT_ID_TOUCH);
-
- // initialize epoll event pool
- events = (struct epoll_event*) malloc(sizeof(struct epoll_event) * EPOLL_SIZE);
- if(events == NULL)
- {
- LOGE("Out of memory when allocate epoll event pool\n");
- ret = -1;
- goto END_RETURN;
- }
- if((efd = epoll_create(MAX_CONNECT_SIZE)) < 0)
- {
- LOGE("epoll creation error\n");
+ /* 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 END_EVENT;
+ goto free_and_end;
}
- // add server sockets to epoll event pool
- ev.events = EPOLLIN;
- ev.data.fd = manager.host_server_socket;
- if(epoll_ctl(efd, EPOLL_CTL_ADD, manager.host_server_socket, &ev) < 0)
- {
- LOGE("Host server socket epoll_ctl error\n");
+ /* nlh data field contains connectors message */
+ msg = NLMSG_DATA(nlh);
+ if (msg->len == 0) {
ret = -1;
- goto END_EFD;
+ goto free_and_end;
}
- ev.events = EPOLLIN;
- ev.data.fd = manager.target_server_socket;
- if(epoll_ctl(efd, EPOLL_CTL_ADD, manager.target_server_socket, &ev) < 0)
- {
- LOGE("Target server socket epoll_ctl error\n");
- ret = -1;
- goto END_EFD;
+
+ /* Insert your message handler here */
+
+ ret = 0;
+
+free_and_end:
+ free(nlh);
+
+ return ret;
+}
+
+
+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)
+{
+ // connect request from host
+ int result = hostServerHandler();
+ if (result < 0) {
+ LOGE("Internal DA framework error (hostServerHandler)\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(efd, EPOLL_CTL_ADD, g_key_dev[i].fd, &ev) < 0)
- {
- LOGE("keyboard device file epoll_ctl error\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);
}
- 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(efd, EPOLL_CTL_ADD, g_touch_dev[i].fd, &ev) < 0)
- {
- LOGE("touch device file epoll_ctl error\n");
- }
- }
+ 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");
}
- // handler loop
- while (1)
- {
- numevent = epoll_wait(efd, events, EPOLL_SIZE, -1);
- if(numevent <= 0)
- {
- LOGE("Failed to epoll_wait : num of event(%d), errno(%d)\n", numevent, errno);
- continue;
- }
+ return ECORE_CALLBACK_RENEW;
+}
- 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 == targetEventHandler(efd, k, u))
- {
- LOGI("all target process is closed\n");
- terminate_all();
- ret = 0;
- goto END_EFD;
- }
- }
- break;
- }
- }
+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;
+ }
+
+ 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;
+ }
+
+ 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;
+}
- 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(deviceEventHandlerNew(&g_touch_dev[k], INPUT_ID_TOUCH) < 0)
- {
- terminate_error("Internal DA framework error, Please re-run the profiling.", 1);
- ret = -1;
- goto END_EFD;
- }
- break;
- }
- }
+// return 0 for normal case
+int daemonLoop(void)
+{
+ int return_value = 0;
- 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(deviceEventHandlerNew(&g_key_dev[k], INPUT_ID_KEY) < 0)
- {
- terminate_error("Internal DA framework error, Please re-run the profiling.", 1);
- ret = -1;
- goto END_EFD;
- }
- break;
- }
- }
+ ecore_init();
- if(g_key_dev[k].fd != ARRAY_END)
- continue;
-
- // connect request from target
- if(events[i].data.fd == manager.target_server_socket)
- {
- if(targetServerHandler(efd) < 0) // critical error
- {
- terminate_error("Internal DA framework error, Please re-run the profiling.", 1);
- ret = -1;
- goto END_EFD;
- }
- }
- // connect request from host
- else if(events[i].data.fd == manager.host_server_socket)
- {
- int result = hostServerHandler(efd);
- if(result < 0)
- {
- terminate_error("Internal DA framework error, Please re-run the profiling.", 1);
- ret = -1;
- goto END_EFD;
- }
- }
- // control message from host
- else if(events[i].data.fd == manager.host.control_socket)
- {
- int result = controlSocketHandler(efd);
- if(result == -11) // socket close
- {
- // close target and host socket and quit
- LOGI("host close = %d\n", manager.host.control_socket);
- terminate_all();
- ret = 0;
- goto END_EFD;
- }
- else if(result < 0)
- {
- terminate_error("Internal DA framework error, Please re-run the profiling.", 1);
- ret = -1;
- goto END_EFD;
- }
- }
- 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
- epoll_ctl(efd, EPOLL_CTL_DEL, manager.host.data_socket, NULL);
- close(manager.host.data_socket);
- manager.host.data_socket = -1;
- }
-
- LOGW("host message from data socket %d\n", recvLen);
- }
- // check for application launch timerfd
- else if(events[i].data.fd == manager.app_launch_timerfd)
- {
- // send to host timeout error message for launching application
- terminate_error("Failed to launch application", 1);
- epoll_ctl(efd, EPOLL_CTL_DEL, manager.app_launch_timerfd, NULL);
- close(manager.app_launch_timerfd);
- manager.app_launch_timerfd = -1;
- ret = -1;
- goto END_EFD;
- }
- // unknown socket
- else
- {
- // never happened
- LOGW("Unknown socket fd (%d)\n", events[i].data.fd);
- }
- }
+ if (init_input_events() == -1) {
+ return_value = -1;
+ goto END_EVENT;
}
-END_EFD:
- close(efd);
-END_EVENT:
- free(events);
-END_RETURN:
- return ret;
+ if (!initialize_events()) {
+ return_value = -1;
+ goto END_EFD;
+ }
+
+ if (launch_timer_start() < 0) {
+ LOGE("Launch timer start failed\n");
+ return_value = -1;
+ goto END_EFD;
+ }
+
+ init_prof_session(&prof_session);
+
+ ecore_main_loop_begin();
+ ecore_shutdown();
+
+ END_EFD:
+ LOGI("close efd\n");
+ close(manager.efd);
+ END_EVENT:
+ return return_value;
}