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