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 #include "input_events.h"
54 static void* recvThread(void* data)
56 struct target *target = data;
59 struct msg_target_t log;
62 // initialize target variable
66 err = target_recv_msg(target, &log);
70 write(target->event_fd, &event, sizeof(event));
74 if (IS_PROBE_MSG(log.type)) {
75 struct msg_data_t *msg_data = (struct msg_data_t *)&log;
77 if (write_to_buf(msg_data) != 0)
78 LOGE("write to buf fail\n");
83 log.data[log.length] = '\0';
84 if(log.type == MSG_ALLOC)
86 target->allocmem = str_to_int64(log.data);
87 continue; // don't send to host
89 else if(log.type == MSG_PID)
91 LOGI("MSG_PID arrived (pid ppid): %s\n", log.data);
93 // only when first MSG_PID is arrived
94 if (target_get_pid(target) == UNKNOWN_PID) {
98 n = sscanf(log.data, "%d %d", &pid, &ppid);
102 * TODO: complain to host about wrong
103 * pid message send stop message to
107 write(target->event_fd, &event,
112 /* set pid and ppid */
113 target_set_pid(target, pid);
114 target_set_ppid(target, ppid);
118 write(target->event_fd, &event, sizeof(uint64_t));
120 send_maps_inst_msg_to(target);
121 continue; // don't send to host
123 else if(log.type == MSG_TERMINATE)
125 LOGI("MSG_TERMINATE arrived: pid[%d]\n",
126 target_get_pid(target));
128 // send stop message to main thread
130 write(target->event_fd, &event,
134 } else if (log.type == MSG_MSG) {
135 // don't send to host
136 LOGI("EXTRA '%s'\n", log.data);
138 } else if (log.type == MSG_ERROR) {
139 // don't send to host
140 LOGE("EXTRA '%s'\n", log.data);
142 } else if (log.type == MSG_WARNING) {
143 // don't send to host
144 LOGW("EXTRA '%s'\n", log.data);
147 #ifdef PRINT_TARGET_LOG
148 else if(log.type == MSG_LOG)
152 case '2': // UI control creation log
153 case '3': // UI event log
154 case '6': // UI lifecycle log
155 case '7': // screenshot log
156 case '8': // scene transition log
157 LOGI("%dclass|%s\n", log.data[0] - '0', log.data);
163 else if(log.type == MSG_IMAGE)
165 LOGI("MSG_IMAGE received\n");
167 else // not MSG_LOG and not MSG_IMAGE
169 LOGI("Extra MSG TYPE (%d|%d|%s)\n", log.type, log.length, log.data);
173 // do not send any message to host until MSG_PID message arrives
174 if(unlikely(pass == 0))
176 while(target->initial_log == 0)
184 target->recv_thread = -1;
188 int makeRecvThread(struct target *target)
190 if (target_start(target, recvThread) < 0) {
191 LOGE("Failed to create recv thread\n");
198 static void *samplingThread(void *data)
201 sigset_t waitsigmask;
203 LOGI("sampling thread started\n");
205 sigemptyset(&waitsigmask);
206 sigaddset(&waitsigmask, SIGALRM);
207 sigaddset(&waitsigmask, SIGUSR1);
210 err = sigwait(&waitsigmask, &signo);
212 LOGE("Failed to sigwait() in sampling thread\n");
216 if (signo == SIGALRM) {
217 struct system_info_t sys_info;
218 struct msg_data_t *msg;
220 if (get_system_info(&sys_info) == -1) {
221 LOGE("Cannot get system info\n");
222 //do not send sys_info because
227 msg = pack_system_info(&sys_info);
229 LOGE("Cannot pack system info\n");
230 reset_system_info(&sys_info);
234 if (write_to_buf(msg) != 0)
235 LOGE("write to buf fail\n");
237 #ifdef THREAD_SAMPLING_DEBUG
238 printBuf((char *)msg, MSG_DATA_HDR_LEN + msg->len);
242 reset_system_info(&sys_info);
245 else if(signo == SIGUSR1)
247 LOGI("SIGUSR1 catched\n");
254 LOGE("This should never happen in sampling thread\n");
258 LOGI("sampling thread ended\n");
262 // return 0 if normal case
263 // return minus value if critical error
264 // return plus value if non-critical error
265 int samplingStart(void)
267 struct itimerval timerval;
268 time_t sec = prof_session.conf.system_trace_period / 1000;
269 suseconds_t usec = prof_session.conf.system_trace_period * 1000 %
272 if(manager.sampling_thread != -1) // already started
275 if (check_running_status(&prof_session) == 0) {
276 LOGI("try to start sampling when running_status is 0\n");
280 if(pthread_create(&(manager.sampling_thread), NULL, samplingThread, NULL) < 0)
282 LOGE("Failed to create sampling thread\n");
286 timerval.it_interval.tv_sec = sec;
287 timerval.it_interval.tv_usec = usec;
288 timerval.it_value.tv_sec = sec;
289 timerval.it_value.tv_usec = usec;
290 setitimer(ITIMER_REAL, &timerval, NULL);
295 int samplingStop(void)
297 if(manager.sampling_thread != -1)
299 struct itimerval stopval;
302 stopval.it_interval.tv_sec = 0;
303 stopval.it_interval.tv_usec = 0;
304 stopval.it_value.tv_sec = 0;
305 stopval.it_value.tv_usec = 0;
306 setitimer(ITIMER_REAL, &stopval, NULL);
308 pthread_kill(manager.sampling_thread, SIGUSR1);
309 LOGI("join sampling thread started\n");
310 pthread_join(manager.sampling_thread, NULL);
311 LOGI("join sampling thread done\n");
313 manager.sampling_thread = -1;
319 static useconds_t time_diff_us(struct timeval *tv1, struct timeval *tv2)
321 return (tv1->tv_sec - tv2->tv_sec) * 1000000 +
322 ((int)tv1->tv_usec - (int)tv2->tv_usec);
325 static void *replay_thread(void *arg)
327 struct replay_event_seq_t *event_seq = (struct replay_event_seq_t *)arg;
330 useconds_t prev_event_offset = 0;
332 struct replay_event_t * pevent = NULL;
334 LOGI_th_rep("replay events thread started\n");
335 if (event_seq->event_num != 0)
337 pevent = event_seq->events;
340 for (i = 0; i < event_seq->event_num; i++) {
341 useconds_t event_offset = time_diff_us(&pevent->ev.time, &event_seq->tv);
342 if (event_offset >= prev_event_offset)
343 ms = event_offset - prev_event_offset;
347 #ifdef THREAD_REPLAY_DEBUG
348 print_replay_event(pevent, i + 1, "\t");
350 LOGI_th_rep("%d) sleep %d\n", i, ms);
353 write_input_event(pevent->id, &pevent->ev);
355 prev_event_offset = event_offset;
360 LOGI("replay events thread finished\n");
367 if (manager.replay_thread != -1) // already started
370 if (pthread_create(&(manager.replay_thread),
373 &prof_session.replay_event_seq) < 0)
375 LOGE("Failed to create replay thread\n");
384 if (manager.replay_thread == -1) {
385 LOGI("replay thread not running\n");
388 LOGI("stopping replay thread\n");
389 pthread_cancel(manager.replay_thread);
390 pthread_join(manager.replay_thread, NULL);
391 manager.replay_thread = -1;
392 reset_replay_event_seq(&prof_session.replay_event_seq);
393 LOGI("replay thread joined\n");