106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci */
1506f6ba60Sopenharmony_ci#include "hisysevent_plugin.h"
1606f6ba60Sopenharmony_ci#include "hisysevent_plugin_result.pbencoder.h"
1706f6ba60Sopenharmony_ci
1806f6ba60Sopenharmony_ci#include <cinttypes>
1906f6ba60Sopenharmony_ci#include <csignal>
2006f6ba60Sopenharmony_ci#include <cstdio>
2106f6ba60Sopenharmony_ci#include <fcntl.h>
2206f6ba60Sopenharmony_ci#include <sstream>
2306f6ba60Sopenharmony_ci#include <sys/syscall.h>
2406f6ba60Sopenharmony_ci#include <sys/types.h>
2506f6ba60Sopenharmony_ci#include <sys/wait.h>
2606f6ba60Sopenharmony_ci#include <unistd.h>
2706f6ba60Sopenharmony_ci
2806f6ba60Sopenharmony_cinamespace {
2906f6ba60Sopenharmony_ciusing namespace OHOS::Developtools::Profiler;
3006f6ba60Sopenharmony_ciconstexpr int PIPE_SIZE = 256 * 1024;
3106f6ba60Sopenharmony_ciconstexpr int MAX_STRING_LEN = 256 * 1024;
3206f6ba60Sopenharmony_ciconstexpr int MIN_STRING_LEN = 10;
3306f6ba60Sopenharmony_ciconstexpr int BYTE_BUFFER_SIZE = 1024;
3406f6ba60Sopenharmony_ci} // namespace
3506f6ba60Sopenharmony_ci
3606f6ba60Sopenharmony_ciHisyseventPlugin::HisyseventPlugin() : fp_(nullptr, nullptr) {}
3706f6ba60Sopenharmony_ci
3806f6ba60Sopenharmony_ciHisyseventPlugin::~HisyseventPlugin()
3906f6ba60Sopenharmony_ci{
4006f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__);
4106f6ba60Sopenharmony_ci    Stop();
4206f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "END %s: success!", __func__);
4306f6ba60Sopenharmony_ci}
4406f6ba60Sopenharmony_ci
4506f6ba60Sopenharmony_ciint HisyseventPlugin::SetWriter(WriterStruct* writer)
4606f6ba60Sopenharmony_ci{
4706f6ba60Sopenharmony_ci    resultWriter_ = writer;
4806f6ba60Sopenharmony_ci
4906f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "END %s: success!", __func__);
5006f6ba60Sopenharmony_ci    return 0;
5106f6ba60Sopenharmony_ci}
5206f6ba60Sopenharmony_ci
5306f6ba60Sopenharmony_ciint HisyseventPlugin::Start(const uint8_t* configData, uint32_t configSize)
5406f6ba60Sopenharmony_ci{
5506f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__);
5606f6ba60Sopenharmony_ci    CHECK_NOTNULL(configData, -1, "NOTE %s: param invalid", __func__);
5706f6ba60Sopenharmony_ci
5806f6ba60Sopenharmony_ci    CHECK_TRUE(protoConfig_.ParseFromArray(configData, configSize) > 0, -1,
5906f6ba60Sopenharmony_ci               "NOTE HisyseventPlugin: ParseFromArray failed");
6006f6ba60Sopenharmony_ci
6106f6ba60Sopenharmony_ci    PROFILER_LOG_DEBUG(LOG_CORE, "config sourse data:%s domain:%s event:%s", protoConfig_.msg().c_str(),
6206f6ba60Sopenharmony_ci        protoConfig_.subscribe_domain().c_str(), protoConfig_.subscribe_event().c_str());
6306f6ba60Sopenharmony_ci
6406f6ba60Sopenharmony_ci    CHECK_TRUE(InitHisyseventCmd(), -1, "HisyseventPlugin: Init HisyseventCmd failed");
6506f6ba60Sopenharmony_ci
6606f6ba60Sopenharmony_ci    fp_ = std::unique_ptr<FILE, std::function<int (FILE*)>>(
6706f6ba60Sopenharmony_ci        COMMON::CustomPopen(fullCmd_, "r", pipeFds_, childPid_, true), [this](FILE* fp) -> int {
6806f6ba60Sopenharmony_ci            return COMMON::CustomPclose(fp, pipeFds_, childPid_, true);
6906f6ba60Sopenharmony_ci        });
7006f6ba60Sopenharmony_ci
7106f6ba60Sopenharmony_ci    CHECK_NOTNULL(fp_.get(), -1, "HisyseventPlugin: fullCmd_ Failed, errno(%d)", errno);
7206f6ba60Sopenharmony_ci    CHECK_NOTNULL(resultWriter_, -1, "HisyseventPlugin: Writer is no set!!");
7306f6ba60Sopenharmony_ci    CHECK_NOTNULL(resultWriter_->write, -1, "HisyseventPlugin: Writer.write is no set!!");
7406f6ba60Sopenharmony_ci    CHECK_NOTNULL(resultWriter_->flush, -1, "HisyseventPlugin: Writer.flush is no set!!");
7506f6ba60Sopenharmony_ci    id_ = 1;
7606f6ba60Sopenharmony_ci    running_ = true;
7706f6ba60Sopenharmony_ci    workThread_ = std::thread([this] { this->Run(); });
7806f6ba60Sopenharmony_ci
7906f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "END %s: success!", __func__);
8006f6ba60Sopenharmony_ci    return 0;
8106f6ba60Sopenharmony_ci}
8206f6ba60Sopenharmony_ci
8306f6ba60Sopenharmony_ciint HisyseventPlugin::Stop()
8406f6ba60Sopenharmony_ci{
8506f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__);
8606f6ba60Sopenharmony_ci    running_ = false;
8706f6ba60Sopenharmony_ci    COMMON::CustomPUnblock(pipeFds_);
8806f6ba60Sopenharmony_ci
8906f6ba60Sopenharmony_ci    if (workThread_.joinable()) {
9006f6ba60Sopenharmony_ci        workThread_.join();
9106f6ba60Sopenharmony_ci    }
9206f6ba60Sopenharmony_ci
9306f6ba60Sopenharmony_ci    if (fp_ != nullptr) {
9406f6ba60Sopenharmony_ci        fp_.reset();
9506f6ba60Sopenharmony_ci    }
9606f6ba60Sopenharmony_ci
9706f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "END %s: success!", __func__);
9806f6ba60Sopenharmony_ci    return 0;
9906f6ba60Sopenharmony_ci}
10006f6ba60Sopenharmony_ci
10106f6ba60Sopenharmony_civoid HisyseventPlugin::Run(void)
10206f6ba60Sopenharmony_ci{
10306f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__);
10406f6ba60Sopenharmony_ci    std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(MAX_STRING_LEN);
10506f6ba60Sopenharmony_ci
10606f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE,
10706f6ba60Sopenharmony_ci                      "NOTE hisysevent_plugin_result.proto->HisyseventInfo:dataProto;Ready to output the result!");
10806f6ba60Sopenharmony_ci
10906f6ba60Sopenharmony_ci    fcntl(fileno(fp_.get()), F_SETPIPE_SZ, PIPE_SIZE);
11006f6ba60Sopenharmony_ci    int aPipeSize = fcntl(fileno(fp_.get()), F_GETPIPE_SZ);
11106f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "{fp = %d, aPipeSize=%d, PIPE_SIZE=%d}", fileno(fp_.get()), aPipeSize, PIPE_SIZE);
11206f6ba60Sopenharmony_ci
11306f6ba60Sopenharmony_ci    std::unique_ptr<HisyseventInfo> dataProto = nullptr;
11406f6ba60Sopenharmony_ci    std::unique_ptr<ProtoEncoder::HisyseventInfo> hisyseventInfo = nullptr;
11506f6ba60Sopenharmony_ci    if (resultWriter_->isProtobufSerialize) {
11606f6ba60Sopenharmony_ci        dataProto = std::make_unique<HisyseventInfo>();
11706f6ba60Sopenharmony_ci    } else {
11806f6ba60Sopenharmony_ci        hisyseventInfo = std::make_unique<ProtoEncoder::HisyseventInfo>(resultWriter_->startReport(resultWriter_));
11906f6ba60Sopenharmony_ci    }
12006f6ba60Sopenharmony_ci
12106f6ba60Sopenharmony_ci    while (running_) {
12206f6ba60Sopenharmony_ci        char* cptr = nullptr;
12306f6ba60Sopenharmony_ci        if (fgets(reinterpret_cast<char*>(buffer.get()), MAX_STRING_LEN, fp_.get()) != nullptr) {
12406f6ba60Sopenharmony_ci            cptr = reinterpret_cast<char*>(buffer.get());
12506f6ba60Sopenharmony_ci        }
12606f6ba60Sopenharmony_ci        if (cptr == nullptr) {
12706f6ba60Sopenharmony_ci            continue;
12806f6ba60Sopenharmony_ci        }
12906f6ba60Sopenharmony_ci        if (resultWriter_->isProtobufSerialize) {
13006f6ba60Sopenharmony_ci            if (!ParseSyseventLineInfo(cptr, strlen(cptr), dataProto.get())) {
13106f6ba60Sopenharmony_ci                continue;
13206f6ba60Sopenharmony_ci            }
13306f6ba60Sopenharmony_ci
13406f6ba60Sopenharmony_ci            if (dataProto->ByteSizeLong() >= BYTE_BUFFER_SIZE) {
13506f6ba60Sopenharmony_ci                WriteResult(dataProto.get());
13606f6ba60Sopenharmony_ci                dataProto->clear_info();
13706f6ba60Sopenharmony_ci            }
13806f6ba60Sopenharmony_ci        } else {
13906f6ba60Sopenharmony_ci            if (!ParseSyseventLineInfo(cptr, strlen(cptr), hisyseventInfo.get())) {
14006f6ba60Sopenharmony_ci                continue;
14106f6ba60Sopenharmony_ci            }
14206f6ba60Sopenharmony_ci
14306f6ba60Sopenharmony_ci            if (hisyseventInfo->Size() >= BYTE_BUFFER_SIZE) {
14406f6ba60Sopenharmony_ci                FlushDataOptimize(hisyseventInfo.get());
14506f6ba60Sopenharmony_ci                hisyseventInfo.reset();
14606f6ba60Sopenharmony_ci                hisyseventInfo =
14706f6ba60Sopenharmony_ci                    std::make_unique<ProtoEncoder::HisyseventInfo>(resultWriter_->startReport(resultWriter_));
14806f6ba60Sopenharmony_ci            }
14906f6ba60Sopenharmony_ci        }
15006f6ba60Sopenharmony_ci    }
15106f6ba60Sopenharmony_ci
15206f6ba60Sopenharmony_ci    if (resultWriter_->isProtobufSerialize) {
15306f6ba60Sopenharmony_ci        WriteResult(dataProto.get());
15406f6ba60Sopenharmony_ci        dataProto.reset();
15506f6ba60Sopenharmony_ci    } else {
15606f6ba60Sopenharmony_ci        FlushDataOptimize(hisyseventInfo.get());
15706f6ba60Sopenharmony_ci        hisyseventInfo.reset();
15806f6ba60Sopenharmony_ci    }
15906f6ba60Sopenharmony_ci
16006f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "END %s: success!", __func__);
16106f6ba60Sopenharmony_ci}
16206f6ba60Sopenharmony_ci
16306f6ba60Sopenharmony_cistd::string HisyseventPlugin::GetFullCmd()
16406f6ba60Sopenharmony_ci{
16506f6ba60Sopenharmony_ci    std::string cmd;
16606f6ba60Sopenharmony_ci
16706f6ba60Sopenharmony_ci    if (!fullCmd_.empty()) {
16806f6ba60Sopenharmony_ci        size_t i = 0;
16906f6ba60Sopenharmony_ci        size_t dataLen = fullCmd_.size() > 1 ? fullCmd_.size() - 1 : 0;
17006f6ba60Sopenharmony_ci        for (size_t cmdSize = dataLen; i < cmdSize; i++) {
17106f6ba60Sopenharmony_ci            cmd.append(fullCmd_[i]).append(" ");
17206f6ba60Sopenharmony_ci        }
17306f6ba60Sopenharmony_ci        cmd.append(fullCmd_[i]);
17406f6ba60Sopenharmony_ci    }
17506f6ba60Sopenharmony_ci    return cmd;
17606f6ba60Sopenharmony_ci}
17706f6ba60Sopenharmony_ci
17806f6ba60Sopenharmony_ciinline bool HisyseventPlugin::InitHisyseventCmd()
17906f6ba60Sopenharmony_ci{
18006f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__);
18106f6ba60Sopenharmony_ci    if (!fullCmd_.empty()) {
18206f6ba60Sopenharmony_ci        PROFILER_LOG_INFO(LOG_CORE, "fullCmd_ is dirty.Then clear().");
18306f6ba60Sopenharmony_ci        fullCmd_.clear();
18406f6ba60Sopenharmony_ci    }
18506f6ba60Sopenharmony_ci
18606f6ba60Sopenharmony_ci    fullCmd_.emplace_back("/system/bin/hisysevent"); // exe file path
18706f6ba60Sopenharmony_ci    fullCmd_.emplace_back("hisysevent"); // exe file name
18806f6ba60Sopenharmony_ci    fullCmd_.emplace_back("-rd");
18906f6ba60Sopenharmony_ci
19006f6ba60Sopenharmony_ci    if (!protoConfig_.subscribe_domain().empty()) {
19106f6ba60Sopenharmony_ci        fullCmd_.emplace_back("-o");
19206f6ba60Sopenharmony_ci        fullCmd_.emplace_back(protoConfig_.subscribe_domain());
19306f6ba60Sopenharmony_ci    }
19406f6ba60Sopenharmony_ci    if (!protoConfig_.subscribe_event().empty()) {
19506f6ba60Sopenharmony_ci        fullCmd_.emplace_back("-n");
19606f6ba60Sopenharmony_ci        fullCmd_.emplace_back(protoConfig_.subscribe_event());
19706f6ba60Sopenharmony_ci    }
19806f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "END %s: success!", __func__);
19906f6ba60Sopenharmony_ci    return true;
20006f6ba60Sopenharmony_ci}
20106f6ba60Sopenharmony_ci
20206f6ba60Sopenharmony_citemplate <typename T>
20306f6ba60Sopenharmony_ciinline bool HisyseventPlugin::ParseSyseventLineInfo(const char* data, size_t len, T hisyseventInfoProto)
20406f6ba60Sopenharmony_ci{
20506f6ba60Sopenharmony_ci    CHECK_TRUE(data != nullptr && len >= MIN_STRING_LEN, false, "NOTE %s: param invalid", __func__);
20606f6ba60Sopenharmony_ci    size_t dataLen = strlen(data) > 1 ? strlen(data) - 1 : 0;
20706f6ba60Sopenharmony_ci    if (google::protobuf::internal::IsStructurallyValidUTF8(data, dataLen)) {
20806f6ba60Sopenharmony_ci        auto* info = hisyseventInfoProto->add_info();
20906f6ba60Sopenharmony_ci        info->set_id(id_);
21006f6ba60Sopenharmony_ci        size_t len = strlen(data) > 1 ? strlen(data) - 1 : 0;
21106f6ba60Sopenharmony_ci        info->set_context(data, len); // - \n
21206f6ba60Sopenharmony_ci        id_++;
21306f6ba60Sopenharmony_ci    } else {
21406f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "NOTE HisyseventPlugin: hisysevent context include invalid UTF-8 data");
21506f6ba60Sopenharmony_ci        return false;
21606f6ba60Sopenharmony_ci    }
21706f6ba60Sopenharmony_ci    return true;
21806f6ba60Sopenharmony_ci}
21906f6ba60Sopenharmony_ci
22006f6ba60Sopenharmony_citemplate <typename T> inline bool HisyseventPlugin::WriteResult(const T hisyseventInfoProto)
22106f6ba60Sopenharmony_ci{
22206f6ba60Sopenharmony_ci    // Cmd result resize and SerializeToArray and after save to protoBuffer_ ;Then write and flush;Then clear_info
22306f6ba60Sopenharmony_ci    protoBuffer_.resize(hisyseventInfoProto->ByteSizeLong());
22406f6ba60Sopenharmony_ci    hisyseventInfoProto->SerializeToArray(protoBuffer_.data(), protoBuffer_.size());
22506f6ba60Sopenharmony_ci    // SerializeToArray after data=%s",protoBuffer_.data()
22606f6ba60Sopenharmony_ci    resultWriter_->write(resultWriter_, protoBuffer_.data(), protoBuffer_.size());
22706f6ba60Sopenharmony_ci    resultWriter_->flush(resultWriter_);
22806f6ba60Sopenharmony_ci    return true;
22906f6ba60Sopenharmony_ci}
23006f6ba60Sopenharmony_ci
23106f6ba60Sopenharmony_citemplate <typename T> void HisyseventPlugin::FlushDataOptimize(const T hisyseventInfoProto)
23206f6ba60Sopenharmony_ci{
23306f6ba60Sopenharmony_ci    int messageLen = hisyseventInfoProto->Finish();
23406f6ba60Sopenharmony_ci    resultWriter_->finishReport(resultWriter_, messageLen);
23506f6ba60Sopenharmony_ci    resultWriter_->flush(resultWriter_);
23606f6ba60Sopenharmony_ci}
237