[FIX] wrong pack size of system memory total/used
[platform/core/system/swap-manager.git] / daemon / daemon.c
1 /*
2  *  DA manager
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Jaewon Lim <jaewon81.lim@samsung.com>
9  * Woojin Jung <woojin2.jung@samsung.com>
10  * Juyoung Kim <j0.kim@samsung.com>
11  * Cherepanov Vitaliy <v.cherepanov@samsung.com>
12  * Nikita Kalyazin    <n.kalyazin@samsung.com>
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  * http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the License is distributed on an "AS IS" BASIS,
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23  * See the License for the specific language governing permissions and
24  * limitations under the License.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  * - Samsung RnD Institute Russia
29  *
30  */
31 #define __STDC_FORMAT_MACROS
32 #include <stdio.h>
33 #include <stdlib.h>             // for realpath
34 #include <string.h>             // for strtok, strcpy, strncpy
35 #include <limits.h>             // for realpath
36 #include <inttypes.h>
37
38 #include <errno.h>              // for errno
39 #include <sys/types.h>          // for accept, mkdir, opendir, readdir
40 #include <sys/socket.h>         // for accept
41 #include <sys/stat.h>           // for mkdir
42 #include <sys/eventfd.h>        // for eventfd
43 #include <sys/epoll.h>          // for epoll apis
44 #include <sys/timerfd.h>        // for timerfd
45 #include <unistd.h>             // for access, sleep
46 #include <stdbool.h>
47
48 #include <ctype.h>
49
50 #ifndef LOCALTEST
51 #include <attr/xattr.h>         // for fsetxattr
52 #include <sys/smack.h>
53 #endif
54
55 #include <linux/input.h>
56 #include <dirent.h>
57 #include <fcntl.h>
58 #include "daemon.h"
59 #include "sys_stat.h"
60 #include "utils.h"
61 #include "da_protocol.h"
62 #include "da_inst.h"
63 #include "da_data.h"
64 #include "debug.h"
65
66 #define DA_WORK_DIR                     "/home/developer/sdk_tools/da/"
67 #define DA_READELF_PATH                 "/home/developer/sdk_tools/da/readelf"
68 #define SCREENSHOT_DIR                  "/tmp/da"
69
70 #define EPOLL_SIZE                      10
71 #define MAX_APP_LAUNCH_TIME             60
72 #define MAX_CONNECT_TIMEOUT_TIME        5*60
73
74 #define MAX_DEVICE                      10
75 #define MAX_FILENAME                    128
76 #define BUF_SIZE                        1024
77 #define ARRAY_END                       (-11)
78
79 input_dev g_key_dev[MAX_DEVICE];
80 input_dev g_touch_dev[MAX_DEVICE];
81
82 // return bytes size of readed data
83 // return 0 if no data readed or error occurred
84 static int _file_read(FILE *fp, char *buffer, int size)
85 {
86         int ret = 0;
87
88         if (fp != NULL && size > 0) {
89                 ret = fread((void *)buffer, sizeof(char), size, fp);
90                 buffer[ret] = '\0';
91         } else {
92                 // fp is null
93                 if (size > 0)
94                         buffer[0] = '\0';
95                 ret = 0;        // error case
96         }
97
98         return ret;
99 }
100
101 // get input id of given input device
102 static int get_input_id(char *inputname)
103 {
104         static int query_cmd_type = 0;  // 1 if /lib/udev/input_id, 2 if udevadm
105         FILE *cmd_fp = NULL;
106         char buffer[BUF_SIZE];
107         char command[MAX_FILENAME];
108         int ret = -1;
109
110         // determine input_id query command
111         if (unlikely(query_cmd_type == 0)) {
112                 if (access("/lib/udev/input_id", F_OK) == 0) {
113                         // there is /lib/udev/input_id
114                         query_cmd_type = 1;
115                 } else {
116                         // there is not /lib/udev/input_id
117                         query_cmd_type = 2;
118                 }
119         }
120         // make command string
121         if (query_cmd_type == 1) {
122                 sprintf(command, "/lib/udev/input_id /class/input/%s",
123                         inputname);
124         } else {
125                 sprintf(command,
126                         "udevadm info --name=input/%s --query=property",
127                         inputname);
128         }
129
130         // run command
131         cmd_fp = popen(command, "r");
132         if (_file_read(cmd_fp, buffer, BUF_SIZE) < 0) {
133                 LOGE("Failed to read input_id\n");
134                 if (cmd_fp != NULL)
135                         pclose(cmd_fp);
136                 return ret;
137         }
138         // determine input id
139         if (strstr(buffer, INPUT_ID_STR_KEY)) {
140                 // key
141                 ret = INPUT_ID_KEY;
142         } else if (strstr(buffer, INPUT_ID_STR_TOUCH)) {
143                 // touch
144                 ret = INPUT_ID_TOUCH;
145         } else if (strstr(buffer, INPUT_ID_STR_KEYBOARD)) {
146                 // keyboard
147                 ret = INPUT_ID_KEY;
148         } else if (strstr(buffer, INPUT_ID_STR_TABLET)) {
149                 // touch (emulator)
150                 ret = INPUT_ID_TOUCH;
151         }
152
153         if (cmd_fp != NULL)
154                 pclose(cmd_fp);
155         return ret;
156 }
157
158 // get filename and fd of given input type devices
159 static void _get_fds(input_dev *dev, int input_id)
160 {
161         DIR *dp;
162         struct dirent *d;
163         int count = 0;
164
165         dp = opendir("/sys/class/input");
166
167         if (dp != NULL) {
168                 while ((d = readdir(dp)) != NULL) {
169                         if (!strncmp(d->d_name, "event", 5)) {
170                                 // start with "event"
171                                 // event file
172                                 if (input_id == get_input_id(d->d_name)) {
173                                         sprintf(dev[count].fileName,
174                                                 "/dev/input/%s", d->d_name);
175                                         dev[count].fd =
176                                             open(dev[count].fileName,
177                                                  O_RDWR | O_NONBLOCK);
178                                         count++;
179                                 }
180                         }
181                 }
182
183                 closedir(dp);
184         }
185         dev[count].fd = ARRAY_END;      // end of input_dev array
186 }
187
188 //static
189 void _device_write(input_dev *dev, struct input_event *in_ev)
190 {
191         int i;
192         for (i = 0; dev[i].fd != ARRAY_END; i++) {
193                 if (dev[i].fd >= 0) {
194                         write(dev[i].fd, in_ev, sizeof(struct input_event));
195                         LOGI("write(%d, %d, %d)\n",
196                              dev[i].fd, (int)in_ev, sizeof(struct input_event));
197                 }
198         }
199 }
200
201 long long get_total_alloc_size()
202 {
203         int i;
204         long long allocsize = 0;
205
206         for (i = 0; i < MAX_TARGET_COUNT; i++) {
207                 if (manager.target[i].socket != -1 && manager.target[i].allocmem > 0)
208                    allocsize += manager.target[i].allocmem;
209         }
210         return allocsize;
211 }
212
213 static int getEmptyTargetSlot()
214 {
215         int i;
216         for (i = 0; i < MAX_TARGET_COUNT; i++) {
217                 if (manager.target[i].socket == -1)
218                         break;
219         }
220
221         return i;
222 }
223
224 static void setEmptyTargetSlot(int index)
225 {
226         if (index >= 0 && index < MAX_TARGET_COUNT) {
227                 manager.target[index].pid = -1;
228                 manager.target[index].recv_thread = -1;
229                 manager.target[index].allocmem = 0;
230                 manager.target[index].initial_log = 0;
231                 if (manager.target[index].event_fd != -1)
232                         close(manager.target[index].event_fd);
233                 manager.target[index].event_fd = -1;
234                 if (manager.target[index].socket != -1)
235                         close(manager.target[index].socket);
236                 manager.target[index].socket = -1;
237         }
238 }
239
240 // =============================================================================
241 // start and terminate control functions
242 // =============================================================================
243
244 //start application launch timer function
245 static int start_app_launch_timer()
246 {
247         int res = 0;
248         struct epoll_event ev;
249
250         manager.app_launch_timerfd =
251             timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
252         if (manager.app_launch_timerfd > 0) {
253                 struct itimerspec ctime;
254                 ctime.it_value.tv_sec = MAX_APP_LAUNCH_TIME;
255                 ctime.it_value.tv_nsec = 0;
256                 ctime.it_interval.tv_sec = 0;
257                 ctime.it_interval.tv_nsec = 0;
258                 if (timerfd_settime(manager.app_launch_timerfd, 0, &ctime, NULL) < 0) {
259                         LOGE("fail to set app launch timer\n");
260                         close(manager.app_launch_timerfd);
261                         manager.app_launch_timerfd = -1;
262                         res = -1;
263                 } else {
264                         // add event fd to epoll list
265                         ev.events = EPOLLIN;
266                         ev.data.fd = manager.app_launch_timerfd;
267                         if (epoll_ctl(manager.efd, EPOLL_CTL_ADD,
268                                       manager.app_launch_timerfd, &ev) < 0) {
269                                 // fail to add event fd
270                                 LOGE("fail to add app launch timer fd to epoll list\n");
271                                 close(manager.app_launch_timerfd);
272                                 manager.app_launch_timerfd = -1;
273                                 res = -2;
274                         } else {
275                                 LOGI("application launch time started\n");
276                         }
277                 }
278         } else {
279                 LOGE("cannot create launch timer\n");
280                 res = -3;
281         }
282
283         return res;
284 }
285
286 //stop application launch timer
287 static int stop_app_launch_timer()
288 {
289         if (0 > epoll_ctl(manager.efd, EPOLL_CTL_DEL,
290                           manager.app_launch_timerfd, NULL))
291                 LOGW("fail to EPOLL DEL of app launch timerfd\n");
292         close(manager.app_launch_timerfd);
293         manager.app_launch_timerfd = -1;
294         return 0;
295 }
296
297 static int exec_app(const struct app_info_t *app_info)
298 {
299         int res = 0;
300
301         if (app_info == NULL) {
302                 LOGE("Cannot exec app. app_info is NULL");
303                 return -1;
304         }
305
306         switch (app_info->app_type) {
307         case APP_TYPE_TIZEN:
308                 kill_app(app_info->exe_path);
309                 if (exec_app_tizen(app_info->app_id, app_info->exe_path)) {
310                         LOGE("Cannot exec tizen app %s\n", app_info->app_id);
311                         res = -1;
312                 }
313                 break;
314         case APP_TYPE_RUNNING:
315                 // TODO: nothing, it's running
316                 LOGI("already started\n");
317                 break;
318         case APP_TYPE_COMMON:
319                 kill_app(app_info->exe_path);
320                 if (exec_app_common(app_info->exe_path)) {
321                         LOGE("Cannot exec common app %s\n", app_info->exe_path);
322                         res = -1;
323                 }
324                 break;
325         default:
326                 LOGE("Unknown app type %d\n", app_info->app_type);
327                 res = -1;
328                 break;
329         }
330
331         if (res == 0 && app_info->app_type != APP_TYPE_RUNNING)
332                 if (start_app_launch_timer() < 0)
333                         res = -1;
334
335         LOGI("ret=%d\n", res);
336         return res;
337 }
338
339 int launch_timer_start()
340 {
341         static struct epoll_event ev;
342         int res = 0;
343
344         manager.connect_timeout_timerfd =
345             timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
346         if (manager.connect_timeout_timerfd > 0) {
347                 struct itimerspec ctime;
348                 ctime.it_value.tv_sec = MAX_CONNECT_TIMEOUT_TIME;
349                 ctime.it_value.tv_nsec = 0;
350                 ctime.it_interval.tv_sec = 0;
351                 ctime.it_interval.tv_nsec = 0;
352                 if (timerfd_settime(manager.connect_timeout_timerfd, 0, &ctime, NULL) < 0) {
353                         LOGE("fail to set connect timeout timer\n");
354                         close(manager.connect_timeout_timerfd);
355                         manager.connect_timeout_timerfd = -1;
356                 } else {
357                         // add event fd to epoll list
358                         ev.events = EPOLLIN;
359                         ev.data.fd = manager.connect_timeout_timerfd;
360                         if (epoll_ctl(manager.efd, EPOLL_CTL_ADD,
361                                       manager.connect_timeout_timerfd, &ev) < 0)
362                         {
363                                 // fail to add event fd
364                                 LOGE("fail to add app connection timeout timer fd to epoll list\n");
365                                 close(manager.connect_timeout_timerfd);
366                                 manager.connect_timeout_timerfd = -1;
367                         } else {
368                                 LOGI("connection timeout timer started\n");
369                         }
370                 }
371         } else {
372                 LOGE("cannot create connection timeout timer\n");
373         }
374
375         LOGI("ret=%d\n", res);
376         return res;
377 }
378
379 static void epoll_add_input_events();
380 static void epoll_del_input_events();
381
382 int start_profiling()
383 {
384         struct app_list_t *app = NULL;
385         const struct app_info_t *app_info = NULL;
386         int res = 0;
387
388         app_info = app_info_get_first(&app);
389         if (app_info == NULL) {
390                 LOGE("No app info found\n");
391                 return -1;
392         }
393         // remove previous screen capture files
394         remove_indir(SCREENSHOT_DIR);
395         if (mkdir(SCREENSHOT_DIR, 0777) == -1 && errno != EEXIST)
396                 LOGW("Failed to create directory for screenshot : %s\n",
397                      strerror(errno));
398
399 #ifndef LOCALTEST
400         smack_lsetlabel(SCREENSHOT_DIR, "*", SMACK_LABEL_ACCESS);
401 #endif
402
403         if (samplingStart() < 0) {
404                 LOGE("Cannot start sampling\n");
405                 res = -1;
406                 goto exit;
407         }
408
409         if (IS_OPT_SET(FL_RECORDING))
410                 epoll_add_input_events();
411
412         if (exec_app(app_info)) {
413                 LOGE("Cannot exec app\n");
414                 res = -1;
415                 goto recording_stop;
416         }
417
418         goto exit;
419
420  recording_stop:
421         if (IS_OPT_SET(FL_RECORDING))
422                 epoll_del_input_events();
423         samplingStop();
424
425  exit:
426         LOGI("return %d\n", res);
427         return res;
428 }
429
430 void stop_profiling(void)
431 {
432         if (IS_OPT_SET(FL_RECORDING))
433                 epoll_del_input_events();
434         samplingStop();
435 }
436
437 static void reconfigure_recording(struct conf_t conf)
438 {
439         uint64_t old_features = prof_session.conf.use_features0;
440         uint64_t new_features = conf.use_features0;
441         uint64_t to_enable = (new_features ^ old_features) & new_features;
442         uint64_t to_disable = (new_features ^ old_features) & old_features;
443
444         if (IS_OPT_SET_IN(FL_RECORDING, to_disable)) {
445                 epoll_del_input_events();
446                 prof_session.conf.use_features0 &= ~FL_RECORDING;
447         }
448
449         if (IS_OPT_SET_IN(FL_RECORDING, to_enable)) {
450                 epoll_add_input_events();
451                 prof_session.conf.use_features0 |= FL_RECORDING;
452         }
453
454 }
455
456 int reconfigure(struct conf_t conf)
457 {
458         reconfigure_recording(conf);
459
460         samplingStop();
461         memcpy(&prof_session.conf, &conf, sizeof(conf));
462         if (samplingStart() < 0) {
463                 LOGE("Cannot start sampling\n");
464                 return -1;
465         }
466
467         return 0;
468 }
469
470 // just send stop message to all target process
471 static void terminate_all_target()
472 {
473         int i;
474         ssize_t sendlen;
475         msg_target_t sendlog;
476
477         sendlog.type = MSG_STOP;
478         sendlog.length = 0;
479
480         for (i = 0; i < MAX_TARGET_COUNT; i++) {
481                 if (manager.target[i].socket != -1) {
482                         sendlen = send(manager.target[i].socket, &sendlog,
483                                        sizeof(sendlog.type) +
484                                        sizeof(sendlog.length), MSG_NOSIGNAL);
485                         if (sendlen != -1) {
486                                 // send to only first main target proces
487                                 LOGI("TERMINATE send exit msg (socket %d) "
488                                      "by terminate_all_target()\n",
489                                      manager.target[i].socket);
490                                 break;
491                         }
492                 }
493         }
494 }
495
496 // terminate all target and wait for threads
497 void terminate_all()
498 {
499         int i;
500         terminate_all_target();
501
502         // wait for all other thread exit
503         for (i = 0; i < MAX_TARGET_COUNT; i++) {
504                 if (manager.target[i].recv_thread != -1) {
505                         LOGI("join recv thread [%d] is started\n", i);
506                         pthread_join(manager.target[i].recv_thread, NULL);
507                         LOGI("join recv thread %d. done\n", i);
508                 }
509         }
510 }
511
512 // terminate all profiling by critical error
513 // TODO: don't send data to host
514 static void terminate_error(char *errstr, int send_to_host)
515 {
516         LOGE("termination all with err '%s'\n", errstr);
517         struct msg_data_t *msg = NULL;
518         if (send_to_host != 0) {
519                 msg = gen_message_error(errstr);
520                 if (msg) {
521                         write_to_buf(msg);
522                         free_msg_data(msg);
523                 } else {
524                         LOGI("cannot generate error message\n");
525                 }
526         }
527         terminate_all();
528 }
529
530 #define MAX_EVENTS_NUM 10
531 static int deviceEventHandler(input_dev *dev, int input_type)
532 {
533         int ret = 0;
534         ssize_t size = 0;
535         int count = 0;
536         struct input_event in_ev[MAX_EVENTS_NUM];
537         struct msg_data_t *log;
538
539         if (input_type == INPUT_ID_TOUCH || input_type == INPUT_ID_KEY) {
540                 do {
541                         size = read(dev->fd, &in_ev[count], sizeof(*in_ev));
542                         if (size > 0)
543                                 count++;
544                 } while (count < MAX_EVENTS_NUM && size > 0);
545
546                 if (count) {
547                         LOGI("read %d %s events\n",
548                              count,
549                              input_type == INPUT_ID_KEY ? STR_KEY : STR_TOUCH);
550                         log = gen_message_event(in_ev, count, input_type);
551                         printBuf((char *)log, MSG_DATA_HDR_LEN + log->len);
552                         write_to_buf(log);
553                         free_msg_data(log);
554                 }
555         } else {
556                 LOGW("unknown input_type\n");
557                 ret = 1;        // it is not error
558         }
559         return ret;
560 }
561
562 static int target_event_pid_handler(int index, uint64_t msg)
563 {
564         struct app_list_t *app = NULL;
565         struct app_info_t *app_info = NULL;
566         if (index == 0) {       // main application
567                 app_info = app_info_get_first(&app);
568                 if (app_info == NULL) {
569                         LOGE("No app info found\n");
570                         return -1;
571                 }
572
573                 while (app_info != NULL) {
574                         if (is_same_app_process(app_info->exe_path,
575                                                 manager.target[index].pid))
576                                 break;
577                         app_info = app_info_get_next(&app);
578                 }
579
580                 if (app_info == NULL) {
581                         LOGE("pid %d not found in app list\n",
582                              manager.target[index].pid);
583                         return -1;
584                 }
585
586                 if (start_replay() != 0) {
587                         LOGE("Cannot start replay thread\n");
588                         return -1;
589                 }
590         }
591         manager.target[index].initial_log = 1;
592         return 0;
593 }
594
595 static int target_event_stop_handler(int epollfd, int index, uint64_t msg)
596 {
597         LOGI("target close, socket(%d), pid(%d) : (remaining %d target)\n",
598              manager.target[index].socket, manager.target[index].pid,
599              manager.target_count - 1);
600
601         if (index == 0)         // main application
602                 stop_replay();
603
604         if (0 > epoll_ctl(epollfd, EPOLL_CTL_DEL,
605                           manager.target[index].event_fd, NULL))
606                 LOGW("fail to EPOLL DEL of event fd(%d)\n", index);
607
608         setEmptyTargetSlot(index);
609         // all target client are closed
610         if (0 == __sync_sub_and_fetch(&manager.target_count, 1)) {
611                 LOGI("all targets are stopped\n");
612                 if (stop_all() != ERR_NO)
613                         LOGE("Stop failed\n");
614                 return -11;
615         }
616
617         return 0;
618 }
619
620 // return 0 if normal case
621 // return plus value if non critical error occur
622 // return minus value if critical error occur
623 // return -11 if all target process closed
624 static int target_event_handler(int epollfd, int index, uint64_t msg)
625 {
626         int err = 0;
627         if (msg & EVENT_PID)
628                 err = target_event_pid_handler(index, msg);
629         if (err)
630                 return err;
631
632         if (msg & EVENT_STOP || msg & EVENT_ERROR)
633                 err = target_event_stop_handler(epollfd, index, msg);
634
635         return err;
636 }
637
638 #ifndef LOCALTEST
639 static void target_setup_smack_attributes(int target_index)
640 {
641         fsetxattr(manager.target[target_index].socket,
642                   "security.SMACK64IPIN", "*", 1, 0);
643         fsetxattr(manager.target[target_index].socket,
644                   "security.SMACK64IPOUT", "*", 1, 0);
645 }
646 #else
647 static void target_setup_smack_attributes(int unused)
648 {
649 }
650 #endif
651
652 // return 0 if normal case
653 // return plus value if non critical error occur
654 // return minus value if critical error occur
655 static int targetServerHandler(int efd)
656 {
657         msg_target_t log;
658         struct epoll_event ev;
659
660         int index = getEmptyTargetSlot();
661         if (index == MAX_TARGET_COUNT) {
662                 LOGW("Max target number(8) reached, no more target can connected\n");
663                 return 1;
664         }
665
666         manager.target[index].socket =
667             accept(manager.target_server_socket, NULL, NULL);
668
669         if (manager.target[index].socket >= 0) {
670                 // accept succeed
671                 target_setup_smack_attributes(index);
672
673                 // send config message to target process
674                 log.type = MSG_OPTION;
675                 log.length = sprintf(log.data, "%lu",
676                                      (unsigned long int)prof_session.conf.use_features0);
677                 if (0 > send(manager.target[index].socket, &log,
678                              sizeof(log.type) + sizeof(log.length) + log.length,
679                              MSG_NOSIGNAL))
680                         LOGE("fail to send data to target index(%d)\n", index);
681
682                 // make event fd
683                 manager.target[index].event_fd = eventfd(0, EFD_NONBLOCK);
684                 if (manager.target[index].event_fd == -1) {
685                         // fail to make event fd
686                         LOGE("fail to make event fd for socket (%d)\n",
687                              manager.target[index].socket);
688                         goto TARGET_CONNECT_FAIL;
689                 }
690
691                 // add event fd to epoll list
692                 ev.events = EPOLLIN;
693                 ev.data.fd = manager.target[index].event_fd;
694                 if (epoll_ctl(efd, EPOLL_CTL_ADD, manager.target[index].event_fd, &ev) < 0) {
695                         // fail to add event fd
696                         LOGE("fail to add event fd to epoll list for socket (%d)\n",
697                              manager.target[index].socket);
698                         goto TARGET_CONNECT_FAIL;
699                 }
700
701                 // make recv thread for target
702                 if (makeRecvThread(index) != 0) {
703                         // fail to make recv thread
704                         LOGE("fail to make recv thread for socket (%d)\n",
705                              manager.target[index].socket);
706                         if (0 > epoll_ctl(efd, EPOLL_CTL_DEL,
707                                           manager.target[index].event_fd, NULL))
708                                 LOGW("fail to EPOLL DEL of event fd(%d)\n", index);
709                         goto TARGET_CONNECT_FAIL;
710                 }
711
712                 if (manager.app_launch_timerfd >= 0) {
713                         LOGI("release launch timer\n");
714                         if (stop_app_launch_timer() < 0)
715                                 LOGE("cannot stop app launch timer\n");
716                 }
717
718                 LOGI("target connected = %d(running %d target)\n",
719                      manager.target[index].socket, manager.target_count + 1);
720
721                 manager.target_count++;
722                 return 0;
723         } else {
724                 // accept error
725                 LOGE("Failed to accept at target server socket\n");
726         }
727
728  TARGET_CONNECT_FAIL:
729         if (manager.target_count == 0) {
730                 // if this connection is main connection
731                 return -1;
732         } else {
733                 // if this connection is not main connection then ignore process by error
734                 setEmptyTargetSlot(index);
735                 return 1;
736         }
737 }
738
739 // return 0 if normal case
740 // return plus value if non critical error occur
741 // return minus value if critical error occur
742 static int hostServerHandler(int efd)
743 {
744         static int hostserverorder = 0;
745         int csocket;
746         struct epoll_event ev;
747
748         if (hostserverorder > 1)        // control and data socket connected already
749                 return 1;               // ignore
750
751         csocket = accept(manager.host_server_socket, NULL, NULL);
752
753         if (csocket >= 0) {
754                 // accept succeed
755                 ev.events = EPOLLIN;
756                 ev.data.fd = csocket;
757                 if (epoll_ctl(efd, EPOLL_CTL_ADD, csocket, &ev) < 0) {
758                         // consider as accept fail
759                         LOGE("Failed to add socket fd to epoll list\n");
760                         close(csocket);
761                         return -1;
762                 }
763
764                 if (hostserverorder == 0) {
765                         manager.host.control_socket = csocket;
766                         unlink_portfile();
767                         LOGI("host control socket connected = %d\n", csocket);
768                 } else {
769                         manager.host.data_socket = csocket;
770                         LOGI("host data socket connected = %d\n", csocket);
771                 }
772
773                 hostserverorder++;
774                 return 0;
775         } else {
776                 // accept error
777                 LOGE("Failed to accept from host server socket\n");
778                 return -1;
779         }
780 }
781
782 // return plus value if non critical error occur
783 // return minus value if critical error occur
784 // return -11 if socket closed
785
786 static int controlSocketHandler(int efd)
787 {
788         ssize_t recv_len;
789         struct msg_t msg_head;
790         struct msg_t *msg;
791         int res = 0;
792
793         if (manager.connect_timeout_timerfd >= 0) {
794                 LOGI("release connect timeout timer\n");
795                 if (0 > epoll_ctl(efd, EPOLL_CTL_DEL,
796                                   manager.connect_timeout_timerfd, NULL))
797                         LOGW("fail to EPOLL DEL of timeout timer fd\n");
798                 close(manager.connect_timeout_timerfd);
799                 manager.connect_timeout_timerfd = -1;
800         }
801         // Receive header
802         recv_len = recv(manager.host.control_socket,
803                         &msg_head, MSG_CMD_HDR_LEN, 0);
804         // error or close request from host
805         if (recv_len == -1 || recv_len == 0)
806                 return -11;
807         else {
808                 msg = malloc(MSG_CMD_HDR_LEN + msg_head.len);
809                 if (!msg) {
810                         LOGE("Cannot alloc msg\n");
811                         sendACKToHost(msg_head.id, ERR_WRONG_MESSAGE_FORMAT, 0, 0);
812                         return -1;
813                 }
814                 msg->id = msg_head.id;
815                 msg->len = msg_head.len;
816                 if (msg->len > 0) {
817                         // Receive payload (if exists)
818                         recv_len = recv(manager.host.control_socket,
819                                         msg->payload, msg->len, MSG_WAITALL);
820                         if (recv_len == -1)
821                                 return -11;
822                 }
823                 printBuf((char *)msg, MSG_CMD_HDR_LEN + msg->len);
824                 res = host_message_handler(msg);
825                 free(msg);
826         }
827
828         return res;
829 }
830
831 static void epoll_add_input_events()
832 {
833         struct epoll_event ev;
834         int i;
835
836         // add device fds to epoll event pool
837         ev.events = EPOLLIN;
838         for (i = 0; g_key_dev[i].fd != ARRAY_END; i++) {
839                 if (g_key_dev[i].fd >= 0) {
840                         ev.data.fd = g_key_dev[i].fd;
841                         if (epoll_ctl(manager.efd,
842                                       EPOLL_CTL_ADD, g_key_dev[i].fd, &ev) < 0
843                                       && errno != EEXIST)
844                                 LOGE("keyboard device file epoll_ctl error: %s\n", strerror(errno));
845                 }
846         }
847
848         ev.events = EPOLLIN;
849         for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++) {
850                 if (g_touch_dev[i].fd >= 0) {
851                         ev.data.fd = g_touch_dev[i].fd;
852                         if (epoll_ctl(manager.efd,
853                                       EPOLL_CTL_ADD,
854                                       g_touch_dev[i].fd, &ev) < 0
855                                       && errno != EEXIST)
856                                 LOGE("touch device file epoll_ctl error: %s\n", strerror(errno));
857                 }
858         }
859 }
860
861 static void epoll_del_input_events()
862 {
863         int i;
864
865         // remove device fds from epoll event pool
866         for (i = 0; g_key_dev[i].fd != ARRAY_END; i++)
867                 if (g_key_dev[i].fd >= 0)
868                         if (epoll_ctl(manager.efd,
869                                       EPOLL_CTL_DEL, g_key_dev[i].fd, NULL) < 0)
870                                 LOGE("keyboard device file epoll_ctl error: %s\n", strerror(errno));
871
872         for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++)
873                 if (g_touch_dev[i].fd >= 0)
874                         if (epoll_ctl(manager.efd,
875                                       EPOLL_CTL_DEL,
876                                       g_touch_dev[i].fd, NULL) < 0)
877                                 LOGE("touch device file epoll_ctl error: %s\n", strerror(errno));
878 }
879
880 static bool initialize_epoll_events(void)
881 {
882         struct epoll_event ev;
883
884         if ((manager.efd = epoll_create1(0)) < 0) {
885                 LOGE("epoll creation error\n");
886                 return false;
887         }
888         // add server sockets to epoll event pool
889         ev.events = EPOLLIN;
890         ev.data.fd = manager.host_server_socket;
891         if (epoll_ctl(manager.efd, EPOLL_CTL_ADD,
892                       manager.host_server_socket, &ev) < 0) {
893                 LOGE("Host server socket epoll_ctl error\n");
894                 return false;
895         }
896         ev.events = EPOLLIN;
897         ev.data.fd = manager.target_server_socket;
898         if (epoll_ctl(manager.efd, EPOLL_CTL_ADD,
899                       manager.target_server_socket, &ev) < 0) {
900                 LOGE("Target server socket epoll_ctl error\n");
901                 return false;
902         }
903         return true;
904 }
905
906 // return 0 for normal case
907 int daemonLoop()
908 {
909         int return_value = 0;
910         struct epoll_event *events = malloc(EPOLL_SIZE * sizeof(*events));
911
912         _get_fds(g_key_dev, INPUT_ID_KEY);
913         _get_fds(g_touch_dev, INPUT_ID_TOUCH);
914
915         if (!events) {
916                 LOGE("Out of memory when allocate epoll event pool\n");
917                 return_value = -1;
918                 goto END_EVENT;
919         }
920         if (!initialize_epoll_events()) {
921                 return_value = -1;
922                 goto END_EFD;
923         }
924
925         if (launch_timer_start() < 0) {
926                 LOGE("Launch timer start failed\n");
927                 return_value = -1;
928                 goto END_EFD;
929         }
930
931         init_prof_session(&prof_session);
932
933         // handler loop
934         while (1) {
935                 int i, k;
936                 ssize_t recvLen;
937                 // number of occured events
938                 int numevent = epoll_wait(manager.efd, events, EPOLL_SIZE, -1);
939                 if (numevent <= 0) {
940                         LOGE("Failed to epoll_wait : num of event(%d), errno(%d)\n", numevent, errno);
941                         continue;
942                 }
943
944                 for (i = 0; i < numevent; i++) {
945                         // check for request from event fd
946                         for (k = 0; k < MAX_TARGET_COUNT; k++) {
947                                 if (manager.target[k].socket != -1 &&
948                                     events[i].data.fd == manager.target[k].event_fd) {
949                                         uint64_t u;
950                                         recvLen = read(manager.target[k].event_fd, &u, sizeof(uint64_t));
951                                         if (recvLen != sizeof(uint64_t)) {
952                                                 // maybe closed, but ignoring is more safe then
953                                                 // removing fd from epoll list
954                                         } else {
955                                                 if (-11 == target_event_handler(manager.efd, k, u)) {
956                                                         LOGI("all target process is closed\n");
957                                                         continue;
958                                                 }
959                                         }
960                                         break;
961                                 }
962                         }
963
964                         if (k != MAX_TARGET_COUNT)
965                                 continue;
966
967                         // check for request from device fd
968                         for (k = 0; g_touch_dev[k].fd != ARRAY_END; k++) {
969                                 if (g_touch_dev[k].fd >= 0 &&
970                                     events[i].data.fd == g_touch_dev[k].fd) {
971                                         if (deviceEventHandler(&g_touch_dev[k],
972                                             INPUT_ID_TOUCH) < 0) {
973                                                 LOGE("Internal DA framework error, "
974                                                      "Please re-run the profiling (touch dev)\n");
975                                                 continue;
976                                         }
977                                         break;
978                                 }
979                         }
980
981                         if (g_touch_dev[k].fd != ARRAY_END)
982                                 continue;
983
984                         for (k = 0; g_key_dev[k].fd != ARRAY_END; k++) {
985                                 if (g_key_dev[k].fd >= 0 &&
986                                     events[i].data.fd == g_key_dev[k].fd) {
987                                         if (deviceEventHandler(&g_key_dev[k], INPUT_ID_KEY) < 0) {
988                                                 LOGE("Internal DA framework error, "
989                                                      "Please re-run the profiling (key dev)\n");
990                                                 continue;
991                                         }
992                                         break;
993                                 }
994                         }
995
996                         if (g_key_dev[k].fd != ARRAY_END)
997                                 continue;
998
999                         // connect request from target
1000                         if (events[i].data.fd == manager.target_server_socket) {
1001                                 if (targetServerHandler(manager.efd) < 0) {
1002                                         // critical error
1003                                         terminate_error("Internal DA framework error, "
1004                                                         "Please re-run the profiling "
1005                                                         "(targetServerHandler)\n", 1);
1006                                         continue;
1007                                 }
1008                         } else if (events[i].data.fd == manager.host_server_socket) {
1009                         // connect request from host
1010                                 int result = hostServerHandler(manager.efd);
1011                                 if (result < 0) {
1012                                         LOGE("Internal DA framework error (hostServerHandler)\n");
1013                                         continue;
1014                                 }
1015                         } else if (events[i].data.fd == manager.host.control_socket) {
1016                         // control message from host
1017                                 int result = controlSocketHandler(manager.efd);
1018                                 if (result == -11) {
1019                                         // socket close
1020                                         //if the host disconnected.
1021                                         //In all other cases daemon must report an error and continue the loop
1022                                         //close connect_timeoutt and host socket and quit
1023                                         LOGI("Connection closed. Termination. (%d)\n",
1024                                               manager.host.control_socket);
1025                                         return_value = 0;
1026                                         goto END_EFD;
1027                                 } else if (result < 0) {
1028                                         LOGE("Control socket handler.\n");
1029                                 }
1030                         } else if (events[i].data.fd == manager.host.data_socket) {
1031                                 char recvBuf[32];
1032                                 recvLen = recv(manager.host.data_socket, recvBuf, 32, MSG_DONTWAIT);
1033                                 if (recvLen == 0) {
1034                                         // close data socket
1035                                         if (0 > epoll_ctl(manager.efd,
1036                                                           EPOLL_CTL_DEL,
1037                                                           manager.host.data_socket,
1038                                                           NULL))
1039                                                 LOGW("fail to EPOLL DEL of host data socket\n");
1040                                         close(manager.host.data_socket);
1041                                         manager.host.data_socket = -1;
1042                                         // TODO: finish transfer thread
1043                                 }
1044
1045                                 LOGI("host message from data socket %d\n",
1046                                      recvLen);
1047                         } else if (events[i].data.fd == manager.app_launch_timerfd) {
1048                                 // check for application launch timerfd
1049                                 // send to host timeout error message for launching application
1050                                 LOGE("Failed to launch application\n");
1051                                 if (stop_app_launch_timer() < 0)
1052                                         LOGE("cannot stop app launch timer\n");
1053                                 continue;
1054                         } else if (events[i].data.fd == manager.connect_timeout_timerfd) {
1055                                 // check for connection timeout timerfd
1056                                 // send to host timeout error message for launching application
1057                                 terminate_error("no incoming connections", 1);
1058                                 if (0 > epoll_ctl(manager.efd, EPOLL_CTL_DEL,
1059                                                   manager.connect_timeout_timerfd,
1060                                                   NULL))
1061                                         LOGW("fail to EPOLL DEL of timeout timer fd\n");
1062                                 close(manager.connect_timeout_timerfd);
1063                                 manager.connect_timeout_timerfd = -1;
1064                                 LOGE("No connection in %d sec. shutdown.\n",
1065                                      MAX_CONNECT_TIMEOUT_TIME);
1066                                 goto END_EFD;
1067                         } else {
1068                                 // unknown socket
1069                                 // never happened
1070                                 LOGW("Unknown socket fd (%d)\n",
1071                                      events[i].data.fd);
1072                         }
1073                 }
1074         }
1075
1076  END_EFD:
1077         LOGI("close efd\n");
1078         close(manager.efd);
1079  END_EVENT:
1080         free(events);
1081         return return_value;
1082 }