4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
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>
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
18 * http://www.apache.org/licenses/LICENSE-2.0
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.
28 * - Samsung RnD Institute Russia
34 #include <stdlib.h> // for atoi, atol
35 #include <string.h> // for strchr
36 #include <stdint.h> // for uint64_t
37 #include <sys/types.h> // for recv
38 #include <sys/socket.h> // for recv
39 #include <sys/time.h> // for setitimer
40 #include <signal.h> // for sigemptyset, sigset_t, sigaddset, ...
41 #include <unistd.h> // for write
47 #include "da_protocol.h"
51 #include "input_events.h"
53 static void* recvThread(void* data)
55 __da_target_info *target = data;
61 // initialize target variable
67 // read from target process
68 recvLen = recv(target->socket, &log,
69 sizeof(log.type) + sizeof(log.length),
72 if(unlikely(recvLen < sizeof(log.type) + sizeof(log.length)))
75 write(target->event_fd, &event, sizeof(uint64_t));
78 if (IS_PROBE_MSG(log.type)) {
79 struct msg_data_t tmp_msg;
80 int offs = sizeof(log.type) + sizeof(log.length);
82 recvLen = recv(target->socket,
84 MSG_DATA_HDR_LEN - offs,
86 memcpy(&tmp_msg, &log, MSG_DATA_HDR_LEN);
87 struct msg_data_t *msg = malloc(MSG_DATA_HDR_LEN +
89 memcpy(msg, &tmp_msg, MSG_DATA_HDR_LEN);
90 recvLen = recv(target->socket,
91 (char *)msg + MSG_DATA_HDR_LEN,
92 msg->len, MSG_WAITALL);
99 if (likely(log.length > 0))
101 recvLen = recv(target->socket, log.data, log.length,
103 if(unlikely((recvLen == -1) || (recvLen != log.length))) // consume as disconnect
106 write(target->event_fd, &event, sizeof(uint64_t));
111 log.data[log.length] = '\0';
112 if(log.type == MSG_ALLOC)
114 target->allocmem = str_to_int64(log.data);
115 continue; // don't send to host
117 else if(log.type == MSG_PID)
119 LOGI("MSG_PID arrived : %s\n", log.data);
121 // only when first MSG_PID is arrived
122 if(target->pid == -1)
125 barloc = strchr(log.data, '|');
129 * TODO: complain to host about wrong
130 * pid message send stop message to
134 write(target->event_fd, &event,
141 target->pid = atoi(log.data);
143 write(target->event_fd, &event, sizeof(uint64_t));
145 continue; // don't send to host
147 else if(log.type == MSG_TERMINATE)
149 // send stop message to main thread
151 write(target->event_fd, &event,
154 struct msg_data_t *msg = malloc(sizeof(*msg) + /* pid */
156 fill_data_msg_head(msg, NMSG_TERMINATE, 0,
158 *(uint32_t *) msg->payload = (uint32_t) target->pid;
162 } else if (log.type == MSG_MSG) {
163 // don't send to host
164 LOGI("EXTRA MSG(%u) len=%u data='%s'\n", log.type,
165 log.length, log.data);
167 } else if (log.type == MSG_ERROR) {
168 // don't send to host
169 LOGE("EXTRA MSG(%u) len=%u data='%s'\n", log.type,
170 log.length, log.data);
173 #ifdef PRINT_TARGET_LOG
174 else if(log.type == MSG_LOG)
178 case '2': // UI control creation log
179 case '3': // UI event log
180 case '6': // UI lifecycle log
181 case '7': // screenshot log
182 case '8': // scene transition log
183 LOGI("%dclass|%s\n", log.data[0] - '0', log.data);
189 else if(log.type == MSG_IMAGE)
191 LOGI("MSG_IMAGE received\n");
193 else // not MSG_LOG and not MSG_IMAGE
195 LOGI("Extra MSG TYPE (%d|%d|%s)\n", log.type, log.length, log.data);
199 // do not send any message to host until MSG_PID message arrives
200 if(unlikely(pass == 0))
202 while(target->initial_log == 0)
210 target->recv_thread = -1;
214 int makeRecvThread(int index)
216 if (manager.target[index].socket == -1)
219 if (pthread_create(&(manager.target[index].recv_thread),
220 NULL, recvThread, &manager.target[index]) < 0)
222 LOGE("Failed to create recv thread for socket (%d)\n",
223 manager.target[index].socket);
231 void* samplingThread(void* data)
234 sigset_t waitsigmask;
236 LOGI("sampling thread started\n");
238 sigemptyset(&waitsigmask);
239 sigaddset(&waitsigmask, SIGALRM);
240 sigaddset(&waitsigmask, SIGUSR1);
243 err = sigwait(&waitsigmask, &signo);
245 LOGE("Failed to sigwait() in sampling thread\n");
249 if (signo == SIGALRM) {
250 struct system_info_t sys_info;
251 struct msg_data_t *msg;
253 if (get_system_info(&sys_info) == -1) {
254 LOGE("Cannot get system info\n");
255 //do not send sys_info because
260 msg = pack_system_info(&sys_info);
262 LOGE("Cannot pack system info\n");
263 reset_system_info(&sys_info);
269 printBuf((char *)msg, MSG_DATA_HDR_LEN + msg->len);
272 reset_system_info(&sys_info);
275 else if(signo == SIGUSR1)
277 LOGI("SIGUSR1 catched\n");
284 LOGE("This should never happen in sampling thread\n");
288 LOGI("sampling thread ended\n");
292 // return 0 if normal case
293 // return minus value if critical error
294 // return plus value if non-critical error
295 int samplingStart(void)
297 struct itimerval timerval;
298 time_t sec = prof_session.conf.system_trace_period / 1000;
299 suseconds_t usec = prof_session.conf.system_trace_period * 1000 %
302 if(manager.sampling_thread != -1) // already started
305 if (check_running_status(&prof_session) == 0) {
306 LOGI("try to start sampling when running_status is 0\n");
310 if(pthread_create(&(manager.sampling_thread), NULL, samplingThread, NULL) < 0)
312 LOGE("Failed to create sampling thread\n");
316 timerval.it_interval.tv_sec = sec;
317 timerval.it_interval.tv_usec = usec;
318 timerval.it_value.tv_sec = sec;
319 timerval.it_value.tv_usec = usec;
320 setitimer(ITIMER_REAL, &timerval, NULL);
325 int samplingStop(void)
327 if(manager.sampling_thread != -1)
329 struct itimerval stopval;
332 stopval.it_interval.tv_sec = 0;
333 stopval.it_interval.tv_usec = 0;
334 stopval.it_value.tv_sec = 0;
335 stopval.it_value.tv_usec = 0;
336 setitimer(ITIMER_REAL, &stopval, NULL);
338 pthread_kill(manager.sampling_thread, SIGUSR1);
339 LOGI("join sampling thread started\n");
340 pthread_join(manager.sampling_thread, NULL);
341 LOGI("join sampling thread done\n");
343 manager.sampling_thread = -1;
349 static useconds_t time_diff_us(struct timeval *tv1, struct timeval *tv2)
351 return (tv1->tv_sec - tv2->tv_sec) * 1000000 +
352 ((int)tv1->tv_usec - (int)tv2->tv_usec);
355 static void *replay_thread(void *arg)
357 struct replay_event_seq_t *event_seq = (struct replay_event_seq_t *)arg;
360 useconds_t prev_event_offset = 0;
362 struct replay_event_t * pevent = NULL;
364 LOGI_th_rep("replay events thread started\n");
365 if (event_seq->event_num != 0)
367 pevent = event_seq->events;
370 for (i = 0; i < event_seq->event_num; i++) {
371 useconds_t event_offset = time_diff_us(&pevent->ev.time, &event_seq->tv);
372 if (event_offset >= prev_event_offset)
373 ms = event_offset - prev_event_offset;
377 #ifdef THREAD_REPLAY_DEBUG
378 print_replay_event(pevent, i + 1, "\t");
380 LOGI_th_rep("%d) sleep %d\n", i, ms);
383 write_input_event(pevent->id, &pevent->ev);
385 prev_event_offset = event_offset;
390 LOGI("replay events thread finished\n");
397 if (manager.replay_thread != -1) // already started
400 if (pthread_create(&(manager.replay_thread),
403 &prof_session.replay_event_seq) < 0)
405 LOGE("Failed to create replay thread\n");
414 if (manager.replay_thread == -1) {
415 LOGI("replay thread not running\n");
418 LOGI("stopping replay thread\n");
419 pthread_cancel(manager.replay_thread);
420 pthread_join(manager.replay_thread, NULL);
421 manager.replay_thread = -1;
422 reset_replay_event_seq(&prof_session.replay_event_seq);
423 LOGI("replay thread joined\n");