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"
52 static void* recvThread(void* data)
54 int index = (int)data;
60 // initialize target variable
61 manager.target[index].pid = -1;
62 manager.target[index].allocmem = 0;
66 // read from target process
67 recvLen = recv(manager.target[index].socket, &log,
68 sizeof(log.type) + sizeof(log.length), MSG_WAITALL);
70 if(unlikely(recvLen < sizeof(log.type) + sizeof(log.length)))
73 write(manager.target[index].event_fd, &event, sizeof(uint64_t));
76 if (IS_PROBE_MSG(log.type)) {
77 struct msg_data_t tmp_msg;
78 int offs = sizeof(log.type) + sizeof(log.length);
79 recvLen = recv(manager.target[index].socket,
81 MSG_DATA_HDR_LEN - offs,
83 memcpy(&tmp_msg, &log, MSG_DATA_HDR_LEN);
84 struct msg_data_t *msg = malloc(MSG_DATA_HDR_LEN +
86 memcpy(msg, &tmp_msg, MSG_DATA_HDR_LEN);
87 recvLen = recv(manager.target[index].socket,
88 (char *)msg + MSG_DATA_HDR_LEN,
89 msg->len, MSG_WAITALL);
96 if (likely(log.length > 0))
98 recvLen = recv(manager.target[index].socket,
99 log.data, log.length, MSG_WAITALL);
100 if(unlikely((recvLen == -1) || (recvLen != log.length))) // consume as disconnect
103 write(manager.target[index].event_fd, &event, sizeof(uint64_t));
108 log.data[log.length] = '\0';
109 if(log.type == MSG_ALLOC)
111 manager.target[index].allocmem = str_to_int64(log.data);
112 continue; // don't send to host
114 else if(log.type == MSG_PID)
116 LOGI("MSG_PID arrived : %s\n", log.data);
118 // only when first MSG_PID is arrived
119 if(manager.target[index].pid == -1)
122 barloc = strchr(log.data, '|');
125 // TODO: complain to host about wrong pid message
126 // send stop message to main thread
128 write(manager.target[index].event_fd, &event, sizeof(uint64_t));
134 manager.target[index].pid = atoi(log.data);
136 write(manager.target[index].event_fd, &event, sizeof(uint64_t));
138 continue; // don't send to host
140 else if(log.type == MSG_TERMINATE)
142 // send stop message to main thread
144 write(manager.target[index].event_fd, &event,
147 struct msg_data_t *msg = malloc(sizeof(*msg) + /* pid */
149 fill_data_msg_head(msg, NMSG_TERMINATE, 0,
151 *(uint32_t *) msg->payload = (uint32_t) manager.target[index].pid;
156 else if(log.type == MSG_MSG)
158 // don't send to host
159 LOGI("EXTRA MSG type=%d;len=%d;data='%s'\n", log.type, log.length, log.data);
162 #ifdef PRINT_TARGET_LOG
163 else if(log.type == MSG_LOG)
167 case '2': // UI control creation log
168 case '3': // UI event log
169 case '6': // UI lifecycle log
170 case '7': // screenshot log
171 case '8': // scene transition log
172 LOGI("%dclass|%s\n", log.data[0] - '0', log.data);
178 else if(log.type == MSG_IMAGE)
180 LOGI("MSG_IMAGE received\n");
182 else // not MSG_LOG and not MSG_IMAGE
184 LOGI("Extra MSG TYPE (%d|%d|%s)\n", log.type, log.length, log.data);
188 // do not send any message to host until MSG_PID message arrives
189 if(unlikely(pass == 0))
191 while(manager.target[index].initial_log == 0)
199 manager.target[index].recv_thread = -1;
203 int makeRecvThread(int index)
205 if (manager.target[index].socket == -1)
208 if (pthread_create(&(manager.target[index].recv_thread),
209 NULL, recvThread, (void*)index) < 0)
211 LOGE("Failed to create recv thread for socket (%d)\n",
212 manager.target[index].socket);
220 void* samplingThread(void* data)
223 sigset_t waitsigmask;
225 LOGI("sampling thread started\n");
227 sigemptyset(&waitsigmask);
228 sigaddset(&waitsigmask, SIGALRM);
229 sigaddset(&waitsigmask, SIGUSR1);
232 err = sigwait(&waitsigmask, &signo);
234 LOGE("Failed to sigwait() in sampling thread\n");
238 if (signo == SIGALRM) {
239 int pidarr[MAX_TARGET_COUNT];
241 struct system_info_t sys_info;
242 struct msg_data_t *msg;
244 if (IS_SYSTEM_INFO_NEEDED()) {
245 for (i = 0; i < MAX_TARGET_COUNT; i++) {
246 if (manager.target[i].socket != -1 &&
247 manager.target[i].pid != -1)
248 pidarr[pidcount++] = manager.target[i].pid;
251 if (get_system_info(&sys_info, pidarr, pidcount) == -1) {
252 LOGE("Cannot get system info\n");
253 //do not send sys_info because
258 msg = pack_system_info(&sys_info);
260 LOGE("Cannot pack system info\n");
261 reset_system_info(&sys_info);
267 printBuf((char *)msg, MSG_DATA_HDR_LEN + msg->len);
270 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
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);
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 /* filter touch and key events here
383 and process them separately */
387 LOGI_th_rep("event -> %s\n", INPUT_ID_STR_TOUCH);
388 _device_write(g_touch_dev, &pevent->ev);
392 LOGI_th_rep("event -> %s\n", INPUT_ID_STR_KEY);
393 _device_write(g_key_dev, &pevent->ev);
396 LOGE("event -> UNKNOWN INPUT ID");
399 prev_event_offset = event_offset;
404 LOGI("replay events thread finished\n");
411 if (manager.replay_thread != -1) // already started
414 if (pthread_create(&(manager.replay_thread),
417 &prof_session.replay_event_seq) < 0)
419 LOGE("Failed to create replay thread\n");
428 if (manager.replay_thread == -1) {
429 LOGI("replay thread not running\n");
432 LOGI("stopping replay thread\n");
433 pthread_cancel(manager.replay_thread);
434 pthread_join(manager.replay_thread, NULL);
435 manager.replay_thread = -1;
436 reset_replay_event_seq(&prof_session.replay_event_seq);
437 LOGI("replay thread joined\n");