1b0e7dd80Sopenharmony_ci/*
2b0e7dd80Sopenharmony_ci * Copyright (C) 2023-2024 Huawei Device Co., Ltd.
3b0e7dd80Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b0e7dd80Sopenharmony_ci * you may not use this file except in compliance with the License.
5b0e7dd80Sopenharmony_ci * You may obtain a copy of the License at
6b0e7dd80Sopenharmony_ci *
7b0e7dd80Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8b0e7dd80Sopenharmony_ci *
9b0e7dd80Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b0e7dd80Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b0e7dd80Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b0e7dd80Sopenharmony_ci * See the License for the specific language governing permissions and
13b0e7dd80Sopenharmony_ci * limitations under the License.
14b0e7dd80Sopenharmony_ci */
15b0e7dd80Sopenharmony_ci
16b0e7dd80Sopenharmony_ci#include "hitrace_dump.h"
17b0e7dd80Sopenharmony_ci
18b0e7dd80Sopenharmony_ci#include <atomic>
19b0e7dd80Sopenharmony_ci#include <cinttypes>
20b0e7dd80Sopenharmony_ci#include <csignal>
21b0e7dd80Sopenharmony_ci#include <fstream>
22b0e7dd80Sopenharmony_ci#include <map>
23b0e7dd80Sopenharmony_ci#include <memory>
24b0e7dd80Sopenharmony_ci#include <mutex>
25b0e7dd80Sopenharmony_ci#include <set>
26b0e7dd80Sopenharmony_ci#include <sys/epoll.h>
27b0e7dd80Sopenharmony_ci#include <sys/prctl.h>
28b0e7dd80Sopenharmony_ci#include <sys/sysinfo.h>
29b0e7dd80Sopenharmony_ci#include <sys/wait.h>
30b0e7dd80Sopenharmony_ci#include <thread>
31b0e7dd80Sopenharmony_ci#include <unistd.h>
32b0e7dd80Sopenharmony_ci
33b0e7dd80Sopenharmony_ci#include "common_utils.h"
34b0e7dd80Sopenharmony_ci#include "dynamic_buffer.h"
35b0e7dd80Sopenharmony_ci#include "hitrace_meter.h"
36b0e7dd80Sopenharmony_ci#include "hilog/log.h"
37b0e7dd80Sopenharmony_ci#include "hitrace_osal.h"
38b0e7dd80Sopenharmony_ci#include "parameters.h"
39b0e7dd80Sopenharmony_ci#include "securec.h"
40b0e7dd80Sopenharmony_ci#include "trace_utils.h"
41b0e7dd80Sopenharmony_ci
42b0e7dd80Sopenharmony_ciusing namespace std;
43b0e7dd80Sopenharmony_ciusing namespace OHOS::HiviewDFX::HitraceOsal;
44b0e7dd80Sopenharmony_ciusing OHOS::HiviewDFX::HiLog;
45b0e7dd80Sopenharmony_ci
46b0e7dd80Sopenharmony_cinamespace OHOS {
47b0e7dd80Sopenharmony_cinamespace HiviewDFX {
48b0e7dd80Sopenharmony_cinamespace Hitrace {
49b0e7dd80Sopenharmony_ci
50b0e7dd80Sopenharmony_cinamespace {
51b0e7dd80Sopenharmony_ci
52b0e7dd80Sopenharmony_cistruct TraceParams {
53b0e7dd80Sopenharmony_ci    std::vector<std::string> tags;
54b0e7dd80Sopenharmony_ci    std::vector<std::string> tagGroups;
55b0e7dd80Sopenharmony_ci    std::string bufferSize;
56b0e7dd80Sopenharmony_ci    std::string clockType;
57b0e7dd80Sopenharmony_ci    std::string isOverWrite;
58b0e7dd80Sopenharmony_ci    std::string outputFile;
59b0e7dd80Sopenharmony_ci    int fileLimit;
60b0e7dd80Sopenharmony_ci    int fileSize;
61b0e7dd80Sopenharmony_ci    int appPid;
62b0e7dd80Sopenharmony_ci};
63b0e7dd80Sopenharmony_ci
64b0e7dd80Sopenharmony_ciconstexpr uint16_t MAGIC_NUMBER = 57161;
65b0e7dd80Sopenharmony_ciconstexpr uint16_t VERSION_NUMBER = 1;
66b0e7dd80Sopenharmony_ciconstexpr uint8_t FILE_RAW_TRACE = 0;
67b0e7dd80Sopenharmony_ciconstexpr uint8_t HM_FILE_RAW_TRACE = 1;
68b0e7dd80Sopenharmony_ciconstexpr int UNIT_TIME = 100000;
69b0e7dd80Sopenharmony_ciconstexpr int ALIGNMENT_COEFFICIENT = 4;
70b0e7dd80Sopenharmony_ci
71b0e7dd80Sopenharmony_ciconst int DEFAULT_BUFFER_SIZE = 12 * 1024;
72b0e7dd80Sopenharmony_ciconst int DEFAULT_FILE_SIZE = 100 * 1024;
73b0e7dd80Sopenharmony_ci#ifdef DOUBLE_TRACEBUFFER_ENABLE
74b0e7dd80Sopenharmony_ciconst int HM_DEFAULT_BUFFER_SIZE = 288 * 1024;
75b0e7dd80Sopenharmony_ci#else
76b0e7dd80Sopenharmony_ciconst int HM_DEFAULT_BUFFER_SIZE = 144 * 1024;
77b0e7dd80Sopenharmony_ci#endif
78b0e7dd80Sopenharmony_ciconst int SAVED_CMDLINES_SIZE = 3072; // 3M
79b0e7dd80Sopenharmony_ciconst int KB_PER_MB = 1024;
80b0e7dd80Sopenharmony_ciconst uint64_t S_TO_NS = 1000000000;
81b0e7dd80Sopenharmony_ciconst int MAX_NEW_TRACE_FILE_LIMIT = 5;
82b0e7dd80Sopenharmony_ciconst int JUDGE_FILE_EXIST = 10;  // Check whether the trace file exists every 10 times.
83b0e7dd80Sopenharmony_ciconst int SNAPSHOT_FILE_MAX_COUNT = 20;
84b0e7dd80Sopenharmony_ci
85b0e7dd80Sopenharmony_ciconst std::string DEFAULT_OUTPUT_DIR = "/data/log/hitrace/";
86b0e7dd80Sopenharmony_ciconst std::string SAVED_EVENTS_FORMAT = "saved_events_format";
87b0e7dd80Sopenharmony_ci
88b0e7dd80Sopenharmony_cistruct alignas(ALIGNMENT_COEFFICIENT) TraceFileHeader {
89b0e7dd80Sopenharmony_ci    uint16_t magicNumber {MAGIC_NUMBER};
90b0e7dd80Sopenharmony_ci    uint8_t fileType {FILE_RAW_TRACE};
91b0e7dd80Sopenharmony_ci    uint16_t versionNumber {VERSION_NUMBER};
92b0e7dd80Sopenharmony_ci    uint32_t reserved {0};
93b0e7dd80Sopenharmony_ci};
94b0e7dd80Sopenharmony_ci
95b0e7dd80Sopenharmony_cienum ContentType : uint8_t {
96b0e7dd80Sopenharmony_ci    CONTENT_TYPE_DEFAULT = 0,
97b0e7dd80Sopenharmony_ci    CONTENT_TYPE_EVENTS_FORMAT = 1,
98b0e7dd80Sopenharmony_ci    CONTENT_TYPE_CMDLINES  = 2,
99b0e7dd80Sopenharmony_ci    CONTENT_TYPE_TGIDS = 3,
100b0e7dd80Sopenharmony_ci    CONTENT_TYPE_CPU_RAW = 4,
101b0e7dd80Sopenharmony_ci    CONTENT_TYPE_HEADER_PAGE = 30,
102b0e7dd80Sopenharmony_ci    CONTENT_TYPE_PRINTK_FORMATS = 31,
103b0e7dd80Sopenharmony_ci    CONTENT_TYPE_KALLSYMS = 32
104b0e7dd80Sopenharmony_ci};
105b0e7dd80Sopenharmony_ci
106b0e7dd80Sopenharmony_cistruct alignas(ALIGNMENT_COEFFICIENT) TraceFileContentHeader {
107b0e7dd80Sopenharmony_ci    uint8_t type = CONTENT_TYPE_DEFAULT;
108b0e7dd80Sopenharmony_ci    uint32_t length = 0;
109b0e7dd80Sopenharmony_ci};
110b0e7dd80Sopenharmony_ci
111b0e7dd80Sopenharmony_cistruct PageHeader {
112b0e7dd80Sopenharmony_ci    uint64_t timestamp = 0;
113b0e7dd80Sopenharmony_ci    uint64_t size = 0;
114b0e7dd80Sopenharmony_ci    uint8_t overwrite = 0;
115b0e7dd80Sopenharmony_ci    uint8_t *startPos = nullptr;
116b0e7dd80Sopenharmony_ci    uint8_t *endPos = nullptr;
117b0e7dd80Sopenharmony_ci};
118b0e7dd80Sopenharmony_ci
119b0e7dd80Sopenharmony_ci#ifndef PAGE_SIZE
120b0e7dd80Sopenharmony_ciconstexpr size_t PAGE_SIZE = 4096;
121b0e7dd80Sopenharmony_ci#endif
122b0e7dd80Sopenharmony_ci
123b0e7dd80Sopenharmony_ciconst int BUFFER_SIZE = 256 * PAGE_SIZE; // 1M
124b0e7dd80Sopenharmony_ci
125b0e7dd80Sopenharmony_cistd::atomic<bool> g_dumpFlag(false);
126b0e7dd80Sopenharmony_cistd::atomic<bool> g_dumpEnd(true);
127b0e7dd80Sopenharmony_cistd::mutex g_traceMutex;
128b0e7dd80Sopenharmony_ci
129b0e7dd80Sopenharmony_cibool g_serviceThreadIsStart = false;
130b0e7dd80Sopenharmony_ciuint64_t g_sysInitParamTags = 0;
131b0e7dd80Sopenharmony_ciTraceMode g_traceMode = TraceMode::CLOSE;
132b0e7dd80Sopenharmony_cistd::string g_traceRootPath;
133b0e7dd80Sopenharmony_ciuint8_t g_buffer[BUFFER_SIZE] = {0};
134b0e7dd80Sopenharmony_cistd::vector<std::pair<std::string, int>> g_traceFilesTable;
135b0e7dd80Sopenharmony_cistd::vector<std::string> g_outputFilesForCmd;
136b0e7dd80Sopenharmony_ciint g_outputFileSize = 0;
137b0e7dd80Sopenharmony_ciint g_inputMaxDuration = 0;
138b0e7dd80Sopenharmony_ciuint64_t g_inputTraceEndTime = 0; // in nano seconds
139b0e7dd80Sopenharmony_ciint g_newTraceFileLimit = 0;
140b0e7dd80Sopenharmony_ciint g_writeFileLimit = 0;
141b0e7dd80Sopenharmony_cibool g_needGenerateNewTraceFile = false;
142b0e7dd80Sopenharmony_ciuint64_t g_traceStartTime = 0;
143b0e7dd80Sopenharmony_ciuint64_t g_traceEndTime = std::numeric_limits<uint64_t>::max(); // in nano seconds
144b0e7dd80Sopenharmony_cistd::atomic<uint8_t> g_dumpStatus(TraceErrorCode::UNSET);
145b0e7dd80Sopenharmony_ci
146b0e7dd80Sopenharmony_ciTraceParams g_currentTraceParams = {};
147b0e7dd80Sopenharmony_ci
148b0e7dd80Sopenharmony_cistd::string GetFilePath(const std::string &fileName)
149b0e7dd80Sopenharmony_ci{
150b0e7dd80Sopenharmony_ci    return g_traceRootPath + fileName;
151b0e7dd80Sopenharmony_ci}
152b0e7dd80Sopenharmony_ci
153b0e7dd80Sopenharmony_cistd::vector<std::string> Split(const std::string &str, char delimiter)
154b0e7dd80Sopenharmony_ci{
155b0e7dd80Sopenharmony_ci    std::vector<std::string> res;
156b0e7dd80Sopenharmony_ci    size_t startPos = 0;
157b0e7dd80Sopenharmony_ci    for (size_t i = 0; i < str.size(); i++) {
158b0e7dd80Sopenharmony_ci        if (str[i] == delimiter) {
159b0e7dd80Sopenharmony_ci            res.push_back(str.substr(startPos, i - startPos));
160b0e7dd80Sopenharmony_ci            startPos = i + 1;
161b0e7dd80Sopenharmony_ci        }
162b0e7dd80Sopenharmony_ci    }
163b0e7dd80Sopenharmony_ci    if (startPos < str.size()) {
164b0e7dd80Sopenharmony_ci        res.push_back(str.substr(startPos));
165b0e7dd80Sopenharmony_ci    }
166b0e7dd80Sopenharmony_ci    return res;
167b0e7dd80Sopenharmony_ci}
168b0e7dd80Sopenharmony_ci
169b0e7dd80Sopenharmony_cibool IsTraceMounted()
170b0e7dd80Sopenharmony_ci{
171b0e7dd80Sopenharmony_ci    const std::string debugfsPath = "/sys/kernel/debug/tracing/";
172b0e7dd80Sopenharmony_ci    const std::string tracefsPath = "/sys/kernel/tracing/";
173b0e7dd80Sopenharmony_ci    if (access((debugfsPath + "trace_marker").c_str(), F_OK) != -1) {
174b0e7dd80Sopenharmony_ci        g_traceRootPath = debugfsPath;
175b0e7dd80Sopenharmony_ci        return true;
176b0e7dd80Sopenharmony_ci    }
177b0e7dd80Sopenharmony_ci    if (access((tracefsPath + "trace_marker").c_str(), F_OK) != -1) {
178b0e7dd80Sopenharmony_ci        g_traceRootPath = tracefsPath;
179b0e7dd80Sopenharmony_ci        return true;
180b0e7dd80Sopenharmony_ci    }
181b0e7dd80Sopenharmony_ci    HILOG_ERROR(LOG_CORE, "IsTraceMounted: Did not find trace folder");
182b0e7dd80Sopenharmony_ci    return false;
183b0e7dd80Sopenharmony_ci}
184b0e7dd80Sopenharmony_ci
185b0e7dd80Sopenharmony_ci// Arch is 64bit when reserved = 0; Arch is 32bit when reserved = 1.
186b0e7dd80Sopenharmony_civoid GetArchWordSize(TraceFileHeader& header)
187b0e7dd80Sopenharmony_ci{
188b0e7dd80Sopenharmony_ci    if (sizeof(void*) == sizeof(uint64_t)) {
189b0e7dd80Sopenharmony_ci        header.reserved |= 0;
190b0e7dd80Sopenharmony_ci    } else if (sizeof(void*) == sizeof(uint32_t)) {
191b0e7dd80Sopenharmony_ci        header.reserved |= 1;
192b0e7dd80Sopenharmony_ci    }
193b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "reserved with arch word info is %{public}d.", header.reserved);
194b0e7dd80Sopenharmony_ci}
195b0e7dd80Sopenharmony_ci
196b0e7dd80Sopenharmony_civoid GetCpuNums(TraceFileHeader& header)
197b0e7dd80Sopenharmony_ci{
198b0e7dd80Sopenharmony_ci    const int maxCpuNums = 24;
199b0e7dd80Sopenharmony_ci    int cpuNums = GetCpuProcessors();
200b0e7dd80Sopenharmony_ci    if (cpuNums > maxCpuNums || cpuNums <= 0) {
201b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "error: cpu_number is %{public}d.", cpuNums);
202b0e7dd80Sopenharmony_ci        return;
203b0e7dd80Sopenharmony_ci    }
204b0e7dd80Sopenharmony_ci    header.reserved |= (static_cast<uint64_t>(cpuNums) << 1);
205b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "reserved with cpu number info is %{public}d.", header.reserved);
206b0e7dd80Sopenharmony_ci}
207b0e7dd80Sopenharmony_ci
208b0e7dd80Sopenharmony_cibool CheckTags(const std::vector<std::string> &tags, const std::map<std::string, TagCategory> &allTags)
209b0e7dd80Sopenharmony_ci{
210b0e7dd80Sopenharmony_ci    for (const auto &tag : tags) {
211b0e7dd80Sopenharmony_ci        if (allTags.find(tag) == allTags.end()) {
212b0e7dd80Sopenharmony_ci            HILOG_ERROR(LOG_CORE, "CheckTags: %{public}s is not provided.", tag.c_str());
213b0e7dd80Sopenharmony_ci            return false;
214b0e7dd80Sopenharmony_ci        }
215b0e7dd80Sopenharmony_ci    }
216b0e7dd80Sopenharmony_ci    return true;
217b0e7dd80Sopenharmony_ci}
218b0e7dd80Sopenharmony_ci
219b0e7dd80Sopenharmony_cibool CheckTagGroup(const std::vector<std::string> &tagGroups,
220b0e7dd80Sopenharmony_ci                   const std::map<std::string, std::vector<std::string>> &tagGroupTable)
221b0e7dd80Sopenharmony_ci{
222b0e7dd80Sopenharmony_ci    for (auto groupName : tagGroups) {
223b0e7dd80Sopenharmony_ci        if (tagGroupTable.find(groupName) == tagGroupTable.end()) {
224b0e7dd80Sopenharmony_ci            HILOG_ERROR(LOG_CORE, "CheckTagGroup: %{public}s is not provided.", groupName.c_str());
225b0e7dd80Sopenharmony_ci            return false;
226b0e7dd80Sopenharmony_ci        }
227b0e7dd80Sopenharmony_ci    }
228b0e7dd80Sopenharmony_ci    return true;
229b0e7dd80Sopenharmony_ci}
230b0e7dd80Sopenharmony_ci
231b0e7dd80Sopenharmony_cibool WriteStrToFileInner(const std::string& filename, const std::string& str)
232b0e7dd80Sopenharmony_ci{
233b0e7dd80Sopenharmony_ci    std::ofstream out;
234b0e7dd80Sopenharmony_ci    out.open(filename, std::ios::out);
235b0e7dd80Sopenharmony_ci    if (out.fail()) {
236b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "WriteStrToFile: %{public}s open failed.", filename.c_str());
237b0e7dd80Sopenharmony_ci        return false;
238b0e7dd80Sopenharmony_ci    }
239b0e7dd80Sopenharmony_ci    out << str;
240b0e7dd80Sopenharmony_ci    if (out.bad()) {
241b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "WriteStrToFile: %{public}s write failed.", filename.c_str());
242b0e7dd80Sopenharmony_ci        out.close();
243b0e7dd80Sopenharmony_ci        return false;
244b0e7dd80Sopenharmony_ci    }
245b0e7dd80Sopenharmony_ci    out.flush();
246b0e7dd80Sopenharmony_ci    out.close();
247b0e7dd80Sopenharmony_ci    return true;
248b0e7dd80Sopenharmony_ci}
249b0e7dd80Sopenharmony_ci
250b0e7dd80Sopenharmony_cibool WriteStrToFile(const std::string& filename, const std::string& str)
251b0e7dd80Sopenharmony_ci{
252b0e7dd80Sopenharmony_ci    if (access((g_traceRootPath + filename).c_str(), W_OK) < 0) {
253b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "WriteStrToFile: Failed to access %{public}s, errno(%{public}d).",
254b0e7dd80Sopenharmony_ci            (g_traceRootPath + filename).c_str(), errno);
255b0e7dd80Sopenharmony_ci        return false;
256b0e7dd80Sopenharmony_ci    }
257b0e7dd80Sopenharmony_ci    return WriteStrToFileInner(g_traceRootPath + filename, str);
258b0e7dd80Sopenharmony_ci}
259b0e7dd80Sopenharmony_ci
260b0e7dd80Sopenharmony_civoid SetTraceNodeStatus(const std::string &path, bool enabled)
261b0e7dd80Sopenharmony_ci{
262b0e7dd80Sopenharmony_ci    WriteStrToFile(path, enabled ? "1" : "0");
263b0e7dd80Sopenharmony_ci}
264b0e7dd80Sopenharmony_ci
265b0e7dd80Sopenharmony_civoid TruncateFile()
266b0e7dd80Sopenharmony_ci{
267b0e7dd80Sopenharmony_ci    int fd = creat((g_traceRootPath + "trace").c_str(), 0);
268b0e7dd80Sopenharmony_ci    if (fd == -1) {
269b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "TruncateFile: clear old trace failed.");
270b0e7dd80Sopenharmony_ci        return;
271b0e7dd80Sopenharmony_ci    }
272b0e7dd80Sopenharmony_ci    close(fd);
273b0e7dd80Sopenharmony_ci    return;
274b0e7dd80Sopenharmony_ci}
275b0e7dd80Sopenharmony_ci
276b0e7dd80Sopenharmony_cibool SetProperty(const std::string& property, const std::string& value)
277b0e7dd80Sopenharmony_ci{
278b0e7dd80Sopenharmony_ci    bool result = OHOS::system::SetParameter(property, value);
279b0e7dd80Sopenharmony_ci    if (!result) {
280b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "SetProperty: set %{public}s failed.", value.c_str());
281b0e7dd80Sopenharmony_ci    } else {
282b0e7dd80Sopenharmony_ci        HILOG_INFO(LOG_CORE, "SetProperty: set %{public}s success.", value.c_str());
283b0e7dd80Sopenharmony_ci    }
284b0e7dd80Sopenharmony_ci    return result;
285b0e7dd80Sopenharmony_ci}
286b0e7dd80Sopenharmony_ci
287b0e7dd80Sopenharmony_ci// close all trace node
288b0e7dd80Sopenharmony_civoid TraceInit(const std::map<std::string, TagCategory> &allTags)
289b0e7dd80Sopenharmony_ci{
290b0e7dd80Sopenharmony_ci    // close all ftrace events
291b0e7dd80Sopenharmony_ci    for (auto it = allTags.begin(); it != allTags.end(); it++) {
292b0e7dd80Sopenharmony_ci        if (it->second.type != 1) {
293b0e7dd80Sopenharmony_ci            continue;
294b0e7dd80Sopenharmony_ci        }
295b0e7dd80Sopenharmony_ci        for (size_t i = 0; i < it->second.sysFiles.size(); i++) {
296b0e7dd80Sopenharmony_ci            SetTraceNodeStatus(it->second.sysFiles[i], false);
297b0e7dd80Sopenharmony_ci        }
298b0e7dd80Sopenharmony_ci    }
299b0e7dd80Sopenharmony_ci    // close all user tags
300b0e7dd80Sopenharmony_ci    SetProperty("debug.hitrace.tags.enableflags", std::to_string(0));
301b0e7dd80Sopenharmony_ci
302b0e7dd80Sopenharmony_ci    // set buffer_size_kb 1
303b0e7dd80Sopenharmony_ci    WriteStrToFile("buffer_size_kb", "1");
304b0e7dd80Sopenharmony_ci
305b0e7dd80Sopenharmony_ci    // close tracing_on
306b0e7dd80Sopenharmony_ci    SetTraceNodeStatus("tracing_on", false);
307b0e7dd80Sopenharmony_ci}
308b0e7dd80Sopenharmony_ci
309b0e7dd80Sopenharmony_ci// Open specific trace node
310b0e7dd80Sopenharmony_civoid SetAllTags(const TraceParams &traceParams, const std::map<std::string, TagCategory> &allTags,
311b0e7dd80Sopenharmony_ci                const std::map<std::string, std::vector<std::string>> &tagGroupTable)
312b0e7dd80Sopenharmony_ci{
313b0e7dd80Sopenharmony_ci    std::set<std::string> readyEnableTagList;
314b0e7dd80Sopenharmony_ci    for (std::string tagName : traceParams.tags) {
315b0e7dd80Sopenharmony_ci        readyEnableTagList.insert(tagName);
316b0e7dd80Sopenharmony_ci    }
317b0e7dd80Sopenharmony_ci
318b0e7dd80Sopenharmony_ci    // if set tagGroup, need to append default group
319b0e7dd80Sopenharmony_ci    if (traceParams.tagGroups.size() > 0) {
320b0e7dd80Sopenharmony_ci        auto iter = tagGroupTable.find("default");
321b0e7dd80Sopenharmony_ci        if (iter == tagGroupTable.end()) {
322b0e7dd80Sopenharmony_ci            HILOG_ERROR(LOG_CORE, "SetAllTags: default group is wrong.");
323b0e7dd80Sopenharmony_ci        } else {
324b0e7dd80Sopenharmony_ci            for (auto defaultTag : iter->second) {
325b0e7dd80Sopenharmony_ci                readyEnableTagList.insert(defaultTag);
326b0e7dd80Sopenharmony_ci            }
327b0e7dd80Sopenharmony_ci        }
328b0e7dd80Sopenharmony_ci    }
329b0e7dd80Sopenharmony_ci
330b0e7dd80Sopenharmony_ci    for (std::string groupName : traceParams.tagGroups) {
331b0e7dd80Sopenharmony_ci        auto iter = tagGroupTable.find(groupName);
332b0e7dd80Sopenharmony_ci        if (iter == tagGroupTable.end()) {
333b0e7dd80Sopenharmony_ci            continue;
334b0e7dd80Sopenharmony_ci        }
335b0e7dd80Sopenharmony_ci        for (std::string tag : iter->second) {
336b0e7dd80Sopenharmony_ci            readyEnableTagList.insert(tag);
337b0e7dd80Sopenharmony_ci        }
338b0e7dd80Sopenharmony_ci    }
339b0e7dd80Sopenharmony_ci
340b0e7dd80Sopenharmony_ci    uint64_t enabledUserTags = 0;
341b0e7dd80Sopenharmony_ci    for (std::string tagName : readyEnableTagList) {
342b0e7dd80Sopenharmony_ci        auto iter = allTags.find(tagName);
343b0e7dd80Sopenharmony_ci        if (iter == allTags.end()) {
344b0e7dd80Sopenharmony_ci            HILOG_ERROR(LOG_CORE, "tag<%{public}s> is invalid.", tagName.c_str());
345b0e7dd80Sopenharmony_ci            continue;
346b0e7dd80Sopenharmony_ci        }
347b0e7dd80Sopenharmony_ci
348b0e7dd80Sopenharmony_ci        if (iter->second.type == 0) {
349b0e7dd80Sopenharmony_ci            enabledUserTags |= iter->second.tag;
350b0e7dd80Sopenharmony_ci        }
351b0e7dd80Sopenharmony_ci
352b0e7dd80Sopenharmony_ci        if (iter->second.type == 1) {
353b0e7dd80Sopenharmony_ci            for (const auto& path : iter->second.sysFiles) {
354b0e7dd80Sopenharmony_ci                SetTraceNodeStatus(path, true);
355b0e7dd80Sopenharmony_ci            }
356b0e7dd80Sopenharmony_ci        }
357b0e7dd80Sopenharmony_ci    }
358b0e7dd80Sopenharmony_ci    SetProperty("debug.hitrace.tags.enableflags", std::to_string(enabledUserTags));
359b0e7dd80Sopenharmony_ci}
360b0e7dd80Sopenharmony_ci
361b0e7dd80Sopenharmony_cistd::string ReadFileInner(const std::string& filename)
362b0e7dd80Sopenharmony_ci{
363b0e7dd80Sopenharmony_ci    std::string resolvedPath = CanonicalizeSpecPath(filename.c_str());
364b0e7dd80Sopenharmony_ci    std::ifstream fileIn(resolvedPath.c_str());
365b0e7dd80Sopenharmony_ci    if (!fileIn.is_open()) {
366b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "ReadFile: %{public}s open failed.", filename.c_str());
367b0e7dd80Sopenharmony_ci        return "";
368b0e7dd80Sopenharmony_ci    }
369b0e7dd80Sopenharmony_ci
370b0e7dd80Sopenharmony_ci    std::string str((std::istreambuf_iterator<char>(fileIn)), std::istreambuf_iterator<char>());
371b0e7dd80Sopenharmony_ci    fileIn.close();
372b0e7dd80Sopenharmony_ci    return str;
373b0e7dd80Sopenharmony_ci}
374b0e7dd80Sopenharmony_ci
375b0e7dd80Sopenharmony_cistd::string ReadFile(const std::string& filename)
376b0e7dd80Sopenharmony_ci{
377b0e7dd80Sopenharmony_ci    std::string filePath = GetFilePath(filename);
378b0e7dd80Sopenharmony_ci    return ReadFileInner(filePath);
379b0e7dd80Sopenharmony_ci}
380b0e7dd80Sopenharmony_ci
381b0e7dd80Sopenharmony_civoid SetClock(const std::string& clockType)
382b0e7dd80Sopenharmony_ci{
383b0e7dd80Sopenharmony_ci    const std::string traceClockPath = "trace_clock";
384b0e7dd80Sopenharmony_ci    if (clockType.size() == 0) {
385b0e7dd80Sopenharmony_ci        WriteStrToFile(traceClockPath, "boot"); //set default: boot
386b0e7dd80Sopenharmony_ci        return;
387b0e7dd80Sopenharmony_ci    }
388b0e7dd80Sopenharmony_ci    std::string allClocks = ReadFile(traceClockPath);
389b0e7dd80Sopenharmony_ci    if (allClocks.find(clockType) == std::string::npos) {
390b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "SetClock: %{public}s is non-existent, set to boot", clockType.c_str());
391b0e7dd80Sopenharmony_ci        WriteStrToFile(traceClockPath, "boot"); // set default: boot
392b0e7dd80Sopenharmony_ci        return;
393b0e7dd80Sopenharmony_ci    }
394b0e7dd80Sopenharmony_ci
395b0e7dd80Sopenharmony_ci    allClocks.erase(allClocks.find_last_not_of(" \n") + 1);
396b0e7dd80Sopenharmony_ci    allClocks.push_back(' ');
397b0e7dd80Sopenharmony_ci
398b0e7dd80Sopenharmony_ci    std::set<std::string> allClockTypes;
399b0e7dd80Sopenharmony_ci    size_t curPos = 0;
400b0e7dd80Sopenharmony_ci    for (size_t i = 0; i < allClocks.size(); i++) {
401b0e7dd80Sopenharmony_ci        if (allClocks[i] == ' ') {
402b0e7dd80Sopenharmony_ci            allClockTypes.insert(allClocks.substr(curPos, i - curPos));
403b0e7dd80Sopenharmony_ci            curPos = i + 1;
404b0e7dd80Sopenharmony_ci        }
405b0e7dd80Sopenharmony_ci    }
406b0e7dd80Sopenharmony_ci
407b0e7dd80Sopenharmony_ci    std::string currentClockType;
408b0e7dd80Sopenharmony_ci    for (auto i : allClockTypes) {
409b0e7dd80Sopenharmony_ci        if (clockType.compare(i) == 0) {
410b0e7dd80Sopenharmony_ci            HILOG_INFO(LOG_CORE, "SetClock: set clock %{public}s success.", clockType.c_str());
411b0e7dd80Sopenharmony_ci            WriteStrToFile(traceClockPath, clockType);
412b0e7dd80Sopenharmony_ci            return;
413b0e7dd80Sopenharmony_ci        }
414b0e7dd80Sopenharmony_ci        if (i[0] == '[') {
415b0e7dd80Sopenharmony_ci            currentClockType = i;
416b0e7dd80Sopenharmony_ci        }
417b0e7dd80Sopenharmony_ci    }
418b0e7dd80Sopenharmony_ci
419b0e7dd80Sopenharmony_ci    const int marks = 2;
420b0e7dd80Sopenharmony_ci    if (clockType.compare(currentClockType.substr(1, currentClockType.size() - marks)) == 0) {
421b0e7dd80Sopenharmony_ci        HILOG_INFO(LOG_CORE, "SetClock: set clock %{public}s success.", clockType.c_str());
422b0e7dd80Sopenharmony_ci        return;
423b0e7dd80Sopenharmony_ci    }
424b0e7dd80Sopenharmony_ci
425b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "SetClock: unknown %{public}s, change to default clock_type: boot.", clockType.c_str());
426b0e7dd80Sopenharmony_ci    WriteStrToFile(traceClockPath, "boot"); // set default: boot
427b0e7dd80Sopenharmony_ci    return;
428b0e7dd80Sopenharmony_ci}
429b0e7dd80Sopenharmony_ci
430b0e7dd80Sopenharmony_cibool SetTraceSetting(const TraceParams &traceParams, const std::map<std::string, TagCategory> &allTags,
431b0e7dd80Sopenharmony_ci                     const std::map<std::string, std::vector<std::string>> &tagGroupTable)
432b0e7dd80Sopenharmony_ci{
433b0e7dd80Sopenharmony_ci    TraceInit(allTags);
434b0e7dd80Sopenharmony_ci
435b0e7dd80Sopenharmony_ci    TruncateFile();
436b0e7dd80Sopenharmony_ci
437b0e7dd80Sopenharmony_ci    SetAllTags(traceParams, allTags, tagGroupTable);
438b0e7dd80Sopenharmony_ci
439b0e7dd80Sopenharmony_ci    WriteStrToFile("current_tracer", "nop");
440b0e7dd80Sopenharmony_ci    WriteStrToFile("buffer_size_kb", traceParams.bufferSize);
441b0e7dd80Sopenharmony_ci
442b0e7dd80Sopenharmony_ci    SetClock(traceParams.clockType);
443b0e7dd80Sopenharmony_ci
444b0e7dd80Sopenharmony_ci    if (traceParams.isOverWrite == "1") {
445b0e7dd80Sopenharmony_ci        WriteStrToFile("options/overwrite", "1");
446b0e7dd80Sopenharmony_ci    } else {
447b0e7dd80Sopenharmony_ci        WriteStrToFile("options/overwrite", "0");
448b0e7dd80Sopenharmony_ci    }
449b0e7dd80Sopenharmony_ci
450b0e7dd80Sopenharmony_ci    WriteStrToFile("saved_cmdlines_size", std::to_string(SAVED_CMDLINES_SIZE));
451b0e7dd80Sopenharmony_ci    WriteStrToFile("options/record-tgid", "1");
452b0e7dd80Sopenharmony_ci    WriteStrToFile("options/record-cmd", "1");
453b0e7dd80Sopenharmony_ci    return true;
454b0e7dd80Sopenharmony_ci}
455b0e7dd80Sopenharmony_ci
456b0e7dd80Sopenharmony_cibool CheckPage(uint8_t contentType, uint8_t *page)
457b0e7dd80Sopenharmony_ci{
458b0e7dd80Sopenharmony_ci    const int pageThreshold = PAGE_SIZE / 2;
459b0e7dd80Sopenharmony_ci
460b0e7dd80Sopenharmony_ci    // Check raw_trace page size.
461b0e7dd80Sopenharmony_ci    if (contentType >= CONTENT_TYPE_CPU_RAW && !IsHmKernel()) {
462b0e7dd80Sopenharmony_ci        PageHeader *pageHeader = reinterpret_cast<PageHeader*>(&page);
463b0e7dd80Sopenharmony_ci        if (pageHeader->size < static_cast<uint64_t>(pageThreshold)) {
464b0e7dd80Sopenharmony_ci            return false;
465b0e7dd80Sopenharmony_ci        }
466b0e7dd80Sopenharmony_ci    }
467b0e7dd80Sopenharmony_ci
468b0e7dd80Sopenharmony_ci    return true;
469b0e7dd80Sopenharmony_ci}
470b0e7dd80Sopenharmony_ci
471b0e7dd80Sopenharmony_cibool CheckFileExist(const std::string &outputFile)
472b0e7dd80Sopenharmony_ci{
473b0e7dd80Sopenharmony_ci    g_writeFileLimit++;
474b0e7dd80Sopenharmony_ci    if (g_writeFileLimit > JUDGE_FILE_EXIST) {
475b0e7dd80Sopenharmony_ci        g_writeFileLimit = 0;
476b0e7dd80Sopenharmony_ci        if (access(outputFile.c_str(), F_OK) != 0) {
477b0e7dd80Sopenharmony_ci            g_needGenerateNewTraceFile = true;
478b0e7dd80Sopenharmony_ci            HILOG_INFO(LOG_CORE, "CheckFileExist access file:%{public}s failed, errno: %{public}d.",
479b0e7dd80Sopenharmony_ci                outputFile.c_str(), errno);
480b0e7dd80Sopenharmony_ci            return false;
481b0e7dd80Sopenharmony_ci        }
482b0e7dd80Sopenharmony_ci    }
483b0e7dd80Sopenharmony_ci    return true;
484b0e7dd80Sopenharmony_ci}
485b0e7dd80Sopenharmony_ci
486b0e7dd80Sopenharmony_civoid SetTimeIntervalBoundary()
487b0e7dd80Sopenharmony_ci{
488b0e7dd80Sopenharmony_ci    if (g_inputMaxDuration > 0) {
489b0e7dd80Sopenharmony_ci        if (g_inputTraceEndTime) {
490b0e7dd80Sopenharmony_ci            g_traceStartTime = g_inputTraceEndTime - static_cast<uint64_t>(g_inputMaxDuration) * S_TO_NS;
491b0e7dd80Sopenharmony_ci            g_traceEndTime = g_inputTraceEndTime;
492b0e7dd80Sopenharmony_ci        } else {
493b0e7dd80Sopenharmony_ci            struct timespec bts = {0, 0};
494b0e7dd80Sopenharmony_ci            clock_gettime(CLOCK_BOOTTIME, &bts);
495b0e7dd80Sopenharmony_ci            g_traceStartTime = static_cast<uint64_t>(bts.tv_sec * S_TO_NS + bts.tv_nsec) -
496b0e7dd80Sopenharmony_ci                static_cast<uint64_t>(g_inputMaxDuration) * S_TO_NS;
497b0e7dd80Sopenharmony_ci            g_traceEndTime = std::numeric_limits<uint64_t>::max();
498b0e7dd80Sopenharmony_ci        }
499b0e7dd80Sopenharmony_ci    } else {
500b0e7dd80Sopenharmony_ci        g_traceStartTime = 0;
501b0e7dd80Sopenharmony_ci        g_traceEndTime = g_inputTraceEndTime > 0 ? g_inputTraceEndTime : std::numeric_limits<uint64_t>::max();
502b0e7dd80Sopenharmony_ci    }
503b0e7dd80Sopenharmony_ci    return;
504b0e7dd80Sopenharmony_ci}
505b0e7dd80Sopenharmony_ci
506b0e7dd80Sopenharmony_civoid RestoreTimeIntervalBoundary()
507b0e7dd80Sopenharmony_ci{
508b0e7dd80Sopenharmony_ci    g_traceStartTime = 0;
509b0e7dd80Sopenharmony_ci    g_traceEndTime = std::numeric_limits<uint64_t>::max();
510b0e7dd80Sopenharmony_ci}
511b0e7dd80Sopenharmony_ci
512b0e7dd80Sopenharmony_civoid GetFileSizeThresholdAndTraceTime(bool &isCpuRaw, uint8_t contentType, uint64_t &traceStartTime,
513b0e7dd80Sopenharmony_ci                                      uint64_t &traceEndTime, int &fileSizeThreshold)
514b0e7dd80Sopenharmony_ci{
515b0e7dd80Sopenharmony_ci    isCpuRaw = contentType >= CONTENT_TYPE_CPU_RAW && contentType < CONTENT_TYPE_HEADER_PAGE;
516b0e7dd80Sopenharmony_ci    if (isCpuRaw) {
517b0e7dd80Sopenharmony_ci        traceStartTime = g_traceStartTime;
518b0e7dd80Sopenharmony_ci        traceEndTime = g_traceEndTime;
519b0e7dd80Sopenharmony_ci    }
520b0e7dd80Sopenharmony_ci    if (g_currentTraceParams.fileSize != 0) {
521b0e7dd80Sopenharmony_ci        fileSizeThreshold = g_currentTraceParams.fileSize * KB_PER_MB;
522b0e7dd80Sopenharmony_ci    }
523b0e7dd80Sopenharmony_ci}
524b0e7dd80Sopenharmony_ci
525b0e7dd80Sopenharmony_cibool IsWriteFileOverflow(const bool isCpuRaw, const int &outputFileSize, const ssize_t &writeLen,
526b0e7dd80Sopenharmony_ci                         const int &fileSizeThreshold)
527b0e7dd80Sopenharmony_ci{
528b0e7dd80Sopenharmony_ci    // attention: we only check file size threshold in CMD_MODE
529b0e7dd80Sopenharmony_ci    if (!isCpuRaw || g_traceMode != TraceMode::CMD_MODE) {
530b0e7dd80Sopenharmony_ci        return false;
531b0e7dd80Sopenharmony_ci    }
532b0e7dd80Sopenharmony_ci    if (outputFileSize + writeLen + static_cast<int>(sizeof(TraceFileContentHeader)) >= fileSizeThreshold) {
533b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "Failed to write, current round write file size exceeds the file size limit.");
534b0e7dd80Sopenharmony_ci        return true;
535b0e7dd80Sopenharmony_ci    }
536b0e7dd80Sopenharmony_ci    if (writeLen > INT_MAX - BUFFER_SIZE) {
537b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "Failed to write, write file length is nearly overflow.");
538b0e7dd80Sopenharmony_ci        return true;
539b0e7dd80Sopenharmony_ci    }
540b0e7dd80Sopenharmony_ci    return false;
541b0e7dd80Sopenharmony_ci}
542b0e7dd80Sopenharmony_ci
543b0e7dd80Sopenharmony_cibool WriteFile(uint8_t contentType, const std::string &src, int outFd, const std::string &outputFile)
544b0e7dd80Sopenharmony_ci{
545b0e7dd80Sopenharmony_ci    std::string srcPath = CanonicalizeSpecPath(src.c_str());
546b0e7dd80Sopenharmony_ci    int srcFd = open(srcPath.c_str(), O_RDONLY | O_NONBLOCK);
547b0e7dd80Sopenharmony_ci    if (srcFd < 0) {
548b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "WriteFile: open %{public}s failed.", src.c_str());
549b0e7dd80Sopenharmony_ci        return false;
550b0e7dd80Sopenharmony_ci    }
551b0e7dd80Sopenharmony_ci    if (!CheckFileExist(outputFile)) {
552b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "need generate new trace file, old file:%{public}s.", outputFile.c_str());
553b0e7dd80Sopenharmony_ci        return false;
554b0e7dd80Sopenharmony_ci    }
555b0e7dd80Sopenharmony_ci    struct TraceFileContentHeader contentHeader;
556b0e7dd80Sopenharmony_ci    contentHeader.type = contentType;
557b0e7dd80Sopenharmony_ci    write(outFd, reinterpret_cast<char *>(&contentHeader), sizeof(contentHeader));
558b0e7dd80Sopenharmony_ci    ssize_t writeLen = 0;
559b0e7dd80Sopenharmony_ci    int count = 0;
560b0e7dd80Sopenharmony_ci    const int maxCount = 2;
561b0e7dd80Sopenharmony_ci
562b0e7dd80Sopenharmony_ci    uint64_t traceStartTime = 0;
563b0e7dd80Sopenharmony_ci    uint64_t traceEndTime = std::numeric_limits<uint64_t>::max();
564b0e7dd80Sopenharmony_ci    int fileSizeThreshold = DEFAULT_FILE_SIZE * KB_PER_MB;
565b0e7dd80Sopenharmony_ci    bool isCpuRaw = false;
566b0e7dd80Sopenharmony_ci    GetFileSizeThresholdAndTraceTime(isCpuRaw, contentType, traceStartTime, traceEndTime, fileSizeThreshold);
567b0e7dd80Sopenharmony_ci    while (true) {
568b0e7dd80Sopenharmony_ci        int bytes = 0;
569b0e7dd80Sopenharmony_ci        bool endFlag = false;
570b0e7dd80Sopenharmony_ci        /* Write 1M at a time */
571b0e7dd80Sopenharmony_ci        while (bytes < BUFFER_SIZE) {
572b0e7dd80Sopenharmony_ci            ssize_t readBytes = TEMP_FAILURE_RETRY(read(srcFd, g_buffer + bytes, PAGE_SIZE));
573b0e7dd80Sopenharmony_ci            if (readBytes == 0) {
574b0e7dd80Sopenharmony_ci                endFlag = true;
575b0e7dd80Sopenharmony_ci                HILOG_DEBUG(LOG_CORE, "WriteFile: read %{public}s end.", src.c_str());
576b0e7dd80Sopenharmony_ci                break;
577b0e7dd80Sopenharmony_ci            } else if (readBytes < 0) {
578b0e7dd80Sopenharmony_ci                endFlag = true;
579b0e7dd80Sopenharmony_ci                HILOG_DEBUG(LOG_CORE, "WriteFile: read %{public}s, data size: %{public}zd failed, errno: %{public}d.",
580b0e7dd80Sopenharmony_ci                    src.c_str(), readBytes, errno);
581b0e7dd80Sopenharmony_ci                break;
582b0e7dd80Sopenharmony_ci            }
583b0e7dd80Sopenharmony_ci
584b0e7dd80Sopenharmony_ci            uint64_t pageTraceTime = 0;
585b0e7dd80Sopenharmony_ci            if (memcpy_s(&pageTraceTime, sizeof(uint64_t), g_buffer + bytes, sizeof(uint64_t)) != EOK) {
586b0e7dd80Sopenharmony_ci                HILOG_ERROR(LOG_CORE, "Failed to memcpy g_buffer to pageTraceTime.");
587b0e7dd80Sopenharmony_ci                break;
588b0e7dd80Sopenharmony_ci            }
589b0e7dd80Sopenharmony_ci            if (traceEndTime < pageTraceTime) {
590b0e7dd80Sopenharmony_ci                endFlag = true;
591b0e7dd80Sopenharmony_ci                readBytes = 0;
592b0e7dd80Sopenharmony_ci                HILOG_INFO(LOG_CORE,
593b0e7dd80Sopenharmony_ci                    "Current pageTraceTime:(%{public}" PRId64 ") is larger than traceEndTime:(%{public}" PRId64 ")",
594b0e7dd80Sopenharmony_ci                    pageTraceTime, traceEndTime);
595b0e7dd80Sopenharmony_ci                break;
596b0e7dd80Sopenharmony_ci            }
597b0e7dd80Sopenharmony_ci
598b0e7dd80Sopenharmony_ci            if (pageTraceTime < traceStartTime) {
599b0e7dd80Sopenharmony_ci                continue;
600b0e7dd80Sopenharmony_ci            }
601b0e7dd80Sopenharmony_ci
602b0e7dd80Sopenharmony_ci            if (CheckPage(contentType, g_buffer + bytes) == false) {
603b0e7dd80Sopenharmony_ci                count++;
604b0e7dd80Sopenharmony_ci            }
605b0e7dd80Sopenharmony_ci            bytes += readBytes;
606b0e7dd80Sopenharmony_ci            if (count >= maxCount) {
607b0e7dd80Sopenharmony_ci                endFlag = true;
608b0e7dd80Sopenharmony_ci                break;
609b0e7dd80Sopenharmony_ci            }
610b0e7dd80Sopenharmony_ci        }
611b0e7dd80Sopenharmony_ci
612b0e7dd80Sopenharmony_ci        ssize_t writeRet = TEMP_FAILURE_RETRY(write(outFd, g_buffer, bytes));
613b0e7dd80Sopenharmony_ci        if (writeRet < 0) {
614b0e7dd80Sopenharmony_ci            HILOG_WARN(LOG_CORE, "WriteFile Fail, errno: %{public}d.", errno);
615b0e7dd80Sopenharmony_ci        } else {
616b0e7dd80Sopenharmony_ci            if (writeRet != static_cast<ssize_t>(bytes)) {
617b0e7dd80Sopenharmony_ci                HILOG_WARN(LOG_CORE, "Failed to write full info, writeLen: %{public}zd, FullLen: %{public}d.",
618b0e7dd80Sopenharmony_ci                    writeRet, bytes);
619b0e7dd80Sopenharmony_ci            }
620b0e7dd80Sopenharmony_ci            writeLen += writeRet;
621b0e7dd80Sopenharmony_ci        }
622b0e7dd80Sopenharmony_ci
623b0e7dd80Sopenharmony_ci        if (IsWriteFileOverflow(isCpuRaw, g_outputFileSize, writeLen, fileSizeThreshold)) {
624b0e7dd80Sopenharmony_ci            break;
625b0e7dd80Sopenharmony_ci        }
626b0e7dd80Sopenharmony_ci
627b0e7dd80Sopenharmony_ci        if (endFlag == true) {
628b0e7dd80Sopenharmony_ci            break;
629b0e7dd80Sopenharmony_ci        }
630b0e7dd80Sopenharmony_ci    }
631b0e7dd80Sopenharmony_ci    contentHeader.length = static_cast<uint32_t>(writeLen);
632b0e7dd80Sopenharmony_ci    uint32_t offset = contentHeader.length + sizeof(contentHeader);
633b0e7dd80Sopenharmony_ci    off_t pos = lseek(outFd, 0, SEEK_CUR);
634b0e7dd80Sopenharmony_ci    lseek(outFd, pos - offset, SEEK_SET);
635b0e7dd80Sopenharmony_ci    write(outFd, reinterpret_cast<char *>(&contentHeader), sizeof(contentHeader));
636b0e7dd80Sopenharmony_ci    lseek(outFd, pos, SEEK_SET);
637b0e7dd80Sopenharmony_ci    close(srcFd);
638b0e7dd80Sopenharmony_ci    if (isCpuRaw) {
639b0e7dd80Sopenharmony_ci        if (writeLen > 0) {
640b0e7dd80Sopenharmony_ci            g_dumpStatus = TraceErrorCode::SUCCESS;
641b0e7dd80Sopenharmony_ci        } else if (g_dumpStatus == TraceErrorCode::UNSET) {
642b0e7dd80Sopenharmony_ci            g_dumpStatus = TraceErrorCode::OUT_OF_TIME;
643b0e7dd80Sopenharmony_ci        }
644b0e7dd80Sopenharmony_ci    }
645b0e7dd80Sopenharmony_ci    g_outputFileSize += static_cast<int>(offset);
646b0e7dd80Sopenharmony_ci    g_needGenerateNewTraceFile = false;
647b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "WriteFile end, path: %{public}s, byte: %{public}zd. g_writeFileLimit: %{public}d",
648b0e7dd80Sopenharmony_ci        src.c_str(), writeLen, g_writeFileLimit);
649b0e7dd80Sopenharmony_ci    return true;
650b0e7dd80Sopenharmony_ci}
651b0e7dd80Sopenharmony_ci
652b0e7dd80Sopenharmony_civoid WriteEventFile(std::string &srcPath, int outFd)
653b0e7dd80Sopenharmony_ci{
654b0e7dd80Sopenharmony_ci    uint8_t buffer[PAGE_SIZE] = {0};
655b0e7dd80Sopenharmony_ci    std::string srcSpecPath = CanonicalizeSpecPath(srcPath.c_str());
656b0e7dd80Sopenharmony_ci    int srcFd = open(srcSpecPath.c_str(), O_RDONLY);
657b0e7dd80Sopenharmony_ci    if (srcFd < 0) {
658b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "WriteEventFile: open %{public}s failed.", srcPath.c_str());
659b0e7dd80Sopenharmony_ci        return;
660b0e7dd80Sopenharmony_ci    }
661b0e7dd80Sopenharmony_ci    int64_t readLen = 0;
662b0e7dd80Sopenharmony_ci    do {
663b0e7dd80Sopenharmony_ci        int64_t len = read(srcFd, buffer, PAGE_SIZE);
664b0e7dd80Sopenharmony_ci        if (len <= 0) {
665b0e7dd80Sopenharmony_ci            break;
666b0e7dd80Sopenharmony_ci        }
667b0e7dd80Sopenharmony_ci        write(outFd, buffer, len);
668b0e7dd80Sopenharmony_ci        readLen += len;
669b0e7dd80Sopenharmony_ci    } while (true);
670b0e7dd80Sopenharmony_ci    close(srcFd);
671b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "WriteEventFile end, path: %{public}s, data size: (%{public}" PRId64 ").",
672b0e7dd80Sopenharmony_ci        srcPath.c_str(), static_cast<uint64_t>(readLen));
673b0e7dd80Sopenharmony_ci}
674b0e7dd80Sopenharmony_ci
675b0e7dd80Sopenharmony_cibool WriteEventsFormat(int outFd, const std::string &outputFile)
676b0e7dd80Sopenharmony_ci{
677b0e7dd80Sopenharmony_ci    const std::string savedEventsFormatPath = DEFAULT_OUTPUT_DIR + SAVED_EVENTS_FORMAT;
678b0e7dd80Sopenharmony_ci    if (access(savedEventsFormatPath.c_str(), F_OK) != -1) {
679b0e7dd80Sopenharmony_ci        return WriteFile(CONTENT_TYPE_EVENTS_FORMAT, savedEventsFormatPath, outFd, outputFile);
680b0e7dd80Sopenharmony_ci    }
681b0e7dd80Sopenharmony_ci    std::string filePath = CanonicalizeSpecPath(savedEventsFormatPath.c_str());
682b0e7dd80Sopenharmony_ci    int fd = open(filePath.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0644); // 0644:-rw-r--r--
683b0e7dd80Sopenharmony_ci    if (fd < 0) {
684b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "WriteEventsFormat: open %{public}s failed.", savedEventsFormatPath.c_str());
685b0e7dd80Sopenharmony_ci        return false;
686b0e7dd80Sopenharmony_ci    }
687b0e7dd80Sopenharmony_ci    const std::vector<std::string> priorityTracingCategory = {
688b0e7dd80Sopenharmony_ci        "events/sched/sched_wakeup/format",
689b0e7dd80Sopenharmony_ci        "events/sched/sched_switch/format",
690b0e7dd80Sopenharmony_ci        "events/sched/sched_blocked_reason/format",
691b0e7dd80Sopenharmony_ci        "events/power/cpu_frequency/format",
692b0e7dd80Sopenharmony_ci        "events/power/clock_set_rate/format",
693b0e7dd80Sopenharmony_ci        "events/power/cpu_frequency_limits/format",
694b0e7dd80Sopenharmony_ci        "events/f2fs/f2fs_sync_file_enter/format",
695b0e7dd80Sopenharmony_ci        "events/f2fs/f2fs_sync_file_exit/format",
696b0e7dd80Sopenharmony_ci        "events/f2fs/f2fs_readpage/format",
697b0e7dd80Sopenharmony_ci        "events/f2fs/f2fs_readpages/format",
698b0e7dd80Sopenharmony_ci        "events/f2fs/f2fs_sync_fs/format",
699b0e7dd80Sopenharmony_ci        "events/hmdfs/hmdfs_syncfs_enter/format",
700b0e7dd80Sopenharmony_ci        "events/hmdfs/hmdfs_syncfs_exit/format",
701b0e7dd80Sopenharmony_ci        "events/erofs/erofs_readpage/format",
702b0e7dd80Sopenharmony_ci        "events/erofs/erofs_readpages/format",
703b0e7dd80Sopenharmony_ci        "events/ext4/ext4_da_write_begin/format",
704b0e7dd80Sopenharmony_ci        "events/ext4/ext4_da_write_end/format",
705b0e7dd80Sopenharmony_ci        "events/ext4/ext4_sync_file_enter/format",
706b0e7dd80Sopenharmony_ci        "events/ext4/ext4_sync_file_exit/format",
707b0e7dd80Sopenharmony_ci        "events/block/block_bio_remap/format",
708b0e7dd80Sopenharmony_ci        "events/block/block_rq_issue/format",
709b0e7dd80Sopenharmony_ci        "events/block/block_rq_complete/format",
710b0e7dd80Sopenharmony_ci        "events/block/block_rq_insert/format",
711b0e7dd80Sopenharmony_ci        "events/dma_fence/dma_fence_emit/format",
712b0e7dd80Sopenharmony_ci        "events/dma_fence/dma_fence_destroy/format",
713b0e7dd80Sopenharmony_ci        "events/dma_fence/dma_fence_enable_signal/format",
714b0e7dd80Sopenharmony_ci        "events/dma_fence/dma_fence_signaled/format",
715b0e7dd80Sopenharmony_ci        "events/dma_fence/dma_fence_wait_end/format",
716b0e7dd80Sopenharmony_ci        "events/dma_fence/dma_fence_wait_start/format",
717b0e7dd80Sopenharmony_ci        "events/dma_fence/dma_fence_init/format",
718b0e7dd80Sopenharmony_ci        "events/binder/binder_transaction/format",
719b0e7dd80Sopenharmony_ci        "events/binder/binder_transaction_received/format",
720b0e7dd80Sopenharmony_ci        "events/mmc/mmc_request_start/format",
721b0e7dd80Sopenharmony_ci        "events/mmc/mmc_request_done/format",
722b0e7dd80Sopenharmony_ci        "events/memory_bus/format",
723b0e7dd80Sopenharmony_ci        "events/cpufreq_interactive/format",
724b0e7dd80Sopenharmony_ci        "events/filemap/file_check_and_advance_wb_err/format",
725b0e7dd80Sopenharmony_ci        "events/filemap/filemap_set_wb_err/format",
726b0e7dd80Sopenharmony_ci        "events/filemap/mm_filemap_add_to_page_cache/format",
727b0e7dd80Sopenharmony_ci        "events/filemap/mm_filemap_delete_from_page_cache/format",
728b0e7dd80Sopenharmony_ci        "events/workqueue/workqueue_execute_end/format",
729b0e7dd80Sopenharmony_ci        "events/workqueue/workqueue_execute_start/format",
730b0e7dd80Sopenharmony_ci        "events/thermal_power_allocator/thermal_power_allocator/format",
731b0e7dd80Sopenharmony_ci        "events/thermal_power_allocator/thermal_power_allocator_pid/format",
732b0e7dd80Sopenharmony_ci        "events/ftrace/print/format",
733b0e7dd80Sopenharmony_ci        "events/tracing_mark_write/tracing_mark_write/format",
734b0e7dd80Sopenharmony_ci        "events/power/cpu_idle/format",
735b0e7dd80Sopenharmony_ci        "events/power_kernel/cpu_idle/format",
736b0e7dd80Sopenharmony_ci        "events/xacct/tracing_mark_write/format",
737b0e7dd80Sopenharmony_ci        "events/ufs/ufshcd_command/format",
738b0e7dd80Sopenharmony_ci        "events/irq/irq_handler_entry/format"
739b0e7dd80Sopenharmony_ci    };
740b0e7dd80Sopenharmony_ci    for (size_t i = 0; i < priorityTracingCategory.size(); i++) {
741b0e7dd80Sopenharmony_ci        std::string srcPath = g_traceRootPath + priorityTracingCategory[i];
742b0e7dd80Sopenharmony_ci        if (access(srcPath.c_str(), R_OK) != -1) {
743b0e7dd80Sopenharmony_ci            WriteEventFile(srcPath, fd);
744b0e7dd80Sopenharmony_ci        }
745b0e7dd80Sopenharmony_ci    }
746b0e7dd80Sopenharmony_ci    close(fd);
747b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "WriteEventsFormat end. path: %{public}s.", filePath.c_str());
748b0e7dd80Sopenharmony_ci    return WriteFile(CONTENT_TYPE_EVENTS_FORMAT, filePath, outFd, outputFile);
749b0e7dd80Sopenharmony_ci}
750b0e7dd80Sopenharmony_ci
751b0e7dd80Sopenharmony_cibool WriteHeaderPage(int outFd, const std::string &outputFile)
752b0e7dd80Sopenharmony_ci{
753b0e7dd80Sopenharmony_ci    if (IsHmKernel()) {
754b0e7dd80Sopenharmony_ci        return true;
755b0e7dd80Sopenharmony_ci    }
756b0e7dd80Sopenharmony_ci    std::string headerPagePath = GetFilePath("events/header_page");
757b0e7dd80Sopenharmony_ci    return WriteFile(CONTENT_TYPE_HEADER_PAGE, headerPagePath, outFd, outputFile);
758b0e7dd80Sopenharmony_ci}
759b0e7dd80Sopenharmony_ci
760b0e7dd80Sopenharmony_cibool WritePrintkFormats(int outFd, const std::string &outputFile)
761b0e7dd80Sopenharmony_ci{
762b0e7dd80Sopenharmony_ci    if (IsHmKernel()) {
763b0e7dd80Sopenharmony_ci        return true;
764b0e7dd80Sopenharmony_ci    }
765b0e7dd80Sopenharmony_ci    std::string printkFormatPath = GetFilePath("printk_formats");
766b0e7dd80Sopenharmony_ci    return WriteFile(CONTENT_TYPE_PRINTK_FORMATS, printkFormatPath, outFd, outputFile);
767b0e7dd80Sopenharmony_ci}
768b0e7dd80Sopenharmony_ci
769b0e7dd80Sopenharmony_cibool WriteKallsyms(int outFd)
770b0e7dd80Sopenharmony_ci{
771b0e7dd80Sopenharmony_ci    /* not implement in hmkernel */
772b0e7dd80Sopenharmony_ci    if (IsHmKernel()) {
773b0e7dd80Sopenharmony_ci        return true;
774b0e7dd80Sopenharmony_ci    }
775b0e7dd80Sopenharmony_ci    /* not implement in linux */
776b0e7dd80Sopenharmony_ci    return true;
777b0e7dd80Sopenharmony_ci}
778b0e7dd80Sopenharmony_ci
779b0e7dd80Sopenharmony_cibool HmWriteCpuRawInner(int outFd, const std::string &outputFile)
780b0e7dd80Sopenharmony_ci{
781b0e7dd80Sopenharmony_ci    uint8_t type = CONTENT_TYPE_CPU_RAW;
782b0e7dd80Sopenharmony_ci    std::string src = g_traceRootPath + "/trace_pipe_raw";
783b0e7dd80Sopenharmony_ci
784b0e7dd80Sopenharmony_ci    if (!WriteFile(type, src, outFd, outputFile)) {
785b0e7dd80Sopenharmony_ci        return false;
786b0e7dd80Sopenharmony_ci    }
787b0e7dd80Sopenharmony_ci
788b0e7dd80Sopenharmony_ci    if (g_dumpStatus) {
789b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "HmWriteCpuRawInner failed, errno: %{public}d.", static_cast<int>(g_dumpStatus.load()));
790b0e7dd80Sopenharmony_ci        return false;
791b0e7dd80Sopenharmony_ci    }
792b0e7dd80Sopenharmony_ci
793b0e7dd80Sopenharmony_ci    return true;
794b0e7dd80Sopenharmony_ci}
795b0e7dd80Sopenharmony_ci
796b0e7dd80Sopenharmony_cibool WriteCpuRawInner(int outFd, const std::string &outputFile)
797b0e7dd80Sopenharmony_ci{
798b0e7dd80Sopenharmony_ci    int cpuNums = GetCpuProcessors();
799b0e7dd80Sopenharmony_ci    uint8_t type = CONTENT_TYPE_CPU_RAW;
800b0e7dd80Sopenharmony_ci    for (int i = 0; i < cpuNums; i++) {
801b0e7dd80Sopenharmony_ci        std::string src = g_traceRootPath + "per_cpu/cpu" + std::to_string(i) + "/trace_pipe_raw";
802b0e7dd80Sopenharmony_ci        if (!WriteFile(static_cast<uint8_t>(type + i), src, outFd, outputFile)) {
803b0e7dd80Sopenharmony_ci            return false;
804b0e7dd80Sopenharmony_ci        }
805b0e7dd80Sopenharmony_ci    }
806b0e7dd80Sopenharmony_ci    if (g_dumpStatus) {
807b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "WriteCpuRawInner failed, errno: %{public}d.", static_cast<int>(g_dumpStatus.load()));
808b0e7dd80Sopenharmony_ci        return false;
809b0e7dd80Sopenharmony_ci    }
810b0e7dd80Sopenharmony_ci    return true;
811b0e7dd80Sopenharmony_ci}
812b0e7dd80Sopenharmony_ci
813b0e7dd80Sopenharmony_cibool WriteCpuRaw(int outFd, const std::string &outputFile)
814b0e7dd80Sopenharmony_ci{
815b0e7dd80Sopenharmony_ci    if (!IsHmKernel()) {
816b0e7dd80Sopenharmony_ci        return WriteCpuRawInner(outFd, outputFile);
817b0e7dd80Sopenharmony_ci    } else {
818b0e7dd80Sopenharmony_ci        return HmWriteCpuRawInner(outFd, outputFile);
819b0e7dd80Sopenharmony_ci    }
820b0e7dd80Sopenharmony_ci}
821b0e7dd80Sopenharmony_ci
822b0e7dd80Sopenharmony_cibool WriteCmdlines(int outFd, const std::string &outputFile)
823b0e7dd80Sopenharmony_ci{
824b0e7dd80Sopenharmony_ci    std::string cmdlinesPath = GetFilePath("saved_cmdlines");
825b0e7dd80Sopenharmony_ci    return WriteFile(CONTENT_TYPE_CMDLINES, cmdlinesPath, outFd, outputFile);
826b0e7dd80Sopenharmony_ci}
827b0e7dd80Sopenharmony_ci
828b0e7dd80Sopenharmony_cibool WriteTgids(int outFd, const std::string &outputFile)
829b0e7dd80Sopenharmony_ci{
830b0e7dd80Sopenharmony_ci    std::string tgidsPath = GetFilePath("saved_tgids");
831b0e7dd80Sopenharmony_ci    return WriteFile(CONTENT_TYPE_TGIDS, tgidsPath, outFd, outputFile);
832b0e7dd80Sopenharmony_ci}
833b0e7dd80Sopenharmony_ci
834b0e7dd80Sopenharmony_cibool GenerateNewFile(int &outFd, std::string &outPath)
835b0e7dd80Sopenharmony_ci{
836b0e7dd80Sopenharmony_ci    if (access(outPath.c_str(), F_OK) == 0) {
837b0e7dd80Sopenharmony_ci        return true;
838b0e7dd80Sopenharmony_ci    }
839b0e7dd80Sopenharmony_ci    std::string outputFileName = GenerateTraceFileName(false);
840b0e7dd80Sopenharmony_ci    outPath = CanonicalizeSpecPath(outputFileName.c_str());
841b0e7dd80Sopenharmony_ci    outFd = open(outPath.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0644); // 0644:-rw-r--r--
842b0e7dd80Sopenharmony_ci    if (outFd < 0) {
843b0e7dd80Sopenharmony_ci        g_newTraceFileLimit++;
844b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "open %{public}s failed, errno: %{public}d.", outPath.c_str(), errno);
845b0e7dd80Sopenharmony_ci    }
846b0e7dd80Sopenharmony_ci    if (g_newTraceFileLimit > MAX_NEW_TRACE_FILE_LIMIT) {
847b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "create new trace file %{public}s limited.", outPath.c_str());
848b0e7dd80Sopenharmony_ci        return false;
849b0e7dd80Sopenharmony_ci    }
850b0e7dd80Sopenharmony_ci    g_needGenerateNewTraceFile = true;
851b0e7dd80Sopenharmony_ci    return true;
852b0e7dd80Sopenharmony_ci}
853b0e7dd80Sopenharmony_ci
854b0e7dd80Sopenharmony_cibool DumpTraceLoop(const std::string &outputFileName, bool isLimited)
855b0e7dd80Sopenharmony_ci{
856b0e7dd80Sopenharmony_ci    const int sleepTime = 1;
857b0e7dd80Sopenharmony_ci    int fileSizeThreshold = DEFAULT_FILE_SIZE * KB_PER_MB;
858b0e7dd80Sopenharmony_ci    if (g_currentTraceParams.fileSize != 0) {
859b0e7dd80Sopenharmony_ci        fileSizeThreshold = g_currentTraceParams.fileSize * KB_PER_MB;
860b0e7dd80Sopenharmony_ci    }
861b0e7dd80Sopenharmony_ci    g_outputFileSize = 0;
862b0e7dd80Sopenharmony_ci    std::string outPath = CanonicalizeSpecPath(outputFileName.c_str());
863b0e7dd80Sopenharmony_ci    int outFd = open(outPath.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0644); // 0644:-rw-r--r--
864b0e7dd80Sopenharmony_ci    if (outFd < 0) {
865b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "open %{public}s failed, errno: %{public}d.", outPath.c_str(), errno);
866b0e7dd80Sopenharmony_ci        return false;
867b0e7dd80Sopenharmony_ci    }
868b0e7dd80Sopenharmony_ci    MarkClockSync(g_traceRootPath);
869b0e7dd80Sopenharmony_ci    struct TraceFileHeader header;
870b0e7dd80Sopenharmony_ci    GetArchWordSize(header);
871b0e7dd80Sopenharmony_ci    GetCpuNums(header);
872b0e7dd80Sopenharmony_ci    if (IsHmKernel()) {
873b0e7dd80Sopenharmony_ci        header.fileType = HM_FILE_RAW_TRACE;
874b0e7dd80Sopenharmony_ci    }
875b0e7dd80Sopenharmony_ci    do {
876b0e7dd80Sopenharmony_ci        g_needGenerateNewTraceFile = false;
877b0e7dd80Sopenharmony_ci        write(outFd, reinterpret_cast<char *>(&header), sizeof(header));
878b0e7dd80Sopenharmony_ci        WriteEventsFormat(outFd, outPath);
879b0e7dd80Sopenharmony_ci        while (g_dumpFlag) {
880b0e7dd80Sopenharmony_ci            if (isLimited && g_outputFileSize > fileSizeThreshold) {
881b0e7dd80Sopenharmony_ci                break;
882b0e7dd80Sopenharmony_ci            }
883b0e7dd80Sopenharmony_ci            sleep(sleepTime);
884b0e7dd80Sopenharmony_ci            if (!WriteCpuRaw(outFd, outPath)) {
885b0e7dd80Sopenharmony_ci                break;
886b0e7dd80Sopenharmony_ci            }
887b0e7dd80Sopenharmony_ci        }
888b0e7dd80Sopenharmony_ci        WriteCmdlines(outFd, outPath);
889b0e7dd80Sopenharmony_ci        WriteTgids(outFd, outPath);
890b0e7dd80Sopenharmony_ci        WriteHeaderPage(outFd, outPath);
891b0e7dd80Sopenharmony_ci        WritePrintkFormats(outFd, outPath);
892b0e7dd80Sopenharmony_ci        WriteKallsyms(outFd);
893b0e7dd80Sopenharmony_ci        if (!GenerateNewFile(outFd, outPath)) {
894b0e7dd80Sopenharmony_ci            HILOG_INFO(LOG_CORE, "DumpTraceLoop access file:%{public}s failed, errno: %{public}d.",
895b0e7dd80Sopenharmony_ci                outPath.c_str(), errno);
896b0e7dd80Sopenharmony_ci            return false;
897b0e7dd80Sopenharmony_ci        }
898b0e7dd80Sopenharmony_ci    } while (g_needGenerateNewTraceFile);
899b0e7dd80Sopenharmony_ci    close(outFd);
900b0e7dd80Sopenharmony_ci    return true;
901b0e7dd80Sopenharmony_ci}
902b0e7dd80Sopenharmony_ci
903b0e7dd80Sopenharmony_ci/**
904b0e7dd80Sopenharmony_ci * read trace data loop
905b0e7dd80Sopenharmony_ci * g_dumpFlag: true = open,false = close
906b0e7dd80Sopenharmony_ci * g_dumpEnd: true = end,false = not end
907b0e7dd80Sopenharmony_ci * if user has own output file, Output all data to the file specified by the user;
908b0e7dd80Sopenharmony_ci * if not, Then place all the result files in /data/log/hitrace/ and package them once in 96M.
909b0e7dd80Sopenharmony_ci*/
910b0e7dd80Sopenharmony_civoid ProcessDumpTask()
911b0e7dd80Sopenharmony_ci{
912b0e7dd80Sopenharmony_ci    g_dumpFlag = true;
913b0e7dd80Sopenharmony_ci    g_dumpEnd = false;
914b0e7dd80Sopenharmony_ci    g_outputFilesForCmd = {};
915b0e7dd80Sopenharmony_ci    const std::string threadName = "TraceDumpTask";
916b0e7dd80Sopenharmony_ci    prctl(PR_SET_NAME, threadName.c_str());
917b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "ProcessDumpTask: trace dump thread start.");
918b0e7dd80Sopenharmony_ci
919b0e7dd80Sopenharmony_ci    // clear old record file before record tracing start.
920b0e7dd80Sopenharmony_ci    DelSavedEventsFormat();
921b0e7dd80Sopenharmony_ci    DelOldRecordTraceFile(g_currentTraceParams.fileLimit);
922b0e7dd80Sopenharmony_ci
923b0e7dd80Sopenharmony_ci    if (g_currentTraceParams.fileSize == 0) {
924b0e7dd80Sopenharmony_ci        std::string outputFileName = g_currentTraceParams.outputFile.empty() ?
925b0e7dd80Sopenharmony_ci                                     GenerateTraceFileName(false) : g_currentTraceParams.outputFile;
926b0e7dd80Sopenharmony_ci        if (DumpTraceLoop(outputFileName, false)) {
927b0e7dd80Sopenharmony_ci            g_outputFilesForCmd.push_back(outputFileName);
928b0e7dd80Sopenharmony_ci        }
929b0e7dd80Sopenharmony_ci        g_dumpEnd = true;
930b0e7dd80Sopenharmony_ci        return;
931b0e7dd80Sopenharmony_ci    }
932b0e7dd80Sopenharmony_ci
933b0e7dd80Sopenharmony_ci    while (g_dumpFlag) {
934b0e7dd80Sopenharmony_ci        if (!IsRootVersion()) {
935b0e7dd80Sopenharmony_ci            ClearOldTraceFile(g_outputFilesForCmd, g_currentTraceParams.fileLimit);
936b0e7dd80Sopenharmony_ci        }
937b0e7dd80Sopenharmony_ci        // Generate file name
938b0e7dd80Sopenharmony_ci        std::string outputFileName = GenerateTraceFileName(false);
939b0e7dd80Sopenharmony_ci        if (DumpTraceLoop(outputFileName, true)) {
940b0e7dd80Sopenharmony_ci            g_outputFilesForCmd.push_back(outputFileName);
941b0e7dd80Sopenharmony_ci        } else {
942b0e7dd80Sopenharmony_ci            break;
943b0e7dd80Sopenharmony_ci        }
944b0e7dd80Sopenharmony_ci    }
945b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "ProcessDumpTask: trace dump thread exit.");
946b0e7dd80Sopenharmony_ci    g_dumpEnd = true;
947b0e7dd80Sopenharmony_ci}
948b0e7dd80Sopenharmony_ci
949b0e7dd80Sopenharmony_civoid SearchFromTable(std::vector<std::string> &outputFiles, int nowSec)
950b0e7dd80Sopenharmony_ci{
951b0e7dd80Sopenharmony_ci    const int maxInterval = 30;
952b0e7dd80Sopenharmony_ci    const int agingTime = 30 * 60;
953b0e7dd80Sopenharmony_ci
954b0e7dd80Sopenharmony_ci    for (auto iter = g_traceFilesTable.begin(); iter != g_traceFilesTable.end();) {
955b0e7dd80Sopenharmony_ci        if (nowSec - iter->second >= agingTime) {
956b0e7dd80Sopenharmony_ci            // delete outdated trace file
957b0e7dd80Sopenharmony_ci            if (access(iter->first.c_str(), F_OK) == 0) {
958b0e7dd80Sopenharmony_ci                remove(iter->first.c_str());
959b0e7dd80Sopenharmony_ci                HILOG_INFO(LOG_CORE, "delete old %{public}s file success.", iter->first.c_str());
960b0e7dd80Sopenharmony_ci            }
961b0e7dd80Sopenharmony_ci            iter = g_traceFilesTable.erase(iter);
962b0e7dd80Sopenharmony_ci            continue;
963b0e7dd80Sopenharmony_ci        }
964b0e7dd80Sopenharmony_ci
965b0e7dd80Sopenharmony_ci        if (nowSec - iter->second <= maxInterval) {
966b0e7dd80Sopenharmony_ci            outputFiles.push_back(iter->first);
967b0e7dd80Sopenharmony_ci        }
968b0e7dd80Sopenharmony_ci        iter++;
969b0e7dd80Sopenharmony_ci    }
970b0e7dd80Sopenharmony_ci}
971b0e7dd80Sopenharmony_ci
972b0e7dd80Sopenharmony_cibool ReadRawTrace(std::string &outputFileName)
973b0e7dd80Sopenharmony_ci{
974b0e7dd80Sopenharmony_ci    // read trace data from /per_cpu/cpux/trace_pipe_raw
975b0e7dd80Sopenharmony_ci    std::string outPath = CanonicalizeSpecPath(outputFileName.c_str());
976b0e7dd80Sopenharmony_ci    int outFd = open(outPath.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0644); // 0644:-rw-r--r--
977b0e7dd80Sopenharmony_ci    if (outFd < 0) {
978b0e7dd80Sopenharmony_ci        return false;
979b0e7dd80Sopenharmony_ci    }
980b0e7dd80Sopenharmony_ci    struct TraceFileHeader header;
981b0e7dd80Sopenharmony_ci    GetArchWordSize(header);
982b0e7dd80Sopenharmony_ci    GetCpuNums(header);
983b0e7dd80Sopenharmony_ci    if (IsHmKernel()) {
984b0e7dd80Sopenharmony_ci        header.fileType = HM_FILE_RAW_TRACE;
985b0e7dd80Sopenharmony_ci    }
986b0e7dd80Sopenharmony_ci    write(outFd, reinterpret_cast<char*>(&header), sizeof(header));
987b0e7dd80Sopenharmony_ci
988b0e7dd80Sopenharmony_ci    if (WriteEventsFormat(outFd, outPath) && WriteCpuRaw(outFd, outPath) &&
989b0e7dd80Sopenharmony_ci        WriteCmdlines(outFd, outPath) && WriteTgids(outFd, outPath) &&
990b0e7dd80Sopenharmony_ci        WriteHeaderPage(outFd, outPath) && WritePrintkFormats(outFd, outPath) &&
991b0e7dd80Sopenharmony_ci        WriteKallsyms(outFd)) {
992b0e7dd80Sopenharmony_ci        fsync(outFd);
993b0e7dd80Sopenharmony_ci        close(outFd);
994b0e7dd80Sopenharmony_ci        return true;
995b0e7dd80Sopenharmony_ci    }
996b0e7dd80Sopenharmony_ci    HILOG_ERROR(LOG_CORE, "ReadRawTrace failed.");
997b0e7dd80Sopenharmony_ci    fsync(outFd);
998b0e7dd80Sopenharmony_ci    close(outFd);
999b0e7dd80Sopenharmony_ci    return false;
1000b0e7dd80Sopenharmony_ci}
1001b0e7dd80Sopenharmony_ci
1002b0e7dd80Sopenharmony_civoid SetProcessName(std::string& processName)
1003b0e7dd80Sopenharmony_ci{
1004b0e7dd80Sopenharmony_ci    if (processName.size() <= 0) {
1005b0e7dd80Sopenharmony_ci        return;
1006b0e7dd80Sopenharmony_ci    }
1007b0e7dd80Sopenharmony_ci
1008b0e7dd80Sopenharmony_ci    const int maxNameLen = 16;
1009b0e7dd80Sopenharmony_ci    std::string setName;
1010b0e7dd80Sopenharmony_ci    if (processName.size() > maxNameLen) {
1011b0e7dd80Sopenharmony_ci        setName = processName.substr(0, maxNameLen);
1012b0e7dd80Sopenharmony_ci    } else {
1013b0e7dd80Sopenharmony_ci        setName = processName;
1014b0e7dd80Sopenharmony_ci    }
1015b0e7dd80Sopenharmony_ci
1016b0e7dd80Sopenharmony_ci    prctl(PR_SET_NAME, setName.c_str(), nullptr, nullptr, nullptr);
1017b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "New process: %{public}s.", setName.c_str());
1018b0e7dd80Sopenharmony_ci}
1019b0e7dd80Sopenharmony_ci
1020b0e7dd80Sopenharmony_civoid TimeoutSignalHandler(int signum)
1021b0e7dd80Sopenharmony_ci{
1022b0e7dd80Sopenharmony_ci    if (signum == SIGUSR1) {
1023b0e7dd80Sopenharmony_ci        _exit(EXIT_SUCCESS);
1024b0e7dd80Sopenharmony_ci    }
1025b0e7dd80Sopenharmony_ci}
1026b0e7dd80Sopenharmony_ci
1027b0e7dd80Sopenharmony_cibool EpollWaitforChildProcess(pid_t &pid, int &pipefd)
1028b0e7dd80Sopenharmony_ci{
1029b0e7dd80Sopenharmony_ci    int epollfd = epoll_create1(0);
1030b0e7dd80Sopenharmony_ci    if (epollfd == -1) {
1031b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "epoll_create1 error.");
1032b0e7dd80Sopenharmony_ci        return false;
1033b0e7dd80Sopenharmony_ci    }
1034b0e7dd80Sopenharmony_ci
1035b0e7dd80Sopenharmony_ci    struct epoll_event event;
1036b0e7dd80Sopenharmony_ci    event.events = EPOLLIN;
1037b0e7dd80Sopenharmony_ci    event.data.fd = pipefd;
1038b0e7dd80Sopenharmony_ci    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd, &event) == -1) {
1039b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "epoll_ctl error.");
1040b0e7dd80Sopenharmony_ci        return false;
1041b0e7dd80Sopenharmony_ci    }
1042b0e7dd80Sopenharmony_ci
1043b0e7dd80Sopenharmony_ci    struct epoll_event events[1];
1044b0e7dd80Sopenharmony_ci    constexpr int waitTimeoutMs = 10000; // 10000ms = 10s
1045b0e7dd80Sopenharmony_ci    int numEvents = 0;
1046b0e7dd80Sopenharmony_ci    do {
1047b0e7dd80Sopenharmony_ci        numEvents = epoll_wait(epollfd, events, 1, waitTimeoutMs);
1048b0e7dd80Sopenharmony_ci    } while (numEvents == -1 && errno == EINTR);
1049b0e7dd80Sopenharmony_ci    if (numEvents == -1) {
1050b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "epoll_wait error, error: (%{public}s).", strerror(errno));
1051b0e7dd80Sopenharmony_ci        close(pipefd);
1052b0e7dd80Sopenharmony_ci        close(epollfd);
1053b0e7dd80Sopenharmony_ci        return false;
1054b0e7dd80Sopenharmony_ci    } else if (numEvents == 0) {
1055b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "epoll_wait timeout.");
1056b0e7dd80Sopenharmony_ci        if (waitpid(pid, nullptr, WNOHANG) <= 0) {
1057b0e7dd80Sopenharmony_ci            HILOG_ERROR(LOG_CORE, "kill timeout child process.");
1058b0e7dd80Sopenharmony_ci            kill(pid, SIGUSR1);
1059b0e7dd80Sopenharmony_ci        }
1060b0e7dd80Sopenharmony_ci        close(pipefd);
1061b0e7dd80Sopenharmony_ci        close(epollfd);
1062b0e7dd80Sopenharmony_ci        return false;
1063b0e7dd80Sopenharmony_ci    }
1064b0e7dd80Sopenharmony_ci    read(pipefd, &g_dumpStatus, sizeof(g_dumpStatus));
1065b0e7dd80Sopenharmony_ci    close(pipefd);
1066b0e7dd80Sopenharmony_ci    close(epollfd);
1067b0e7dd80Sopenharmony_ci    if (waitpid(pid, nullptr, 0) <= 0) {
1068b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "wait HitraceDump(%{public}d) exit failed, errno: (%{public}d)", pid, errno);
1069b0e7dd80Sopenharmony_ci    }
1070b0e7dd80Sopenharmony_ci    return true;
1071b0e7dd80Sopenharmony_ci}
1072b0e7dd80Sopenharmony_ci
1073b0e7dd80Sopenharmony_ciTraceErrorCode DumpTraceInner(std::vector<std::string> &outputFiles)
1074b0e7dd80Sopenharmony_ci{
1075b0e7dd80Sopenharmony_ci    int pipefd[2];
1076b0e7dd80Sopenharmony_ci    if (pipe(pipefd) == -1) {
1077b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "pipe creation error.");
1078b0e7dd80Sopenharmony_ci        return TraceErrorCode::SYSTEM_ERROR;
1079b0e7dd80Sopenharmony_ci    }
1080b0e7dd80Sopenharmony_ci
1081b0e7dd80Sopenharmony_ci    std::string outputFileName = GenerateTraceFileName();
1082b0e7dd80Sopenharmony_ci    std::string reOutPath = CanonicalizeSpecPath(outputFileName.c_str());
1083b0e7dd80Sopenharmony_ci    /*Child process handles task, Father process wait.*/
1084b0e7dd80Sopenharmony_ci    pid_t pid = fork();
1085b0e7dd80Sopenharmony_ci    if (pid < 0) {
1086b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "fork error.");
1087b0e7dd80Sopenharmony_ci        return TraceErrorCode::WRITE_TRACE_INFO_ERROR;
1088b0e7dd80Sopenharmony_ci    } else if (pid == 0) {
1089b0e7dd80Sopenharmony_ci        signal(SIGUSR1, TimeoutSignalHandler);
1090b0e7dd80Sopenharmony_ci        close(pipefd[0]);
1091b0e7dd80Sopenharmony_ci        std::string processName = "HitraceDump";
1092b0e7dd80Sopenharmony_ci        SetProcessName(processName);
1093b0e7dd80Sopenharmony_ci        MarkClockSync(g_traceRootPath);
1094b0e7dd80Sopenharmony_ci        constexpr int waitTime = 10000; // 10ms
1095b0e7dd80Sopenharmony_ci        usleep(waitTime);
1096b0e7dd80Sopenharmony_ci        if (ReadRawTrace(reOutPath)) {
1097b0e7dd80Sopenharmony_ci            g_dumpStatus = TraceErrorCode::SUCCESS;
1098b0e7dd80Sopenharmony_ci        }
1099b0e7dd80Sopenharmony_ci        if (!IsRootVersion()) {
1100b0e7dd80Sopenharmony_ci            DelSnapshotTraceFile(false, SNAPSHOT_FILE_MAX_COUNT);
1101b0e7dd80Sopenharmony_ci        }
1102b0e7dd80Sopenharmony_ci        HILOG_DEBUG(LOG_CORE, "%{public}s exit.", processName.c_str());
1103b0e7dd80Sopenharmony_ci        write(pipefd[1], &g_dumpStatus, sizeof(g_dumpStatus));
1104b0e7dd80Sopenharmony_ci        _exit(EXIT_SUCCESS);
1105b0e7dd80Sopenharmony_ci    } else {
1106b0e7dd80Sopenharmony_ci        close(pipefd[1]);
1107b0e7dd80Sopenharmony_ci    }
1108b0e7dd80Sopenharmony_ci
1109b0e7dd80Sopenharmony_ci    if (!EpollWaitforChildProcess(pid, pipefd[0])) {
1110b0e7dd80Sopenharmony_ci        return TraceErrorCode::SYSTEM_ERROR;
1111b0e7dd80Sopenharmony_ci    }
1112b0e7dd80Sopenharmony_ci
1113b0e7dd80Sopenharmony_ci    if (g_dumpStatus) {
1114b0e7dd80Sopenharmony_ci        if (remove(reOutPath.c_str()) == 0) {
1115b0e7dd80Sopenharmony_ci            HILOG_INFO(LOG_CORE, "Delete outpath:%{public}s success.", reOutPath.c_str());
1116b0e7dd80Sopenharmony_ci        } else {
1117b0e7dd80Sopenharmony_ci            HILOG_INFO(LOG_CORE, "Delete outpath:%{public}s failed.", reOutPath.c_str());
1118b0e7dd80Sopenharmony_ci        }
1119b0e7dd80Sopenharmony_ci        return static_cast<TraceErrorCode>(g_dumpStatus.load());
1120b0e7dd80Sopenharmony_ci    }
1121b0e7dd80Sopenharmony_ci
1122b0e7dd80Sopenharmony_ci    if (access(reOutPath.c_str(), F_OK) != 0) {
1123b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "DumpTraceInner: write %{public}s failed.", outputFileName.c_str());
1124b0e7dd80Sopenharmony_ci        return TraceErrorCode::WRITE_TRACE_INFO_ERROR;
1125b0e7dd80Sopenharmony_ci    }
1126b0e7dd80Sopenharmony_ci
1127b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "Output: %{public}s.", reOutPath.c_str());
1128b0e7dd80Sopenharmony_ci    struct timeval now = {0, 0};
1129b0e7dd80Sopenharmony_ci    gettimeofday(&now, nullptr);
1130b0e7dd80Sopenharmony_ci    int nowSec = now.tv_sec;
1131b0e7dd80Sopenharmony_ci    SearchFromTable(outputFiles, nowSec);
1132b0e7dd80Sopenharmony_ci    outputFiles.push_back(outputFileName);
1133b0e7dd80Sopenharmony_ci    g_traceFilesTable.push_back({outputFileName, nowSec});
1134b0e7dd80Sopenharmony_ci    return TraceErrorCode::SUCCESS;
1135b0e7dd80Sopenharmony_ci}
1136b0e7dd80Sopenharmony_ci
1137b0e7dd80Sopenharmony_ciuint64_t GetSysParamTags()
1138b0e7dd80Sopenharmony_ci{
1139b0e7dd80Sopenharmony_ci    return OHOS::system::GetUintParameter<uint64_t>("debug.hitrace.tags.enableflags", 0);
1140b0e7dd80Sopenharmony_ci}
1141b0e7dd80Sopenharmony_ci
1142b0e7dd80Sopenharmony_civoid RestartService()
1143b0e7dd80Sopenharmony_ci{
1144b0e7dd80Sopenharmony_ci    CloseTrace();
1145b0e7dd80Sopenharmony_ci    const std::vector<std::string> tagGroups = {"scene_performance"};
1146b0e7dd80Sopenharmony_ci    OpenTrace(tagGroups);
1147b0e7dd80Sopenharmony_ci}
1148b0e7dd80Sopenharmony_ci
1149b0e7dd80Sopenharmony_cibool CheckParam()
1150b0e7dd80Sopenharmony_ci{
1151b0e7dd80Sopenharmony_ci    uint64_t currentTags = GetSysParamTags();
1152b0e7dd80Sopenharmony_ci    if (currentTags == g_sysInitParamTags) {
1153b0e7dd80Sopenharmony_ci        return true;
1154b0e7dd80Sopenharmony_ci    }
1155b0e7dd80Sopenharmony_ci
1156b0e7dd80Sopenharmony_ci    if (currentTags == 0) {
1157b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "tag is 0, restart it.");
1158b0e7dd80Sopenharmony_ci        RestartService();
1159b0e7dd80Sopenharmony_ci        return false;
1160b0e7dd80Sopenharmony_ci    }
1161b0e7dd80Sopenharmony_ci    HILOG_ERROR(LOG_CORE, "trace is being used, restart later.");
1162b0e7dd80Sopenharmony_ci    return false;
1163b0e7dd80Sopenharmony_ci}
1164b0e7dd80Sopenharmony_ci
1165b0e7dd80Sopenharmony_cibool CheckTraceFile()
1166b0e7dd80Sopenharmony_ci{
1167b0e7dd80Sopenharmony_ci    const std::string enable = "1";
1168b0e7dd80Sopenharmony_ci    if (ReadFile("tracing_on").substr(0, enable.size()) == enable) {
1169b0e7dd80Sopenharmony_ci        return true;
1170b0e7dd80Sopenharmony_ci    }
1171b0e7dd80Sopenharmony_ci    HILOG_ERROR(LOG_CORE, "tracing_on is 0, restart it.");
1172b0e7dd80Sopenharmony_ci    RestartService();
1173b0e7dd80Sopenharmony_ci    return false;
1174b0e7dd80Sopenharmony_ci}
1175b0e7dd80Sopenharmony_ci
1176b0e7dd80Sopenharmony_ci/**
1177b0e7dd80Sopenharmony_ci * SERVICE_MODE is running, check param and tracing_on.
1178b0e7dd80Sopenharmony_ci*/
1179b0e7dd80Sopenharmony_cibool CheckServiceRunning()
1180b0e7dd80Sopenharmony_ci{
1181b0e7dd80Sopenharmony_ci    if (CheckParam() && CheckTraceFile()) {
1182b0e7dd80Sopenharmony_ci        return true;
1183b0e7dd80Sopenharmony_ci    }
1184b0e7dd80Sopenharmony_ci    return false;
1185b0e7dd80Sopenharmony_ci}
1186b0e7dd80Sopenharmony_ci
1187b0e7dd80Sopenharmony_civoid MonitorServiceTask()
1188b0e7dd80Sopenharmony_ci{
1189b0e7dd80Sopenharmony_ci    g_serviceThreadIsStart = true;
1190b0e7dd80Sopenharmony_ci    const std::string threadName = "TraceMonitor";
1191b0e7dd80Sopenharmony_ci    prctl(PR_SET_NAME, threadName.c_str());
1192b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "MonitorServiceTask: monitor thread start.");
1193b0e7dd80Sopenharmony_ci    const int intervalTime = 15;
1194b0e7dd80Sopenharmony_ci    while (true) {
1195b0e7dd80Sopenharmony_ci        sleep(intervalTime);
1196b0e7dd80Sopenharmony_ci        if (g_traceMode != TraceMode::SERVICE_MODE) {
1197b0e7dd80Sopenharmony_ci            break;
1198b0e7dd80Sopenharmony_ci        }
1199b0e7dd80Sopenharmony_ci
1200b0e7dd80Sopenharmony_ci        if (!CheckServiceRunning()) {
1201b0e7dd80Sopenharmony_ci            continue;
1202b0e7dd80Sopenharmony_ci        }
1203b0e7dd80Sopenharmony_ci
1204b0e7dd80Sopenharmony_ci        const int cpuNums = GetCpuProcessors();
1205b0e7dd80Sopenharmony_ci        std::vector<int> result;
1206b0e7dd80Sopenharmony_ci        std::unique_ptr<DynamicBuffer> dynamicBuffer = std::make_unique<DynamicBuffer>(g_traceRootPath, cpuNums);
1207b0e7dd80Sopenharmony_ci        dynamicBuffer->CalculateBufferSize(result);
1208b0e7dd80Sopenharmony_ci
1209b0e7dd80Sopenharmony_ci        if (static_cast<int>(result.size()) != cpuNums) {
1210b0e7dd80Sopenharmony_ci            HILOG_ERROR(LOG_CORE, "CalculateAllNewBufferSize failed.");
1211b0e7dd80Sopenharmony_ci            break;
1212b0e7dd80Sopenharmony_ci        }
1213b0e7dd80Sopenharmony_ci
1214b0e7dd80Sopenharmony_ci        for (size_t i = 0; i < result.size(); i++) {
1215b0e7dd80Sopenharmony_ci            HILOG_DEBUG(LOG_CORE, "cpu%{public}zu set size %{public}d.", i, result[i]);
1216b0e7dd80Sopenharmony_ci            std::string path = "per_cpu/cpu" + std::to_string(i) + "/buffer_size_kb";
1217b0e7dd80Sopenharmony_ci            WriteStrToFile(path, std::to_string(result[i]));
1218b0e7dd80Sopenharmony_ci        }
1219b0e7dd80Sopenharmony_ci    }
1220b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "MonitorServiceTask: monitor thread exit.");
1221b0e7dd80Sopenharmony_ci    g_serviceThreadIsStart = false;
1222b0e7dd80Sopenharmony_ci}
1223b0e7dd80Sopenharmony_ci
1224b0e7dd80Sopenharmony_ciTraceErrorCode HandleTraceOpen(const TraceParams &traceParams,
1225b0e7dd80Sopenharmony_ci                               const std::map<std::string, TagCategory> &allTags,
1226b0e7dd80Sopenharmony_ci                               const std::map<std::string, std::vector<std::string>> &tagGroupTable)
1227b0e7dd80Sopenharmony_ci{
1228b0e7dd80Sopenharmony_ci    if (!SetTraceSetting(traceParams, allTags, tagGroupTable)) {
1229b0e7dd80Sopenharmony_ci        return TraceErrorCode::FILE_ERROR;
1230b0e7dd80Sopenharmony_ci    }
1231b0e7dd80Sopenharmony_ci    SetTraceNodeStatus("tracing_on", true);
1232b0e7dd80Sopenharmony_ci    g_currentTraceParams = traceParams;
1233b0e7dd80Sopenharmony_ci    return TraceErrorCode::SUCCESS;
1234b0e7dd80Sopenharmony_ci}
1235b0e7dd80Sopenharmony_ci
1236b0e7dd80Sopenharmony_ciTraceErrorCode HandleServiceTraceOpen(const std::vector<std::string> &tagGroups,
1237b0e7dd80Sopenharmony_ci                                      const std::map<std::string, TagCategory> &allTags,
1238b0e7dd80Sopenharmony_ci                                      const std::map<std::string, std::vector<std::string>> &tagGroupTable)
1239b0e7dd80Sopenharmony_ci{
1240b0e7dd80Sopenharmony_ci    TraceParams serviceTraceParams;
1241b0e7dd80Sopenharmony_ci    serviceTraceParams.tagGroups = tagGroups;
1242b0e7dd80Sopenharmony_ci    serviceTraceParams.bufferSize = std::to_string(DEFAULT_BUFFER_SIZE);
1243b0e7dd80Sopenharmony_ci    if (IsHmKernel()) {
1244b0e7dd80Sopenharmony_ci        serviceTraceParams.bufferSize = std::to_string(HM_DEFAULT_BUFFER_SIZE);
1245b0e7dd80Sopenharmony_ci    }
1246b0e7dd80Sopenharmony_ci    serviceTraceParams.clockType = "boot";
1247b0e7dd80Sopenharmony_ci    serviceTraceParams.isOverWrite = "1";
1248b0e7dd80Sopenharmony_ci    serviceTraceParams.fileSize = DEFAULT_FILE_SIZE;
1249b0e7dd80Sopenharmony_ci    return HandleTraceOpen(serviceTraceParams, allTags, tagGroupTable);
1250b0e7dd80Sopenharmony_ci}
1251b0e7dd80Sopenharmony_ci
1252b0e7dd80Sopenharmony_civoid RemoveUnSpace(std::string str, std::string& args)
1253b0e7dd80Sopenharmony_ci{
1254b0e7dd80Sopenharmony_ci    int maxCircleTimes = 30;
1255b0e7dd80Sopenharmony_ci    int curTimes = 0;
1256b0e7dd80Sopenharmony_ci    const size_t symbolAndSpaceLen = 2;
1257b0e7dd80Sopenharmony_ci    std::string strSpace = str + " ";
1258b0e7dd80Sopenharmony_ci    while (curTimes < maxCircleTimes) {
1259b0e7dd80Sopenharmony_ci        curTimes++;
1260b0e7dd80Sopenharmony_ci        std::string::size_type index = args.find(strSpace);
1261b0e7dd80Sopenharmony_ci        if (index != std::string::npos) {
1262b0e7dd80Sopenharmony_ci            args.replace(index, symbolAndSpaceLen, str);
1263b0e7dd80Sopenharmony_ci        } else {
1264b0e7dd80Sopenharmony_ci            break;
1265b0e7dd80Sopenharmony_ci        }
1266b0e7dd80Sopenharmony_ci    }
1267b0e7dd80Sopenharmony_ci}
1268b0e7dd80Sopenharmony_ci
1269b0e7dd80Sopenharmony_civoid SetCmdTraceIntParams(const std::string &traceParamsStr, int &traceParams)
1270b0e7dd80Sopenharmony_ci{
1271b0e7dd80Sopenharmony_ci    if (traceParamsStr.empty() || !IsNumber(traceParamsStr)) {
1272b0e7dd80Sopenharmony_ci        HILOG_WARN(LOG_CORE, "Illegal input, traceParams initialized to null.");
1273b0e7dd80Sopenharmony_ci        traceParams = 0;
1274b0e7dd80Sopenharmony_ci        return;
1275b0e7dd80Sopenharmony_ci    }
1276b0e7dd80Sopenharmony_ci    traceParams = std::stoi(traceParamsStr);
1277b0e7dd80Sopenharmony_ci    if (traceParams <= 0) {
1278b0e7dd80Sopenharmony_ci        HILOG_WARN(LOG_CORE, "Illegal input, traceParams initialized to null.");
1279b0e7dd80Sopenharmony_ci        traceParams = 0;
1280b0e7dd80Sopenharmony_ci    }
1281b0e7dd80Sopenharmony_ci}
1282b0e7dd80Sopenharmony_ci
1283b0e7dd80Sopenharmony_ci/**
1284b0e7dd80Sopenharmony_ci * args: tags:tag1,tags2... tagGroups:group1,group2... clockType:boot bufferSize:1024 overwrite:1 output:filename
1285b0e7dd80Sopenharmony_ci * cmdTraceParams:  Save the above parameters
1286b0e7dd80Sopenharmony_ci*/
1287b0e7dd80Sopenharmony_cibool ParseArgs(const std::string &args, TraceParams &cmdTraceParams, const std::map<std::string, TagCategory> &allTags,
1288b0e7dd80Sopenharmony_ci               const std::map<std::string, std::vector<std::string>> &tagGroupTable)
1289b0e7dd80Sopenharmony_ci{
1290b0e7dd80Sopenharmony_ci    std::string userArgs = args;
1291b0e7dd80Sopenharmony_ci    std::string str = ":";
1292b0e7dd80Sopenharmony_ci    RemoveUnSpace(str, userArgs);
1293b0e7dd80Sopenharmony_ci    str = ",";
1294b0e7dd80Sopenharmony_ci    RemoveUnSpace(str, userArgs);
1295b0e7dd80Sopenharmony_ci    std::vector<std::string> argList = Split(userArgs, ' ');
1296b0e7dd80Sopenharmony_ci    for (std::string item : argList) {
1297b0e7dd80Sopenharmony_ci        size_t pos = item.find(":");
1298b0e7dd80Sopenharmony_ci        if (pos == std::string::npos) {
1299b0e7dd80Sopenharmony_ci            HILOG_ERROR(LOG_CORE, "trace command line without colon appears: %{public}s, continue.", item.c_str());
1300b0e7dd80Sopenharmony_ci            continue;
1301b0e7dd80Sopenharmony_ci        }
1302b0e7dd80Sopenharmony_ci        std::string itemName = item.substr(0, pos);
1303b0e7dd80Sopenharmony_ci        if (itemName == "tags") {
1304b0e7dd80Sopenharmony_ci            cmdTraceParams.tags = Split(item.substr(pos + 1), ',');
1305b0e7dd80Sopenharmony_ci        } else if (itemName == "tagGroups") {
1306b0e7dd80Sopenharmony_ci            cmdTraceParams.tagGroups = Split(item.substr(pos + 1), ',');
1307b0e7dd80Sopenharmony_ci        } else if (itemName == "clockType") {
1308b0e7dd80Sopenharmony_ci            cmdTraceParams.clockType = item.substr(pos + 1);
1309b0e7dd80Sopenharmony_ci        } else if (itemName == "bufferSize") {
1310b0e7dd80Sopenharmony_ci            cmdTraceParams.bufferSize = item.substr(pos + 1);
1311b0e7dd80Sopenharmony_ci        } else if (itemName == "overwrite") {
1312b0e7dd80Sopenharmony_ci            cmdTraceParams.isOverWrite = item.substr(pos + 1);
1313b0e7dd80Sopenharmony_ci        } else if (itemName == "output") {
1314b0e7dd80Sopenharmony_ci            cmdTraceParams.outputFile = item.substr(pos + 1);
1315b0e7dd80Sopenharmony_ci        } else if (itemName == "fileSize") {
1316b0e7dd80Sopenharmony_ci            std::string fileSizeStr = item.substr(pos + 1);
1317b0e7dd80Sopenharmony_ci            SetCmdTraceIntParams(fileSizeStr, cmdTraceParams.fileSize);
1318b0e7dd80Sopenharmony_ci        } else if (itemName == "fileLimit") {
1319b0e7dd80Sopenharmony_ci            std::string fileLimitStr = item.substr(pos + 1);
1320b0e7dd80Sopenharmony_ci            SetCmdTraceIntParams(fileLimitStr, cmdTraceParams.fileLimit);
1321b0e7dd80Sopenharmony_ci        } else if (itemName == "appPid") {
1322b0e7dd80Sopenharmony_ci            std::string pidStr = item.substr(pos + 1);
1323b0e7dd80Sopenharmony_ci            SetCmdTraceIntParams(pidStr, cmdTraceParams.appPid);
1324b0e7dd80Sopenharmony_ci            if (cmdTraceParams.appPid == 0) {
1325b0e7dd80Sopenharmony_ci                HILOG_ERROR(LOG_CORE, "Illegal input, appPid(%{public}s) must be number and greater than 0.",
1326b0e7dd80Sopenharmony_ci                    pidStr.c_str());
1327b0e7dd80Sopenharmony_ci                return false;
1328b0e7dd80Sopenharmony_ci            }
1329b0e7dd80Sopenharmony_ci            OHOS::system::SetParameter("debug.hitrace.app_pid", pidStr);
1330b0e7dd80Sopenharmony_ci        } else {
1331b0e7dd80Sopenharmony_ci            HILOG_ERROR(LOG_CORE, "Extra trace command line options appear when ParseArgs: %{public}s, return false.",
1332b0e7dd80Sopenharmony_ci                itemName.c_str());
1333b0e7dd80Sopenharmony_ci            return false;
1334b0e7dd80Sopenharmony_ci        }
1335b0e7dd80Sopenharmony_ci    }
1336b0e7dd80Sopenharmony_ci    if (CheckTags(cmdTraceParams.tags, allTags) && CheckTagGroup(cmdTraceParams.tagGroups, tagGroupTable)) {
1337b0e7dd80Sopenharmony_ci        return true;
1338b0e7dd80Sopenharmony_ci    }
1339b0e7dd80Sopenharmony_ci    return false;
1340b0e7dd80Sopenharmony_ci}
1341b0e7dd80Sopenharmony_ci
1342b0e7dd80Sopenharmony_civoid WriteCpuFreqTrace()
1343b0e7dd80Sopenharmony_ci{
1344b0e7dd80Sopenharmony_ci    std::string freqsfmt = "cpu frequency: ";
1345b0e7dd80Sopenharmony_ci    ReadCurrentCpuFrequencies(freqsfmt);
1346b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "hitracedump write trace(%{public}s)", freqsfmt.c_str());
1347b0e7dd80Sopenharmony_ci    HITRACE_METER_NAME(HITRACE_TAG_OHOS, freqsfmt);
1348b0e7dd80Sopenharmony_ci}
1349b0e7dd80Sopenharmony_ci} // namespace
1350b0e7dd80Sopenharmony_ci
1351b0e7dd80Sopenharmony_ci#ifdef HITRACE_UNITTEST
1352b0e7dd80Sopenharmony_civoid SetSysInitParamTags(uint64_t sysInitParamTags)
1353b0e7dd80Sopenharmony_ci{
1354b0e7dd80Sopenharmony_ci    g_sysInitParamTags = sysInitParamTags;
1355b0e7dd80Sopenharmony_ci}
1356b0e7dd80Sopenharmony_ci
1357b0e7dd80Sopenharmony_cibool SetCheckParam()
1358b0e7dd80Sopenharmony_ci{
1359b0e7dd80Sopenharmony_ci    int ret = CheckParam();
1360b0e7dd80Sopenharmony_ci    return ret;
1361b0e7dd80Sopenharmony_ci}
1362b0e7dd80Sopenharmony_ci#endif
1363b0e7dd80Sopenharmony_ci
1364b0e7dd80Sopenharmony_ciTraceMode GetTraceMode()
1365b0e7dd80Sopenharmony_ci{
1366b0e7dd80Sopenharmony_ci    return g_traceMode;
1367b0e7dd80Sopenharmony_ci}
1368b0e7dd80Sopenharmony_ci
1369b0e7dd80Sopenharmony_ciTraceErrorCode OpenTrace(const std::vector<std::string> &tagGroups)
1370b0e7dd80Sopenharmony_ci{
1371b0e7dd80Sopenharmony_ci    if (g_traceMode != CLOSE) {
1372b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "OpenTrace: CALL_ERROR, g_traceMode:%{public}d.", static_cast<int>(g_traceMode));
1373b0e7dd80Sopenharmony_ci        return CALL_ERROR;
1374b0e7dd80Sopenharmony_ci    }
1375b0e7dd80Sopenharmony_ci    std::lock_guard<std::mutex> lock(g_traceMutex);
1376b0e7dd80Sopenharmony_ci    if (!IsTraceMounted()) {
1377b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "OpenTrace: TRACE_NOT_SUPPORTED.");
1378b0e7dd80Sopenharmony_ci        return TRACE_NOT_SUPPORTED;
1379b0e7dd80Sopenharmony_ci    }
1380b0e7dd80Sopenharmony_ci
1381b0e7dd80Sopenharmony_ci    std::map<std::string, TagCategory> allTags;
1382b0e7dd80Sopenharmony_ci    std::map<std::string, std::vector<std::string>> tagGroupTable;
1383b0e7dd80Sopenharmony_ci    if (!ParseTagInfo(allTags, tagGroupTable)) {
1384b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "OpenTrace: ParseTagInfo TAG_ERROR.");
1385b0e7dd80Sopenharmony_ci        return TAG_ERROR;
1386b0e7dd80Sopenharmony_ci    }
1387b0e7dd80Sopenharmony_ci
1388b0e7dd80Sopenharmony_ci    if (tagGroups.size() == 0 || !CheckTagGroup(tagGroups, tagGroupTable)) {
1389b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "OpenTrace: TAG_ERROR.");
1390b0e7dd80Sopenharmony_ci        return TAG_ERROR;
1391b0e7dd80Sopenharmony_ci    }
1392b0e7dd80Sopenharmony_ci
1393b0e7dd80Sopenharmony_ci    TraceErrorCode ret = HandleServiceTraceOpen(tagGroups, allTags, tagGroupTable);
1394b0e7dd80Sopenharmony_ci    if (ret != SUCCESS) {
1395b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "OpenTrace: open fail.");
1396b0e7dd80Sopenharmony_ci        return ret;
1397b0e7dd80Sopenharmony_ci    }
1398b0e7dd80Sopenharmony_ci    g_traceMode = SERVICE_MODE;
1399b0e7dd80Sopenharmony_ci
1400b0e7dd80Sopenharmony_ci    DelSnapshotTraceFile();
1401b0e7dd80Sopenharmony_ci    if (!IsHmKernel() && !g_serviceThreadIsStart) {
1402b0e7dd80Sopenharmony_ci        // open SERVICE_MODE monitor thread
1403b0e7dd80Sopenharmony_ci        auto it = []() {
1404b0e7dd80Sopenharmony_ci            MonitorServiceTask();
1405b0e7dd80Sopenharmony_ci        };
1406b0e7dd80Sopenharmony_ci        std::thread auxiliaryTask(it);
1407b0e7dd80Sopenharmony_ci        auxiliaryTask.detach();
1408b0e7dd80Sopenharmony_ci    }
1409b0e7dd80Sopenharmony_ci    g_sysInitParamTags = GetSysParamTags();
1410b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "OpenTrace: SERVICE_MODE open success.");
1411b0e7dd80Sopenharmony_ci    return ret;
1412b0e7dd80Sopenharmony_ci}
1413b0e7dd80Sopenharmony_ci
1414b0e7dd80Sopenharmony_ciTraceErrorCode OpenTrace(const std::string &args)
1415b0e7dd80Sopenharmony_ci{
1416b0e7dd80Sopenharmony_ci    std::lock_guard<std::mutex> lock(g_traceMutex);
1417b0e7dd80Sopenharmony_ci    if (g_traceMode != CLOSE) {
1418b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "OpenTrace: CALL_ERROR, g_traceMode:%{public}d.", static_cast<int>(g_traceMode));
1419b0e7dd80Sopenharmony_ci        return CALL_ERROR;
1420b0e7dd80Sopenharmony_ci    }
1421b0e7dd80Sopenharmony_ci
1422b0e7dd80Sopenharmony_ci    if (!IsTraceMounted()) {
1423b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "Hitrace OpenTrace: TRACE_NOT_SUPPORTED.");
1424b0e7dd80Sopenharmony_ci        return TRACE_NOT_SUPPORTED;
1425b0e7dd80Sopenharmony_ci    }
1426b0e7dd80Sopenharmony_ci
1427b0e7dd80Sopenharmony_ci    std::map<std::string, TagCategory> allTags;
1428b0e7dd80Sopenharmony_ci    std::map<std::string, std::vector<std::string>> tagGroupTable;
1429b0e7dd80Sopenharmony_ci    if (!ParseTagInfo(allTags, tagGroupTable) || allTags.size() == 0 || tagGroupTable.size() == 0) {
1430b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "Hitrace OpenTrace: ParseTagInfo TAG_ERROR.");
1431b0e7dd80Sopenharmony_ci        return TAG_ERROR;
1432b0e7dd80Sopenharmony_ci    }
1433b0e7dd80Sopenharmony_ci    // parse args
1434b0e7dd80Sopenharmony_ci    TraceParams cmdTraceParams;
1435b0e7dd80Sopenharmony_ci    if (!ParseArgs(args, cmdTraceParams, allTags, tagGroupTable)) {
1436b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "Hitrace OpenTrace: TAG_ERROR.");
1437b0e7dd80Sopenharmony_ci        return TAG_ERROR;
1438b0e7dd80Sopenharmony_ci    }
1439b0e7dd80Sopenharmony_ci
1440b0e7dd80Sopenharmony_ci    TraceErrorCode ret = HandleTraceOpen(cmdTraceParams, allTags, tagGroupTable);
1441b0e7dd80Sopenharmony_ci    if (ret != SUCCESS) {
1442b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "Hitrace OpenTrace: CMD_MODE open failed.");
1443b0e7dd80Sopenharmony_ci        return FILE_ERROR;
1444b0e7dd80Sopenharmony_ci    }
1445b0e7dd80Sopenharmony_ci    g_traceMode = CMD_MODE;
1446b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "Hitrace OpenTrace: CMD_MODE open success, args:%{public}s.", args.c_str());
1447b0e7dd80Sopenharmony_ci    return ret;
1448b0e7dd80Sopenharmony_ci}
1449b0e7dd80Sopenharmony_ci
1450b0e7dd80Sopenharmony_ciTraceRetInfo DumpTrace()
1451b0e7dd80Sopenharmony_ci{
1452b0e7dd80Sopenharmony_ci    TraceRetInfo ret;
1453b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "DumpTrace start.");
1454b0e7dd80Sopenharmony_ci    if (g_traceMode != SERVICE_MODE) {
1455b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "DumpTrace: CALL_ERROR, g_traceMode:%{public}d.", static_cast<int>(g_traceMode));
1456b0e7dd80Sopenharmony_ci        ret.errorCode = CALL_ERROR;
1457b0e7dd80Sopenharmony_ci        return ret;
1458b0e7dd80Sopenharmony_ci    }
1459b0e7dd80Sopenharmony_ci
1460b0e7dd80Sopenharmony_ci    if (!CheckServiceRunning()) {
1461b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "DumpTrace: TRACE_IS_OCCUPIED.");
1462b0e7dd80Sopenharmony_ci        ret.errorCode = TRACE_IS_OCCUPIED;
1463b0e7dd80Sopenharmony_ci        return ret;
1464b0e7dd80Sopenharmony_ci    }
1465b0e7dd80Sopenharmony_ci    std::lock_guard<std::mutex> lock(g_traceMutex);
1466b0e7dd80Sopenharmony_ci    g_dumpStatus = TraceErrorCode::UNSET;
1467b0e7dd80Sopenharmony_ci    SetTimeIntervalBoundary();
1468b0e7dd80Sopenharmony_ci    ret.errorCode = DumpTraceInner(ret.outputFiles);
1469b0e7dd80Sopenharmony_ci    RestoreTimeIntervalBoundary();
1470b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "DumpTrace done.");
1471b0e7dd80Sopenharmony_ci    return ret;
1472b0e7dd80Sopenharmony_ci}
1473b0e7dd80Sopenharmony_ci
1474b0e7dd80Sopenharmony_ciTraceRetInfo DumpTrace(int maxDuration, uint64_t traceEndTime)
1475b0e7dd80Sopenharmony_ci{
1476b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "DumpTrace with timelimit start, timelimit is %{public}d, endtime is (%{public}" PRId64 ").",
1477b0e7dd80Sopenharmony_ci        maxDuration, traceEndTime);
1478b0e7dd80Sopenharmony_ci    TraceRetInfo ret;
1479b0e7dd80Sopenharmony_ci    if (maxDuration < 0) {
1480b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "DumpTrace: Illegal input.");
1481b0e7dd80Sopenharmony_ci        ret.errorCode = CALL_ERROR;
1482b0e7dd80Sopenharmony_ci        return ret;
1483b0e7dd80Sopenharmony_ci    }
1484b0e7dd80Sopenharmony_ci    {
1485b0e7dd80Sopenharmony_ci        std::time_t now = std::time(nullptr);
1486b0e7dd80Sopenharmony_ci        if (maxDuration > (now - 1)) {
1487b0e7dd80Sopenharmony_ci            maxDuration = 0;
1488b0e7dd80Sopenharmony_ci        }
1489b0e7dd80Sopenharmony_ci        std::lock_guard<std::mutex> lock(g_traceMutex);
1490b0e7dd80Sopenharmony_ci        if (traceEndTime > 0) {
1491b0e7dd80Sopenharmony_ci            if (traceEndTime > static_cast<uint64_t>(now)) {
1492b0e7dd80Sopenharmony_ci                HILOG_WARN(LOG_CORE, "DumpTrace: Warning: traceEndTime is later than current time.");
1493b0e7dd80Sopenharmony_ci            }
1494b0e7dd80Sopenharmony_ci            struct sysinfo info;
1495b0e7dd80Sopenharmony_ci            if (sysinfo(&info) != 0) {
1496b0e7dd80Sopenharmony_ci                HILOG_ERROR(LOG_CORE, "Get system info failed.");
1497b0e7dd80Sopenharmony_ci                ret.errorCode = UNKNOWN_ERROR;
1498b0e7dd80Sopenharmony_ci                return ret;
1499b0e7dd80Sopenharmony_ci            }
1500b0e7dd80Sopenharmony_ci            std::time_t boot_time = now - info.uptime;
1501b0e7dd80Sopenharmony_ci            if (traceEndTime > static_cast<uint64_t>(boot_time)) {
1502b0e7dd80Sopenharmony_ci                // beware of input precision of seconds: add an extra second of tolerance
1503b0e7dd80Sopenharmony_ci                g_inputTraceEndTime = (traceEndTime - static_cast<uint64_t>(boot_time) + 1) * S_TO_NS;
1504b0e7dd80Sopenharmony_ci            } else {
1505b0e7dd80Sopenharmony_ci                HILOG_ERROR(LOG_CORE,
1506b0e7dd80Sopenharmony_ci                    "DumpTrace: traceEndTime:(%{public}" PRId64 ") is earlier than boot_time:(%{public}" PRId64 ").",
1507b0e7dd80Sopenharmony_ci                    traceEndTime, static_cast<uint64_t>(boot_time));
1508b0e7dd80Sopenharmony_ci                ret.errorCode = OUT_OF_TIME;
1509b0e7dd80Sopenharmony_ci                return ret;
1510b0e7dd80Sopenharmony_ci            }
1511b0e7dd80Sopenharmony_ci            g_inputMaxDuration = maxDuration ? maxDuration + 1 : 0; // for precision tolerance
1512b0e7dd80Sopenharmony_ci        } else {
1513b0e7dd80Sopenharmony_ci            g_inputMaxDuration = maxDuration;
1514b0e7dd80Sopenharmony_ci        }
1515b0e7dd80Sopenharmony_ci    }
1516b0e7dd80Sopenharmony_ci    ret = DumpTrace();
1517b0e7dd80Sopenharmony_ci    {
1518b0e7dd80Sopenharmony_ci        std::lock_guard<std::mutex> lock(g_traceMutex);
1519b0e7dd80Sopenharmony_ci        g_inputMaxDuration = 0;
1520b0e7dd80Sopenharmony_ci        g_inputTraceEndTime = 0;
1521b0e7dd80Sopenharmony_ci    }
1522b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "DumpTrace with time limit done.");
1523b0e7dd80Sopenharmony_ci    return ret;
1524b0e7dd80Sopenharmony_ci}
1525b0e7dd80Sopenharmony_ci
1526b0e7dd80Sopenharmony_ciTraceErrorCode DumpTraceOn()
1527b0e7dd80Sopenharmony_ci{
1528b0e7dd80Sopenharmony_ci    std::lock_guard<std::mutex> lock(g_traceMutex);
1529b0e7dd80Sopenharmony_ci    // check current trace status
1530b0e7dd80Sopenharmony_ci    if (g_traceMode != CMD_MODE) {
1531b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "DumpTraceOn: CALL_ERROR, g_traceMode:%{public}d.", static_cast<int>(g_traceMode));
1532b0e7dd80Sopenharmony_ci        return CALL_ERROR;
1533b0e7dd80Sopenharmony_ci    }
1534b0e7dd80Sopenharmony_ci
1535b0e7dd80Sopenharmony_ci    if (!g_dumpEnd) {
1536b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "DumpTraceOn: CALL_ERROR, record trace is dumping now.");
1537b0e7dd80Sopenharmony_ci        return CALL_ERROR;
1538b0e7dd80Sopenharmony_ci    }
1539b0e7dd80Sopenharmony_ci
1540b0e7dd80Sopenharmony_ci    // start task thread
1541b0e7dd80Sopenharmony_ci    auto it = []() {
1542b0e7dd80Sopenharmony_ci        ProcessDumpTask();
1543b0e7dd80Sopenharmony_ci    };
1544b0e7dd80Sopenharmony_ci    std::thread task(it);
1545b0e7dd80Sopenharmony_ci    task.detach();
1546b0e7dd80Sopenharmony_ci    WriteCpuFreqTrace();
1547b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "Recording trace on.");
1548b0e7dd80Sopenharmony_ci    return SUCCESS;
1549b0e7dd80Sopenharmony_ci}
1550b0e7dd80Sopenharmony_ci
1551b0e7dd80Sopenharmony_ciTraceRetInfo DumpTraceOff()
1552b0e7dd80Sopenharmony_ci{
1553b0e7dd80Sopenharmony_ci    std::lock_guard<std::mutex> lock(g_traceMutex);
1554b0e7dd80Sopenharmony_ci    TraceRetInfo ret;
1555b0e7dd80Sopenharmony_ci    // check current trace status
1556b0e7dd80Sopenharmony_ci    if (g_traceMode != CMD_MODE) {
1557b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "DumpTraceOff: The current state is %{public}d, data exception.",
1558b0e7dd80Sopenharmony_ci            static_cast<int>(g_traceMode));
1559b0e7dd80Sopenharmony_ci        ret.errorCode = CALL_ERROR;
1560b0e7dd80Sopenharmony_ci        ret.outputFiles = g_outputFilesForCmd;
1561b0e7dd80Sopenharmony_ci        return ret;
1562b0e7dd80Sopenharmony_ci    }
1563b0e7dd80Sopenharmony_ci
1564b0e7dd80Sopenharmony_ci    g_dumpFlag = false;
1565b0e7dd80Sopenharmony_ci    while (!g_dumpEnd) {
1566b0e7dd80Sopenharmony_ci        usleep(UNIT_TIME);
1567b0e7dd80Sopenharmony_ci        g_dumpFlag = false;
1568b0e7dd80Sopenharmony_ci    }
1569b0e7dd80Sopenharmony_ci    ret.errorCode = SUCCESS;
1570b0e7dd80Sopenharmony_ci    ret.outputFiles = g_outputFilesForCmd;
1571b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "Recording trace off.");
1572b0e7dd80Sopenharmony_ci    return ret;
1573b0e7dd80Sopenharmony_ci}
1574b0e7dd80Sopenharmony_ci
1575b0e7dd80Sopenharmony_ciTraceErrorCode CloseTrace()
1576b0e7dd80Sopenharmony_ci{
1577b0e7dd80Sopenharmony_ci    std::lock_guard<std::mutex> lock(g_traceMutex);
1578b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "CloseTrace start.");
1579b0e7dd80Sopenharmony_ci    if (g_traceMode == CLOSE) {
1580b0e7dd80Sopenharmony_ci        HILOG_INFO(LOG_CORE, "Trace already close.");
1581b0e7dd80Sopenharmony_ci        return SUCCESS;
1582b0e7dd80Sopenharmony_ci    }
1583b0e7dd80Sopenharmony_ci
1584b0e7dd80Sopenharmony_ci    g_traceMode = CLOSE;
1585b0e7dd80Sopenharmony_ci    // Waiting for the data drop task to end
1586b0e7dd80Sopenharmony_ci    g_dumpFlag = false;
1587b0e7dd80Sopenharmony_ci    while (!g_dumpEnd) {
1588b0e7dd80Sopenharmony_ci        usleep(UNIT_TIME);
1589b0e7dd80Sopenharmony_ci        g_dumpFlag = false;
1590b0e7dd80Sopenharmony_ci    }
1591b0e7dd80Sopenharmony_ci    OHOS::system::SetParameter("debug.hitrace.app_pid", "-1");
1592b0e7dd80Sopenharmony_ci    std::map<std::string, TagCategory> allTags;
1593b0e7dd80Sopenharmony_ci    std::map<std::string, std::vector<std::string>> tagGroupTable;
1594b0e7dd80Sopenharmony_ci    if (!ParseTagInfo(allTags, tagGroupTable) || allTags.size() == 0 || tagGroupTable.size() == 0) {
1595b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "CloseTrace: ParseTagInfo TAG_ERROR.");
1596b0e7dd80Sopenharmony_ci        return TAG_ERROR;
1597b0e7dd80Sopenharmony_ci    }
1598b0e7dd80Sopenharmony_ci    TraceInit(allTags);
1599b0e7dd80Sopenharmony_ci    TruncateFile();
1600b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "CloseTrace done.");
1601b0e7dd80Sopenharmony_ci    return SUCCESS;
1602b0e7dd80Sopenharmony_ci}
1603b0e7dd80Sopenharmony_ci
1604b0e7dd80Sopenharmony_cistd::vector<std::pair<std::string, int>> GetTraceFilesTable()
1605b0e7dd80Sopenharmony_ci{
1606b0e7dd80Sopenharmony_ci    return g_traceFilesTable;
1607b0e7dd80Sopenharmony_ci}
1608b0e7dd80Sopenharmony_ci
1609b0e7dd80Sopenharmony_civoid SetTraceFilesTable(const std::vector<std::pair<std::string, int>>& traceFilesTable)
1610b0e7dd80Sopenharmony_ci{
1611b0e7dd80Sopenharmony_ci    g_traceFilesTable = traceFilesTable;
1612b0e7dd80Sopenharmony_ci}
1613b0e7dd80Sopenharmony_ci} // Hitrace
1614b0e7dd80Sopenharmony_ci} // HiviewDFX
1615b0e7dd80Sopenharmony_ci} // OHOS
1616