1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "host_unity.h"
16
17 namespace Hdc {
HdcHostUnity(HTaskInfo hTaskInfo)18 HdcHostUnity::HdcHostUnity(HTaskInfo hTaskInfo)
19 : HdcTaskBase(hTaskInfo)
20 {
21 opContext.thisClass = this;
22 }
23
~HdcHostUnity()24 HdcHostUnity::~HdcHostUnity()
25 {
26 WRITE_LOG(LOG_DEBUG, "~HdcHostUnity channelId:%u", taskInfo->channelId);
27 }
28
ReadyForRelease()29 bool HdcHostUnity::ReadyForRelease()
30 {
31 if (!HdcTaskBase::ReadyForRelease()) {
32 WRITE_LOG(LOG_WARN, "not ready for release channelId:%u", taskInfo->channelId);
33 return false;
34 }
35 if (opContext.enableLog && !opContext.hasFilelogClosed) {
36 WRITE_LOG(LOG_WARN, "enableLog true hasFilelogClosed false channelId:%u", taskInfo->channelId);
37 return false;
38 }
39 return true;
40 }
41
StopTask()42 void HdcHostUnity::StopTask()
43 {
44 // Do not detect RunningProtect, force to close
45 if (opContext.hasFilelogClosed) {
46 WRITE_LOG(LOG_WARN, "StopTask hasFilelogClosed true channelId:%u", taskInfo->channelId);
47 return;
48 }
49 if (opContext.enableLog) {
50 ++refCount;
51 opContext.fsClose.data = &opContext;
52 WRITE_LOG(LOG_DEBUG, "taskInfo->channelId:%u fileLog:%d", taskInfo->channelId, opContext.fileLog);
53 uv_fs_close(loopTask, &opContext.fsClose, opContext.fileLog, OnFileClose);
54 }
55 };
56
OnFileClose(uv_fs_t * req)57 void HdcHostUnity::OnFileClose(uv_fs_t *req)
58 {
59 uv_fs_req_cleanup(req);
60 ContextUnity *context = reinterpret_cast<ContextUnity *>(req->data);
61 HdcHostUnity *thisClass = reinterpret_cast<HdcHostUnity *>(context->thisClass);
62 context->hasFilelogClosed = true;
63 --thisClass->refCount;
64 return;
65 }
66
InitLocalLog(const char * path)67 bool HdcHostUnity::InitLocalLog(const char *path)
68 {
69 uv_fs_t reqFs;
70 // block open
71 if (uv_fs_open(nullptr, &reqFs, path, UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, nullptr)
72 < 0) {
73 WRITE_LOG(LOG_FATAL, "InitLocalLog uv_fs_open failed taskInfo->channelId:%u", taskInfo->channelId);
74 return false;
75 }
76 uv_fs_req_cleanup(&reqFs);
77 opContext.fileLog = reqFs.result;
78 return true;
79 }
80
OnFileIO(uv_fs_t * req)81 void HdcHostUnity::OnFileIO(uv_fs_t *req)
82 {
83 CtxUnityIO *contextIO = reinterpret_cast<CtxUnityIO *>(req->data);
84 ContextUnity *context = reinterpret_cast<ContextUnity *>(contextIO->context);
85 HdcHostUnity *thisClass = reinterpret_cast<HdcHostUnity *>(context->thisClass);
86 uint8_t *bufIO = contextIO->bufIO;
87 uv_fs_req_cleanup(req);
88 --thisClass->refCount;
89 while (true) {
90 if (req->result <= 0) {
91 if (req->result < 0) {
92 constexpr int bufSize = 1024;
93 char buf[bufSize] = { 0 };
94 uv_strerror_r((int)req->result, buf, bufSize);
95 WRITE_LOG(LOG_DEBUG, "Error OnFileIO: %s", buf);
96 }
97 break;
98 }
99 context->fileIOIndex += req->result;
100 break;
101 }
102 delete[] bufIO;
103 delete contextIO; // req is part of contextIO, no need to release
104 }
105
AppendLocalLog(const char * bufLog,const int sizeLog)106 bool HdcHostUnity::AppendLocalLog(const char *bufLog, const int sizeLog)
107 {
108 auto buf = new uint8_t[sizeLog];
109 auto contextIO = new CtxUnityIO();
110 if (!buf || !contextIO) {
111 if (buf) {
112 delete[] buf;
113 }
114 if (contextIO) {
115 delete contextIO;
116 }
117 return false;
118 }
119 uv_fs_t *req = &contextIO->fs;
120 contextIO->bufIO = buf;
121 contextIO->context = &opContext;
122 req->data = contextIO;
123 ++refCount;
124
125 if (memcpy_s(buf, sizeLog, bufLog, sizeLog)) {
126 }
127 uv_buf_t iov = uv_buf_init(reinterpret_cast<char *>(buf), sizeLog);
128 uv_fs_write(loopTask, req, opContext.fileLog, &iov, 1, opContext.fileBufIndex, OnFileIO);
129 opContext.fileBufIndex += sizeLog;
130 return true;
131 }
132
CommandDispatch(const uint16_t command,uint8_t * payload,const int payloadSize)133 bool HdcHostUnity::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize)
134 {
135 bool ret = true;
136 // Both are executed, do not need to detect ChildReady
137 switch (command) {
138 case CMD_UNITY_BUGREPORT_INIT: {
139 if (strlen(reinterpret_cast<char *>(payload))) { // enable local log
140 if (!InitLocalLog(reinterpret_cast<const char *>(payload))) {
141 LogMsg(MSG_FAIL, "Cannot set locallog");
142 ret = false;
143 break;
144 };
145 opContext.enableLog = true;
146 }
147 SendToAnother(CMD_UNITY_BUGREPORT_INIT, nullptr, 0);
148 break;
149 }
150 case CMD_UNITY_BUGREPORT_DATA: {
151 if (opContext.enableLog) {
152 AppendLocalLog(reinterpret_cast<const char *>(payload), payloadSize);
153 } else {
154 ServerCommand(CMD_KERNEL_ECHO_RAW, payload, payloadSize);
155 }
156 break;
157 }
158 default:
159 break;
160 }
161 return ret;
162 };
163 } // namespace Hdc
164