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);
230 static void *samplingThread(void *data)
233 sigset_t waitsigmask;
235 LOGI("sampling thread started\n");
237 sigemptyset(&waitsigmask);
238 sigaddset(&waitsigmask, SIGALRM);
239 sigaddset(&waitsigmask, SIGUSR1);
242 err = sigwait(&waitsigmask, &signo);
244 LOGE("Failed to sigwait() in sampling thread\n");
248 if (signo == SIGALRM) {
249 struct system_info_t sys_info;
250 struct msg_data_t *msg;
252 if (get_system_info(&sys_info) == -1) {
253 LOGE("Cannot get system info\n");
254 //do not send sys_info because
259 msg = pack_system_info(&sys_info);
261 LOGE("Cannot pack system info\n");
262 reset_system_info(&sys_info);
268 printBuf((char *)msg, MSG_DATA_HDR_LEN + msg->len);
271 reset_system_info(&sys_info);
274 else if(signo == SIGUSR1)
276 LOGI("SIGUSR1 catched\n");
283 LOGE("This should never happen in sampling thread\n");
287 LOGI("sampling thread ended\n");
291 // return 0 if normal case
292 // return minus value if critical error
293 // return plus value if non-critical error
294 int samplingStart(void)
296 struct itimerval timerval;
297 time_t sec = prof_session.conf.system_trace_period / 1000;
298 suseconds_t usec = prof_session.conf.system_trace_period * 1000 %
301 if(manager.sampling_thread != -1) // already started
304 if (check_running_status(&prof_session) == 0) {
305 LOGI("try to start sampling when running_status is 0\n");
309 if(pthread_create(&(manager.sampling_thread), NULL, samplingThread, NULL) < 0)
311 LOGE("Failed to create sampling thread\n");
315 timerval.it_interval.tv_sec = sec;
316 timerval.it_interval.tv_usec = usec;
317 timerval.it_value.tv_sec = sec;
318 timerval.it_value.tv_usec = usec;
319 setitimer(ITIMER_REAL, &timerval, NULL);
324 int samplingStop(void)
326 if(manager.sampling_thread != -1)
328 struct itimerval stopval;
331 stopval.it_interval.tv_sec = 0;
332 stopval.it_interval.tv_usec = 0;
333 stopval.it_value.tv_sec = 0;
334 stopval.it_value.tv_usec = 0;
335 setitimer(ITIMER_REAL, &stopval, NULL);
337 pthread_kill(manager.sampling_thread, SIGUSR1);
338 LOGI("join sampling thread started\n");
339 pthread_join(manager.sampling_thread, NULL);
340 LOGI("join sampling thread done\n");
342 manager.sampling_thread = -1;
348 static useconds_t time_diff_us(struct timeval *tv1, struct timeval *tv2)
350 return (tv1->tv_sec - tv2->tv_sec) * 1000000 +
351 ((int)tv1->tv_usec - (int)tv2->tv_usec);
354 static void *replay_thread(void *arg)
356 struct replay_event_seq_t *event_seq = (struct replay_event_seq_t *)arg;
359 useconds_t prev_event_offset = 0;
361 struct replay_event_t * pevent = NULL;
363 LOGI_th_rep("replay events thread started\n");
364 if (event_seq->event_num != 0)
366 pevent = event_seq->events;
369 for (i = 0; i < event_seq->event_num; i++) {
370 useconds_t event_offset = time_diff_us(&pevent->ev.time, &event_seq->tv);
371 if (event_offset >= prev_event_offset)
372 ms = event_offset - prev_event_offset;
376 #ifdef THREAD_REPLAY_DEBUG
377 print_replay_event(pevent, i + 1, "\t");
379 LOGI_th_rep("%d) sleep %d\n", i, ms);
382 write_input_event(pevent->id, &pevent->ev);
384 prev_event_offset = event_offset;
389 LOGI("replay events thread finished\n");
396 if (manager.replay_thread != -1) // already started
399 if (pthread_create(&(manager.replay_thread),
402 &prof_session.replay_event_seq) < 0)
404 LOGE("Failed to create replay thread\n");
413 if (manager.replay_thread == -1) {
414 LOGI("replay thread not running\n");
417 LOGI("stopping replay thread\n");
418 pthread_cancel(manager.replay_thread);
419 pthread_join(manager.replay_thread, NULL);
420 manager.replay_thread = -1;
421 reset_replay_event_seq(&prof_session.replay_event_seq);
422 LOGI("replay thread joined\n");