2 * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 ///////////////////////////////////////////////////////////////////////////////
18 /// \ingroup tag_NS_InterfaceunifiedLogCapture
19 /// \brief This file contains the standard set functions called by the NS
20 // dispatcher on application initialization, cleanup and wakeup.
22 ///////////////////////////////////////////////////////////////////////////////
28 #include <sys/types.h>
30 #include <sys/param.h>
37 #include <loggerservicedebug_loggerservicelog.h>
38 #include <native_service/frameworkunified_multithreading.h>
39 #include <system_service/ss_system_manager_if.h>
40 #include <system_service/ss_system_manager_notifications.h>
41 #include <native_service/frameworkunified_timer.h>
42 #include <system_service/ss_devicedetection_service_notifications.h>
43 #include <system_service/ss_devicedetection_service.h>
44 #include <system_service/ss_devicedetection_service_protocol.h>
45 #include <system_service/ss_devicedetection_service_ifc.h>
46 #include <native_service/frameworkunified_application.h>
47 #include <native_service/frameworkunified_framework_if.h>
48 #include <native_service/frameworkunified_service_protocol.h>
49 #include <native_service/frameworkunified_types.h>
54 #ifndef TN_LOGGERRTIME
55 #define TN_LOGGERRTIME "LoggerRtime"
56 #define PR_LOGGERRTIME_S PR_TSS_S
57 #define PR_LOGGERRTIME PR_TSS
58 #endif // TN_LOGGERRTIME
60 #define USB_REALTIME_MSGMAX 256
61 #define USB_REALTIME_SIZMAX 4096
62 #define USB_REALTIME_QNAME "/PlRtLogger"
64 #define USB_RT_FOLDERPATH_ "/REALTIME_"
67 #define USB_RT_TMP_PATH "/tmp"
69 #define USB_RT_LOGNAME_TMP "usbrt_tmp.log"
70 #define ENC_BUF_MAX_SIZE (1024*8)
74 #define DEV_ENC_EXTENSION ".enc1"
75 #define REL_ENC_EXTENSION ".enc2"
76 #define ALIGNMENT_SIZE 4
77 #endif // RELEASE_BUILD
80 #define USB_RT_LOGNAME_ "loggerservice_usb__realtime"
81 // Max size of each log file
82 #define USB_RT_FILE_SIZE (1024*1024)
83 // Num of logs to write in std::queue at one time
84 #define QUELOG_WRITE_BLOCK_NUM 300
85 // Max of logs to save in std::queue
86 #define QUELOG_SAVE_MAX 12000
87 #define QUELOG_DELNUM (QUELOG_WRITE_BLOCK_NUM*2) // num of deletion at one time
89 #define USB_RT_TIMER_EV 0x89
90 #define USB_RT_TIMER_SYNC 1 // kind
91 #define USB_RT_TIMER_CYCLE 10000 // cycle of timeout(msec)
93 static HANDLE g_rt_tid = NULL;
94 static int g_wfd = -1;
95 static mqd_t g_qid = (mqd_t) - 1;
96 static int g_num_of_file = 1;
97 static char g_mnt_path[MAXPATHLEN];
98 static char g_fld_path[MAXPATHLEN];
99 static char g_log_path[MAXPATHLEN];
100 static char *g_log_name;
101 static bool g_need_sync = false;
102 static size_t g_filesize = 0;
104 //static queue<string> g_saveq;
105 static std::queue<std::string> g_saveq;
107 static DeviceDetectionServiceIf g_devDetect;
108 static bool g_usb_available = false;
110 static char g_log_tmp_path[MAXPATHLEN];
112 EFrameworkunifiedStatus rtUsbLogThread(HANDLE hApp);
113 EFrameworkunifiedStatus rtUsbLogTShutdown(HANDLE hApp);
114 EFrameworkunifiedStatus OnPowerOnOffNotification(HANDLE hApp);
116 EFrameworkunifiedStatus StartTimer(HANDLE hApp, const UI_32 timeout);
117 EFrameworkunifiedStatus CancelTimer(void);
119 // DeviceDetection Related funcs
120 EFrameworkunifiedStatus OnDeviceDetectionAvailability(HANDLE hApp);
121 EFrameworkunifiedStatus OnDeviceDetectionOpenSessionACK(HANDLE hApp);
122 EFrameworkunifiedStatus onDeviceDetectionCloseSessionACK(HANDLE hApp);
123 EFrameworkunifiedStatus onUsbDetectCallback(HANDLE hApp);
125 EFrameworkunifiedStatus EncryptAndCopyFile(void);
127 EFrameworkunifiedStatus StartRtUsbLogThread(HANDLE hApp) {
128 FrameworkunifiedChildThreadAttr attr;
129 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
131 if (g_rt_tid != NULL) {
132 return eFrameworkunifiedStatusOK;
135 // Create Realtime USB Logging Thread and start
136 memset(&attr, 0, sizeof(FrameworkunifiedChildThreadAttr));
137 // One time while to break on Error
138 if (eFrameworkunifiedStatusOK
139 != (l_eStatus = FrameworkunifiedCreateChildThreadAttrSetSched(&attr,
140 eFrameworkunifiedSchedPolicyTSS,
144 g_rt_tid = FrameworkunifiedCreateChildThreadWithAttribute(hApp, TN_LOGGERRTIME,
146 rtUsbLogTShutdown, &attr);
147 if (g_rt_tid == NULL) {
148 l_eStatus = eFrameworkunifiedStatusFail;
150 l_eStatus = FrameworkunifiedStartChildThread(hApp, g_rt_tid, 0, (PVOID) NULL);
156 EFrameworkunifiedStatus StopRtUsbLogThread(HANDLE hApp) {
157 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
161 if (0 != close(g_wfd)) {
162 l_eStatus = eFrameworkunifiedStatusFail;
164 EncryptAndCopyFile();
166 // Close message queue
167 if (g_qid != (mqd_t) - 1) {
168 if (0 != mq_close(g_qid)) {
169 l_eStatus = eFrameworkunifiedStatusFail;
173 if (eFrameworkunifiedStatusOK != FrameworkunifiedStopChildThread(hApp, g_rt_tid, 0, NULL)) {
174 l_eStatus = eFrameworkunifiedStatusFail;
176 if (eFrameworkunifiedStatusOK != FrameworkunifiedDestroyChildThread(hApp, g_rt_tid)) {
177 l_eStatus = eFrameworkunifiedStatusFail;
183 EFrameworkunifiedStatus OnPowerOnOffNotification(HANDLE hApp) {
184 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
185 T_SS_SM_UserModeOnOffNotification_StructType onoff_mode;
187 l_eStatus = FrameworkunifiedGetMsgDataOfSize(hApp, (PVOID) &onoff_mode,
189 if (eFrameworkunifiedStatusOK != l_eStatus) {
190 fprintf(stderr, "%s: Failed to fetch OnOff Mode\n", __FUNCTION__);
193 if (!onoff_mode.isUserModeOn) { // ACC-OFF
197 if (0 != close(g_wfd)) {
198 l_eStatus = eFrameworkunifiedStatusFail;
200 EncryptAndCopyFile();
201 g_wfd = -2; // ACC-OFF detected
207 static int getStartFileNum(void) {
214 if ((dirp = opendir(g_fld_path)) == NULL) {
215 fprintf(stderr, "%s: Failed in opendir, errno=%d\n", __FUNCTION__, errno);
219 if (readdir_r(dirp, &entry, &next) != 0) {
220 fprintf(stderr, "%s: Failed in readdir_r, errno=%d\n", __FUNCTION__,
225 if (next == NULL) { // NO more
228 if (strncmp(entry.d_name, g_log_name, strlen(g_log_name)) != 0) {
231 num = atoi(entry.d_name + strlen(g_log_name));
242 EFrameworkunifiedStatus WriteAndSwitchLogFile(const char* data, ssize_t size) {
244 char logpath[MAXPATHLEN];
246 wrotelen = write(g_wfd, data, size);
247 if (wrotelen != size) {
251 EncryptAndCopyFile();
252 fprintf(stderr, "%s: Failed to write, size=%d, wrotelen=%d, errno=%d\n",
254 // __FUNCTION__, static_cast<int32_t>size, static_cast<int32_t>wrotelen, errno);
255 __FUNCTION__, static_cast<int32_t>(size), static_cast<int32_t>(wrotelen), errno);
257 return eFrameworkunifiedStatusFail;
259 g_filesize += wrotelen;
261 if (static_cast<int>(g_filesize) >= USB_RT_FILE_SIZE) {
264 EncryptAndCopyFile();
268 // snprintf(logpath, "%s/%s", g_log_tmp_path, USB_RT_LOGNAME_TMP);
269 snprintf(logpath, MAXPATHLEN, "%s/%s", g_log_tmp_path, USB_RT_LOGNAME_TMP);
271 if ((g_wfd = open(logpath, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0644))
273 fprintf(stderr, "%s: Failed to open file %s, errno=%d\n", __FUNCTION__,
275 return eFrameworkunifiedStatusFail;
279 return eFrameworkunifiedStatusOK;
282 EFrameworkunifiedStatus OnMessageQueueReceived(HANDLE hApp) {
284 char msg[USB_REALTIME_SIZMAX], msg2[USB_REALTIME_SIZMAX];
285 char logpath[MAXPATHLEN];
290 std::string work_str;
293 const struct timespec tspec = { 0, 0 };
298 if (g_qid == (mqd_t) - 1) { // Already ACC-OFFed
299 return eFrameworkunifiedStatusOK;
301 len = mq_timedreceive(g_qid, msg, sizeof(msg), &prior, &tspec);
302 if (len == (ssize_t) - 1) { // NO more data
303 if (errno != ETIMEDOUT) {
304 fprintf(stderr, "%s: Unexpected error %d\n", __FUNCTION__, errno);
308 // Remove overflowed log
309 if (g_saveq.size() > QUELOG_SAVE_MAX) {
310 int delnum = g_saveq.size() - QUELOG_SAVE_MAX + QUELOG_DELNUM;
311 for (int i = 0; i < delnum; i++) {
315 // check if file is opened
318 * Make folder and open log file
322 // g_saveq.push(string((const char*) msg, len));
323 g_saveq.push(std::string((const char*) msg, len));
325 pushed = true; // request pushed or NON-log message -> NO NEED to write this data to log file
327 if (!g_usb_available) {
328 // No mount event is received
332 if (stat(g_mnt_path, &stbuf) != 0) {
333 // No mount path found
336 // Check and make subfolder
337 int mkdres = mkdir(g_fld_path, 0666);
340 } else if (mkdres == -1 && errno == EEXIST) {
341 // Decide file number to start(Check current log files)
342 g_num_of_file = getStartFileNum();
343 if (g_num_of_file <= 0) {
344 fprintf(stderr, "%s: Failed in getStartFileNum\n", __FUNCTION__);
348 fprintf(stderr, "%s: Failed to mkdir %s, errno=%d\n", __FUNCTION__,
357 // snprintf(logpath, "%s/%s", g_log_tmp_path, USB_RT_LOGNAME_TMP);
358 snprintf(logpath, MAXPATHLEN, "%s/%s", g_log_tmp_path, USB_RT_LOGNAME_TMP);
360 if ((g_wfd = open(logpath, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0644))
362 fprintf(stderr, "%s: Failed to open file %s, errno=%d\n", __FUNCTION__,
366 } else if (g_wfd == -2) {
367 // Already ACC-OFF, Just throw the logs away
370 // Write out saved log if any
371 int written_once = QUELOG_WRITE_BLOCK_NUM; // num of written at once
373 if (g_saveq.empty()) {
376 if (written_once >= QUELOG_WRITE_BLOCK_NUM) {
379 // read request queue
380 len2 = mq_timedreceive(g_qid, msg2, sizeof(msg2), &prior, &tspec);
381 if (len2 == (ssize_t) - 1) { // NO MORE data
382 if (errno != ETIMEDOUT) {
383 fprintf(stderr, "%s: Unexpected error %d\n", __FUNCTION__, errno);
388 // g_saveq.push(string((const char*) msg2, len2));
389 g_saveq.push(std::string((const char*) msg2, len2));
393 work_str = g_saveq.front();
394 if (eFrameworkunifiedStatusOK
395 != WriteAndSwitchLogFile(work_str.data(), work_str.length())) {
396 fprintf(stderr, "%s: Failed in write Saved data, errno=%d\n",
397 __FUNCTION__, errno);
404 if (pushed || g_wfd == -1) {
408 if (eFrameworkunifiedStatusOK != WriteAndSwitchLogFile(msg, len)) {
409 fprintf(stderr, "%s: Failed in write Saved data-2, errno=%d\n",
410 __FUNCTION__, errno);
413 return eFrameworkunifiedStatusOK;
416 EFrameworkunifiedStatus OnSyncTimeout(HANDLE hApp) {
418 if (g_wfd != -1 && g_wfd != -2) {
419 char logpath[MAXPATHLEN];
423 EncryptAndCopyFile();
425 // snprintf(logpath, "%s/%s", g_log_tmp_path, USB_RT_LOGNAME_TMP);
426 snprintf(logpath, MAXPATHLEN, "%s/%s", g_log_tmp_path, USB_RT_LOGNAME_TMP);
428 if ((g_wfd = open(logpath, O_RDWR | O_CREAT | O_APPEND | O_CLOEXEC, 0644))
430 fprintf(stderr, "%s: Failed to open file %s, errno=%d (%s)\n",
431 __FUNCTION__, logpath, errno, strerror(errno));
432 // because in order to continue to obtain logs.
433 return eFrameworkunifiedStatusOK;
438 return eFrameworkunifiedStatusOK;
441 EFrameworkunifiedStatus rtUsbLogThread(HANDLE hApp) {
442 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
443 struct mq_attr qattr;
444 const struct timespec idle_time = { 1, 0 }; // 1sec
445 HANDLE timer_handle = NULL;
447 // Subscribe Boot Mode Notifcation to SysMgr
448 l_eStatus = FrameworkunifiedSubscribeNotificationWithCallback(hApp,
449 NTFY_SSSystemMgrPowerOnOff,
450 OnPowerOnOffNotification);
451 if (eFrameworkunifiedStatusOK != l_eStatus) {
452 fprintf(stderr, "%s: Subscribe PowerOnOff failed, status=%d\n",
453 __FUNCTION__, l_eStatus);
455 // Subscribe Device Detection Availability
457 if (g_devDetect.Initialize(hApp)) {
458 if (eFrameworkunifiedStatusOK
459 != (l_eStatus = g_devDetect.NotifyOnDeviceDetectionAvailability(
460 OnDeviceDetectionAvailability))) {
462 "%s: DevDetec AvailabilityCallback registration failed\n",
465 if (eFrameworkunifiedStatusOK
466 != (l_eStatus = g_devDetect.NotifyOnOpenSessionAck(
467 OnDeviceDetectionOpenSessionACK))) {
468 fprintf(stderr, "%s: DevDetec OpenSession ACK registration failed\n",
471 if (eFrameworkunifiedStatusOK
472 != (l_eStatus = g_devDetect.NotifyOnCloseSessionAck(
473 onDeviceDetectionCloseSessionACK))) {
474 fprintf(stderr, "%s: DevDetec CloseSession ACK registration failed\n",
479 fprintf(stderr, "%s: Device Detection Object Initialization failed\n",
481 nanosleep(&idle_time, NULL);
485 // open message queue
488 qattr.mq_maxmsg = USB_REALTIME_MSGMAX;
489 qattr.mq_msgsize = USB_REALTIME_SIZMAX;
490 qattr.mq_curmsgs = 0;
491 if ((g_qid = mq_open(USB_REALTIME_QNAME, O_RDWR | O_CREAT, 0666, &qattr))
495 fprintf(stderr, "%s: Failed in mq_open, errno=%d\n", __FUNCTION__, errno);
496 nanosleep(&idle_time, NULL);
499 // Attach callback func to message queue fd
500 l_eStatus = FrameworkunifiedAttachCallbackToDispatcherWithFd(hApp, static_cast<int>(g_qid),
501 OnMessageQueueReceived);
502 if (eFrameworkunifiedStatusOK != l_eStatus) {
505 "%s: Error in FrameworkunifiedAttachCallbackToDispatcherWithFd with mq_fd, status=%d\n",
506 __FUNCTION__, l_eStatus);
509 // Start Cyclic Timer
510 timer_handle = FrameworkunifiedAttachTimerCallback(hApp, USB_RT_TIMER_CYCLE,
513 if (timer_handle == NULL) {
514 fprintf(stderr, "%s: Error in FrameworkunifiedAttachTimerCallback\n", __FUNCTION__);
515 return eFrameworkunifiedStatusFail;
518 // Enter dispatcher ==> Just return
519 return eFrameworkunifiedStatusOK;
522 EFrameworkunifiedStatus rtUsbLogTShutdown(HANDLE hApp) {
523 return eFrameworkunifiedStatusOK;
526 EFrameworkunifiedStatus OnDeviceDetectionAvailability(HANDLE hApp) {
527 EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusOK;
529 if (FrameworkunifiedIsServiceAvailable(hApp)) {
530 if (eFrameworkunifiedStatusOK != (eStatus = g_devDetect.OpenSessionRequest())) {
531 fprintf(stderr, "%s: Open session request failed\n", __FUNCTION__);
534 if (eFrameworkunifiedStatusOK != (eStatus = g_devDetect.CloseSessionRequest())) {
535 fprintf(stderr, "%s: Close session request failed\n", __FUNCTION__);
541 EFrameworkunifiedStatus OnDeviceDetectionOpenSessionACK(HANDLE hApp) {
542 EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusOK;
544 if (eFrameworkunifiedStatusOK == (eStatus = g_devDetect.DecodeOpenSessionResponse())) {
545 if (eFrameworkunifiedStatusOK
546 != (eStatus = g_devDetect.RegisterForDeviceDetectionEvent(
547 SS_DEV_DETECT_ANY_USB_EV, onUsbDetectCallback))) {
548 fprintf(stderr, "%s: Registration for SS_DEV_DETECT_ANY_USB_EV failed\n",
552 fprintf(stderr, "%s: Decode open session response failed\n", __FUNCTION__);
557 EFrameworkunifiedStatus onDeviceDetectionCloseSessionACK(HANDLE hApp) {
558 EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusOK;
559 CloseSessionAck tCloseSessionAck;
562 if (eFrameworkunifiedStatusOK
563 == (eStatus = FrameworkunifiedGetMsgDataOfSize(hApp, &tCloseSessionAck,
564 sizeof(tCloseSessionAck)))) {
565 if (eFrameworkunifiedStatusOK != tCloseSessionAck.eStatus) {
566 eStatus = eFrameworkunifiedStatusFail;
573 EFrameworkunifiedStatus onUsbDetectCallback(HANDLE hApp) {
574 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
575 SS_MediaDetectInfo l_tMediaDetectInfo;
577 if (eFrameworkunifiedStatusOK
578 != (l_eStatus = FrameworkunifiedGetMsgDataOfSize(hApp, &l_tMediaDetectInfo,
579 sizeof(l_tMediaDetectInfo)))) {
580 fprintf(stderr, "%s: FrameworkunifiedGetMsgDataOfSize Failed Status:0x%x\n",
581 __FUNCTION__, l_eStatus);
583 if (l_tMediaDetectInfo.dev_type != eUSB) { // NOT mass storage device
586 if (l_tMediaDetectInfo.bIsDeviceAvailable) {
587 if (g_usb_available) { // Already mounted
590 // set USB device available
591 g_usb_available = true;
592 // Organize paths to access
593 strncpy(g_mnt_path, l_tMediaDetectInfo.deviceMountpath,
596 snprintf(g_fld_path, MAXPATHLEN, "%s%s", g_mnt_path, USB_RT_FOLDERPATH_);
597 snprintf(g_log_path, MAXPATHLEN, "%s/%s", g_fld_path, USB_RT_LOGNAME_);
598 g_log_name = const_cast<char*>(USB_RT_LOGNAME_);
602 // snprintf(g_log_tmp_path, "%s", USB_RT_TMP_PATH);
603 snprintf(g_log_tmp_path, MAXPATHLEN, "%s", USB_RT_TMP_PATH);
607 // unset USB device available
608 if (strcmp(l_tMediaDetectInfo.deviceMountpath, g_mnt_path) == 0) {
609 g_usb_available = false;
611 if (g_wfd != -1 && g_wfd != -2) {
614 EncryptAndCopyFile();
623 EFrameworkunifiedStatus EncryptAndCopyFile(void) {
624 char usblogpath[MAXPATHLEN];
625 char logpath[MAXPATHLEN];
626 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
629 struct stat istat_buf;
632 // snprintf(usblogpath, "%s%05d.log", g_log_path, g_num_of_file);
634 // snprintf(logpath, "%s/%s", g_log_tmp_path, USB_RT_LOGNAME_TMP);
635 snprintf(usblogpath, MAXPATHLEN, "%s%05d.log", g_log_path, g_num_of_file);
637 snprintf(logpath, MAXPATHLEN, "%s/%s", g_log_tmp_path, USB_RT_LOGNAME_TMP);
640 rfd = open(logpath, O_RDWR | O_CLOEXEC);
642 fprintf(stderr, "%s: Error. Failed to open file: %s for reading.\n",
643 __FUNCTION__, logpath);
644 return eFrameworkunifiedStatusFail;
647 ret = fstat(rfd, &istat_buf);
649 fprintf(stderr, "%s: Error. stat(%s). errno: %d, %s \n", __FUNCTION__,
650 logpath, errno, strerror(errno));
652 return eFrameworkunifiedStatusFail;
657 off_t total_size = istat_buf.st_size;
659 wfd = open(usblogpath, O_RDWR | O_APPEND | O_TRUNC | O_CREAT | O_CLOEXEC,
662 fprintf(stderr, "%s: Error. Failed to open file: %s for reading.\n",
663 __FUNCTION__, usblogpath);
665 return eFrameworkunifiedStatusFail;
668 pData = reinterpret_cast<BYTE*>(malloc(ENC_BUF_MAX_SIZE));
670 fprintf(stderr, "%s: Error. Failed to malloc %d byte for dst \n",
671 __FUNCTION__, ENC_BUF_MAX_SIZE);
674 return eFrameworkunifiedStatusFail;
677 total_len = static_cast<int>(total_size);
679 read_len = read(rfd, pData, ENC_BUF_MAX_SIZE);
680 if (read_len == -1) {
681 fprintf(stderr, "%s: Error. File read failed. errno: %d, %s \n",
682 __FUNCTION__, errno, strerror(errno));
683 l_eStatus = eFrameworkunifiedStatusFail;
686 ret = write(wfd, pData, read_len);
688 fprintf(stderr, "%s: Error. length(%d) no space to write: %d, %s \n",
689 __FUNCTION__, ret, errno, strerror(errno));
690 l_eStatus = eFrameworkunifiedStatusFail;
693 total_len -= read_len;
694 } while (total_len > 0);
701 if (l_eStatus == eFrameworkunifiedStatusFail) {
705 // Synchronization security
706 struct stat ostat_buf;
708 ret = stat(usblogpath, &ostat_buf);
710 fprintf(stderr, "%s: Error. stat(%s). errno: %d, %s", __FUNCTION__,
711 usblogpath, errno, strerror(errno));
714 if (ostat_buf.st_size >= total_size) {
717 usleep(1000); // interval