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::~HdcHostUnity finish");
27 }
28
ReadyForRelease()29 bool HdcHostUnity::ReadyForRelease()
30 {
31 if (!HdcTaskBase::ReadyForRelease()) {
32 return false;
33 }
34 if (opContext.enableLog && !opContext.hasFilelogClosed) {
35 return false;
36 }
37 return true;
38 }
39
StopTask()40 void HdcHostUnity::StopTask()
41 {
42 // Do not detect RunningProtect, force to close
43 if (opContext.hasFilelogClosed) {
44 return;
45 }
46 if (opContext.enableLog) {
47 ++refCount;
48 opContext.fsClose.data = &opContext;
49 WRITE_LOG(LOG_DEBUG, "taskInfo->channelId:%u fileLog:%d", taskInfo->channelId, opContext.fileLog);
50 uv_fs_close(loopTask, &opContext.fsClose, opContext.fileLog, OnFileClose);
51 }
52 };
53
OnFileClose(uv_fs_t * req)54 void HdcHostUnity::OnFileClose(uv_fs_t *req)
55 {
56 uv_fs_req_cleanup(req);
57 ContextUnity *context = reinterpret_cast<ContextUnity *>(req->data);
58 HdcHostUnity *thisClass = reinterpret_cast<HdcHostUnity *>(context->thisClass);
59 context->hasFilelogClosed = true;
60 --thisClass->refCount;
61 return;
62 }
63
InitLocalLog(const char * path)64 bool HdcHostUnity::InitLocalLog(const char *path)
65 {
66 uv_fs_t reqFs;
67 // block open
68 if (uv_fs_open(nullptr, &reqFs, path, UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, nullptr)
69 < 0) {
70 return false;
71 }
72 uv_fs_req_cleanup(&reqFs);
73 opContext.fileLog = reqFs.result;
74 return true;
75 }
76
OnFileIO(uv_fs_t * req)77 void HdcHostUnity::OnFileIO(uv_fs_t *req)
78 {
79 CtxUnityIO *contextIO = reinterpret_cast<CtxUnityIO *>(req->data);
80 ContextUnity *context = reinterpret_cast<ContextUnity *>(contextIO->context);
81 HdcHostUnity *thisClass = reinterpret_cast<HdcHostUnity *>(context->thisClass);
82 uint8_t *bufIO = contextIO->bufIO;
83 uv_fs_req_cleanup(req);
84 --thisClass->refCount;
85 while (true) {
86 if (req->result <= 0) {
87 if (req->result < 0) {
88 constexpr int bufSize = 1024;
89 char buf[bufSize] = { 0 };
90 uv_strerror_r((int)req->result, buf, bufSize);
91 WRITE_LOG(LOG_DEBUG, "Error OnFileIO: %s", buf);
92 }
93 break;
94 }
95 context->fileIOIndex += req->result;
96 break;
97 }
98 delete[] bufIO;
99 delete contextIO; // req is part of contextIO, no need to release
100 }
101
AppendLocalLog(const char * bufLog,const int sizeLog)102 bool HdcHostUnity::AppendLocalLog(const char *bufLog, const int sizeLog)
103 {
104 auto buf = new uint8_t[sizeLog];
105 auto contextIO = new CtxUnityIO();
106 if (!buf || !contextIO) {
107 if (buf) {
108 delete[] buf;
109 }
110 if (contextIO) {
111 delete contextIO;
112 }
113 return false;
114 }
115 uv_fs_t *req = &contextIO->fs;
116 contextIO->bufIO = buf;
117 contextIO->context = &opContext;
118 req->data = contextIO;
119 ++refCount;
120
121 if (memcpy_s(buf, sizeLog, bufLog, sizeLog)) {
122 }
123 uv_buf_t iov = uv_buf_init(reinterpret_cast<char *>(buf), sizeLog);
124 uv_fs_write(loopTask, req, opContext.fileLog, &iov, 1, opContext.fileBufIndex, OnFileIO);
125 opContext.fileBufIndex += sizeLog;
126 return true;
127 }
128
CommandDispatch(const uint16_t command,uint8_t * payload,const int payloadSize)129 bool HdcHostUnity::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize)
130 {
131 bool ret = true;
132 // Both are executed, do not need to detect ChildReady
133 switch (command) {
134 case CMD_UNITY_BUGREPORT_INIT: {
135 if (strlen(reinterpret_cast<char *>(payload))) { // enable local log
136 if (!InitLocalLog(reinterpret_cast<const char *>(payload))) {
137 LogMsg(MSG_FAIL, "Cannot set locallog");
138 ret = false;
139 break;
140 };
141 opContext.enableLog = true;
142 }
143 SendToAnother(CMD_UNITY_BUGREPORT_INIT, nullptr, 0);
144 break;
145 }
146 case CMD_UNITY_BUGREPORT_DATA: {
147 if (opContext.enableLog) {
148 AppendLocalLog(reinterpret_cast<const char *>(payload), payloadSize);
149 } else {
150 ServerCommand(CMD_KERNEL_ECHO_RAW, payload, payloadSize);
151 }
152 break;
153 }
154 default:
155 break;
156 }
157 return ret;
158 };
159 } // namespace Hdc
160