1b0e7dd80Sopenharmony_ci/*
2b0e7dd80Sopenharmony_ci * Copyright (C) 2022-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 <cinttypes>
17b0e7dd80Sopenharmony_ci#include <csignal>
18b0e7dd80Sopenharmony_ci#include <cstdio>
19b0e7dd80Sopenharmony_ci#include <cstdlib>
20b0e7dd80Sopenharmony_ci#include <cstring>
21b0e7dd80Sopenharmony_ci#include <ctime>
22b0e7dd80Sopenharmony_ci#include <fcntl.h>
23b0e7dd80Sopenharmony_ci#include <fstream>
24b0e7dd80Sopenharmony_ci#include <getopt.h>
25b0e7dd80Sopenharmony_ci#include <map>
26b0e7dd80Sopenharmony_ci#include <regex>
27b0e7dd80Sopenharmony_ci#include <sstream>
28b0e7dd80Sopenharmony_ci#include <string>
29b0e7dd80Sopenharmony_ci#include <sys/stat.h>
30b0e7dd80Sopenharmony_ci#include <sys/types.h>
31b0e7dd80Sopenharmony_ci#include <thread>
32b0e7dd80Sopenharmony_ci#include <unistd.h>
33b0e7dd80Sopenharmony_ci#include <vector>
34b0e7dd80Sopenharmony_ci#include <memory>
35b0e7dd80Sopenharmony_ci#include <iostream>
36b0e7dd80Sopenharmony_ci#include <zlib.h>
37b0e7dd80Sopenharmony_ci
38b0e7dd80Sopenharmony_ci#include "hitrace_meter.h"
39b0e7dd80Sopenharmony_ci#include "common_utils.h"
40b0e7dd80Sopenharmony_ci#include "trace_collector_client.h"
41b0e7dd80Sopenharmony_ci#include "hitrace_osal.h"
42b0e7dd80Sopenharmony_ci#include "securec.h"
43b0e7dd80Sopenharmony_ci
44b0e7dd80Sopenharmony_ciusing namespace std;
45b0e7dd80Sopenharmony_ciusing namespace OHOS::HiviewDFX::HitraceOsal;
46b0e7dd80Sopenharmony_ci
47b0e7dd80Sopenharmony_cinamespace {
48b0e7dd80Sopenharmony_ci
49b0e7dd80Sopenharmony_cistruct TraceArgs {
50b0e7dd80Sopenharmony_ci    std::string tags;
51b0e7dd80Sopenharmony_ci    std::string tagGroups;
52b0e7dd80Sopenharmony_ci    std::string clockType;
53b0e7dd80Sopenharmony_ci    int bufferSize = 0;
54b0e7dd80Sopenharmony_ci    int fileSize = 0;
55b0e7dd80Sopenharmony_ci    bool overwrite = true;
56b0e7dd80Sopenharmony_ci    std::string output;
57b0e7dd80Sopenharmony_ci
58b0e7dd80Sopenharmony_ci    int duration = 0;
59b0e7dd80Sopenharmony_ci    bool isCompress = false;
60b0e7dd80Sopenharmony_ci};
61b0e7dd80Sopenharmony_ci
62b0e7dd80Sopenharmony_cienum RunningState {
63b0e7dd80Sopenharmony_ci    /* Initial value */
64b0e7dd80Sopenharmony_ci    STATE_NULL = 0,
65b0e7dd80Sopenharmony_ci
66b0e7dd80Sopenharmony_ci    /* Record a short trace */
67b0e7dd80Sopenharmony_ci    RECORDING_SHORT_TEXT = 1,  // --text
68b0e7dd80Sopenharmony_ci    RECORDING_SHORT_RAW = 2,  // --raw
69b0e7dd80Sopenharmony_ci
70b0e7dd80Sopenharmony_ci    /* Record a long trace */
71b0e7dd80Sopenharmony_ci    RECORDING_LONG_BEGIN = 10,  // --trace_begin
72b0e7dd80Sopenharmony_ci    RECORDING_LONG_DUMP = 11,  // --trace_dump
73b0e7dd80Sopenharmony_ci    RECORDING_LONG_FINISH = 12,  // --trace_finish
74b0e7dd80Sopenharmony_ci    RECORDING_LONG_FINISH_NODUMP = 13,  // --trace_finish_nodump
75b0e7dd80Sopenharmony_ci    RECORDING_LONG_BEGIN_RECORD = 14,  // --trace_begin --record
76b0e7dd80Sopenharmony_ci    RECORDING_LONG_FINISH_RECORD = 15,  // --trace_finish --record
77b0e7dd80Sopenharmony_ci
78b0e7dd80Sopenharmony_ci    /* Manipulating trace services in snapshot mode */
79b0e7dd80Sopenharmony_ci    SNAPSHOT_START = 20,  // --start_bgsrv
80b0e7dd80Sopenharmony_ci    SNAPSHOT_DUMP = 21,  // --dump_bgsrv
81b0e7dd80Sopenharmony_ci    SNAPSHOT_STOP = 22,  // --stop_bgsrv
82b0e7dd80Sopenharmony_ci
83b0e7dd80Sopenharmony_ci    /* Help Info */
84b0e7dd80Sopenharmony_ci    SHOW_HELP = 31,  // -h, --help
85b0e7dd80Sopenharmony_ci    SHOW_LIST_CATEGORY = 32,  // -l, --list_categories
86b0e7dd80Sopenharmony_ci};
87b0e7dd80Sopenharmony_ci
88b0e7dd80Sopenharmony_ciconst std::map<RunningState, std::string> STATE_INFO = {
89b0e7dd80Sopenharmony_ci    { STATE_NULL, "STATE_NULL" },
90b0e7dd80Sopenharmony_ci    { RECORDING_SHORT_TEXT, "RECORDING_SHORT_TEXT" },
91b0e7dd80Sopenharmony_ci    { RECORDING_SHORT_RAW, "RECORDING_SHORT_RAW" },
92b0e7dd80Sopenharmony_ci    { RECORDING_LONG_BEGIN, "RECORDING_LONG_BEGIN" },
93b0e7dd80Sopenharmony_ci    { RECORDING_LONG_DUMP, "RECORDING_LONG_DUMP" },
94b0e7dd80Sopenharmony_ci    { RECORDING_LONG_FINISH_NODUMP, "RECORDING_LONG_FINISH_NODUMP" },
95b0e7dd80Sopenharmony_ci    { RECORDING_LONG_BEGIN_RECORD, "RECORDING_LONG_BEGIN_RECORD" },
96b0e7dd80Sopenharmony_ci    { RECORDING_LONG_FINISH_RECORD, "RECORDING_LONG_FINISH_RECORD" },
97b0e7dd80Sopenharmony_ci    { SNAPSHOT_START, "SNAPSHOT_START" },
98b0e7dd80Sopenharmony_ci    { SNAPSHOT_DUMP, "SNAPSHOT_DUMP" },
99b0e7dd80Sopenharmony_ci    { SNAPSHOT_STOP, "SNAPSHOT_STOP" },
100b0e7dd80Sopenharmony_ci    { SHOW_HELP, "SHOW_HELP" },
101b0e7dd80Sopenharmony_ci    { SHOW_LIST_CATEGORY, "SHOW_LIST_CATEGORY" },
102b0e7dd80Sopenharmony_ci};
103b0e7dd80Sopenharmony_ci
104b0e7dd80Sopenharmony_ciconstexpr struct option LONG_OPTIONS[] = {
105b0e7dd80Sopenharmony_ci    { "buffer_size",       required_argument, nullptr, 0 },
106b0e7dd80Sopenharmony_ci    { "trace_clock",       required_argument, nullptr, 0 },
107b0e7dd80Sopenharmony_ci    { "help",              no_argument,       nullptr, 0 },
108b0e7dd80Sopenharmony_ci    { "output",            required_argument, nullptr, 0 },
109b0e7dd80Sopenharmony_ci    { "time",              required_argument, nullptr, 0 },
110b0e7dd80Sopenharmony_ci    { "text",              no_argument,       nullptr, 0 },
111b0e7dd80Sopenharmony_ci    { "raw",               no_argument,       nullptr, 0 },
112b0e7dd80Sopenharmony_ci    { "trace_begin",       no_argument,       nullptr, 0 },
113b0e7dd80Sopenharmony_ci    { "trace_finish",      no_argument,       nullptr, 0 },
114b0e7dd80Sopenharmony_ci    { "trace_finish_nodump",      no_argument,       nullptr, 0 },
115b0e7dd80Sopenharmony_ci    { "record",            no_argument,       nullptr, 0 },
116b0e7dd80Sopenharmony_ci    { "trace_dump",        no_argument,       nullptr, 0 },
117b0e7dd80Sopenharmony_ci    { "list_categories",   no_argument,       nullptr, 0 },
118b0e7dd80Sopenharmony_ci    { "overwrite",         no_argument,       nullptr, 0 },
119b0e7dd80Sopenharmony_ci    { "start_bgsrv",       no_argument,       nullptr, 0 },
120b0e7dd80Sopenharmony_ci    { "dump_bgsrv",        no_argument,       nullptr, 0 },
121b0e7dd80Sopenharmony_ci    { "stop_bgsrv",        no_argument,       nullptr, 0 },
122b0e7dd80Sopenharmony_ci    { "file_size",         required_argument, nullptr, 0 },
123b0e7dd80Sopenharmony_ci    { nullptr,             0,                 nullptr, 0 },
124b0e7dd80Sopenharmony_ci};
125b0e7dd80Sopenharmony_ciconst unsigned int CHUNK_SIZE = 65536;
126b0e7dd80Sopenharmony_ci
127b0e7dd80Sopenharmony_ciconstexpr const char *TRACE_TAG_PROPERTY = "debug.hitrace.tags.enableflags";
128b0e7dd80Sopenharmony_ci
129b0e7dd80Sopenharmony_ci// various operating paths of ftrace
130b0e7dd80Sopenharmony_ciconstexpr const char *TRACING_ON_PATH = "tracing_on";
131b0e7dd80Sopenharmony_ciconstexpr const char *TRACE_PATH = "trace";
132b0e7dd80Sopenharmony_ciconstexpr const char *TRACE_MARKER_PATH = "trace_marker";
133b0e7dd80Sopenharmony_ci
134b0e7dd80Sopenharmony_ci// support customization of some parameters
135b0e7dd80Sopenharmony_ciconst int KB_PER_MB = 1024;
136b0e7dd80Sopenharmony_ciconst int MIN_BUFFER_SIZE = 256;
137b0e7dd80Sopenharmony_ciconst int MAX_BUFFER_SIZE = 307200; // 300 MB
138b0e7dd80Sopenharmony_ciconst int HM_MAX_BUFFER_SIZE = 1024 * KB_PER_MB; // 1024 MB
139b0e7dd80Sopenharmony_ciconst int DEFAULT_BUFFER_SIZE = 18432; // 18 MB
140b0e7dd80Sopenharmony_ciconstexpr unsigned int MAX_OUTPUT_LEN = 255;
141b0e7dd80Sopenharmony_ciconst int PAGE_SIZE_KB = 4; // 4 KB
142b0e7dd80Sopenharmony_ciconst int MIN_FILE_SIZE = 51200; // 50 MB
143b0e7dd80Sopenharmony_ciconst int MAX_FILE_SIZE = 512000; // 500 MB
144b0e7dd80Sopenharmony_ci
145b0e7dd80Sopenharmony_cistring g_traceRootPath;
146b0e7dd80Sopenharmony_ci
147b0e7dd80Sopenharmony_cistd::shared_ptr<OHOS::HiviewDFX::UCollectClient::TraceCollector> g_traceCollector;
148b0e7dd80Sopenharmony_ci
149b0e7dd80Sopenharmony_ciTraceArgs g_traceArgs;
150b0e7dd80Sopenharmony_cistd::map<std::string, OHOS::HiviewDFX::Hitrace::TagCategory> g_allTags;
151b0e7dd80Sopenharmony_cistd::map<std::string, std::vector<std::string>> g_allTagGroups;
152b0e7dd80Sopenharmony_ciRunningState g_runningState = STATE_NULL;
153b0e7dd80Sopenharmony_ci}
154b0e7dd80Sopenharmony_ci
155b0e7dd80Sopenharmony_cistatic void ConsoleLog(const std::string& logInfo)
156b0e7dd80Sopenharmony_ci{
157b0e7dd80Sopenharmony_ci    // get localtime
158b0e7dd80Sopenharmony_ci    time_t currentTime;
159b0e7dd80Sopenharmony_ci    time(&currentTime);
160b0e7dd80Sopenharmony_ci    struct tm timeInfo = {};
161b0e7dd80Sopenharmony_ci    const int bufferSize = 20;
162b0e7dd80Sopenharmony_ci    char timeStr[bufferSize] = {0};
163b0e7dd80Sopenharmony_ci    localtime_r(&currentTime, &timeInfo);
164b0e7dd80Sopenharmony_ci    strftime(timeStr, bufferSize, "%Y/%m/%d %H:%M:%S", &timeInfo);
165b0e7dd80Sopenharmony_ci    std::cout << timeStr << " " << logInfo << std::endl;
166b0e7dd80Sopenharmony_ci}
167b0e7dd80Sopenharmony_ci
168b0e7dd80Sopenharmony_cistatic std::string GetStateInfo(const RunningState state)
169b0e7dd80Sopenharmony_ci{
170b0e7dd80Sopenharmony_ci    if (STATE_INFO.find(state) == STATE_INFO.end()) {
171b0e7dd80Sopenharmony_ci        ConsoleLog("error: running_state is invalid.");
172b0e7dd80Sopenharmony_ci        return "";
173b0e7dd80Sopenharmony_ci    }
174b0e7dd80Sopenharmony_ci    return STATE_INFO.at(state);
175b0e7dd80Sopenharmony_ci}
176b0e7dd80Sopenharmony_ci
177b0e7dd80Sopenharmony_cistatic bool IsTraceMounted()
178b0e7dd80Sopenharmony_ci{
179b0e7dd80Sopenharmony_ci    const string debugfsPath = "/sys/kernel/debug/tracing/";
180b0e7dd80Sopenharmony_ci    const string tracefsPath = "/sys/kernel/tracing/";
181b0e7dd80Sopenharmony_ci
182b0e7dd80Sopenharmony_ci    if (access((debugfsPath + TRACE_MARKER_PATH).c_str(), F_OK) != -1) {
183b0e7dd80Sopenharmony_ci        g_traceRootPath = debugfsPath;
184b0e7dd80Sopenharmony_ci        return true;
185b0e7dd80Sopenharmony_ci    }
186b0e7dd80Sopenharmony_ci    if (access((tracefsPath + TRACE_MARKER_PATH).c_str(), F_OK) != -1) {
187b0e7dd80Sopenharmony_ci        g_traceRootPath = tracefsPath;
188b0e7dd80Sopenharmony_ci        return true;
189b0e7dd80Sopenharmony_ci    }
190b0e7dd80Sopenharmony_ci    return false;
191b0e7dd80Sopenharmony_ci}
192b0e7dd80Sopenharmony_ci
193b0e7dd80Sopenharmony_cistatic bool WriteStrToFile(const string& filename, const std::string& str)
194b0e7dd80Sopenharmony_ci{
195b0e7dd80Sopenharmony_ci    ofstream out;
196b0e7dd80Sopenharmony_ci    std::string inSpecPath =
197b0e7dd80Sopenharmony_ci        OHOS::HiviewDFX::Hitrace::CanonicalizeSpecPath((g_traceRootPath + filename).c_str());
198b0e7dd80Sopenharmony_ci    out.open(inSpecPath, ios::out);
199b0e7dd80Sopenharmony_ci    if (out.fail()) {
200b0e7dd80Sopenharmony_ci        ConsoleLog("error: open " + inSpecPath + " failed.");
201b0e7dd80Sopenharmony_ci        return false;
202b0e7dd80Sopenharmony_ci    }
203b0e7dd80Sopenharmony_ci    out << str;
204b0e7dd80Sopenharmony_ci    if (out.bad()) {
205b0e7dd80Sopenharmony_ci        ConsoleLog("error: can not write " + inSpecPath);
206b0e7dd80Sopenharmony_ci        out.close();
207b0e7dd80Sopenharmony_ci        return false;
208b0e7dd80Sopenharmony_ci    }
209b0e7dd80Sopenharmony_ci    out.flush();
210b0e7dd80Sopenharmony_ci    out.close();
211b0e7dd80Sopenharmony_ci    return true;
212b0e7dd80Sopenharmony_ci}
213b0e7dd80Sopenharmony_ci
214b0e7dd80Sopenharmony_cistatic bool SetFtraceEnabled(const string& path, bool enabled)
215b0e7dd80Sopenharmony_ci{
216b0e7dd80Sopenharmony_ci    return WriteStrToFile(path, enabled ? "1" : "0");
217b0e7dd80Sopenharmony_ci}
218b0e7dd80Sopenharmony_ci
219b0e7dd80Sopenharmony_cistatic bool SetProperty(const string& property, const string& value)
220b0e7dd80Sopenharmony_ci{
221b0e7dd80Sopenharmony_ci    return SetPropertyInner(property, value);
222b0e7dd80Sopenharmony_ci}
223b0e7dd80Sopenharmony_ci
224b0e7dd80Sopenharmony_cistatic bool SetTraceTagsEnabled(uint64_t tags)
225b0e7dd80Sopenharmony_ci{
226b0e7dd80Sopenharmony_ci    string value = std::to_string(tags);
227b0e7dd80Sopenharmony_ci    return SetProperty(TRACE_TAG_PROPERTY, value);
228b0e7dd80Sopenharmony_ci}
229b0e7dd80Sopenharmony_ci
230b0e7dd80Sopenharmony_cistatic void ShowListCategory()
231b0e7dd80Sopenharmony_ci{
232b0e7dd80Sopenharmony_ci    printf("  %18s   description:\n", "tagName:");
233b0e7dd80Sopenharmony_ci    for (auto it = g_allTags.begin(); it != g_allTags.end(); ++it) {
234b0e7dd80Sopenharmony_ci        printf("  %18s - %s\n", it->first.c_str(), it->second.description.c_str());
235b0e7dd80Sopenharmony_ci    }
236b0e7dd80Sopenharmony_ci}
237b0e7dd80Sopenharmony_ci
238b0e7dd80Sopenharmony_cistatic void ShowHelp(const string& cmd)
239b0e7dd80Sopenharmony_ci{
240b0e7dd80Sopenharmony_ci    printf("usage: %s [options] [categories...]\n", cmd.c_str());
241b0e7dd80Sopenharmony_ci    printf("options include:\n"
242b0e7dd80Sopenharmony_ci           "  -b N               Sets the size of the buffer (KB) for storing and reading traces. The default \n"
243b0e7dd80Sopenharmony_ci           "                     buffer size is 18432 KB.\n"
244b0e7dd80Sopenharmony_ci           "  --buffer_size N    Like \"-b N\".\n"
245b0e7dd80Sopenharmony_ci           "  -l                 Lists available hitrace categories.\n"
246b0e7dd80Sopenharmony_ci           "  --list_categories  Like \"-l\".\n"
247b0e7dd80Sopenharmony_ci           "  -t N               Sets the hitrace running duration in seconds (5s by default), which depends on \n"
248b0e7dd80Sopenharmony_ci           "                     the time required for analysis.\n"
249b0e7dd80Sopenharmony_ci           "  --time N           Like \"-t N\".\n"
250b0e7dd80Sopenharmony_ci           "  --trace_clock clock\n"
251b0e7dd80Sopenharmony_ci           "                     Sets the type of the clock for adding a timestamp to a trace, which can be\n"
252b0e7dd80Sopenharmony_ci           "                     boot (default), global, mono, uptime, or perf.\n"
253b0e7dd80Sopenharmony_ci           "  --trace_begin      Starts capturing traces.\n"
254b0e7dd80Sopenharmony_ci           "  --trace_dump       Dumps traces to a specified path (stdout by default).\n"
255b0e7dd80Sopenharmony_ci           "  --trace_finish     Stops capturing traces and dumps traces to a specified path (stdout by default).\n"
256b0e7dd80Sopenharmony_ci           "  --trace_finish_nodump\n"
257b0e7dd80Sopenharmony_ci           "                     Stops capturing traces and not dumps traces.\n"
258b0e7dd80Sopenharmony_ci           "  --record           Enable or disable long-term trace collection tasks in conjunction with\n"
259b0e7dd80Sopenharmony_ci           "                    \"--trace_begin\" and \"--trace_finish\".\n"
260b0e7dd80Sopenharmony_ci           "  --overwrite        Sets the action to take when the buffer is full. If this option is used,\n"
261b0e7dd80Sopenharmony_ci           "                     the latest traces are discarded; if this option is not used (default setting),\n"
262b0e7dd80Sopenharmony_ci           "                     the earliest traces are discarded.\n"
263b0e7dd80Sopenharmony_ci           "  -o filename        Specifies the name of the target file (stdout by default).\n"
264b0e7dd80Sopenharmony_ci           "  --output filename\n"
265b0e7dd80Sopenharmony_ci           "                     Like \"-o filename\".\n"
266b0e7dd80Sopenharmony_ci           "  -z                 Compresses a captured trace.\n"
267b0e7dd80Sopenharmony_ci           "  --text             Specify the output format of trace as text.\n"
268b0e7dd80Sopenharmony_ci           "  --raw              Specify the output format of trace as raw trace, the default format is text.\n"
269b0e7dd80Sopenharmony_ci           "  --start_bgsrv      Enable trace_service in snapshot mode.\n"
270b0e7dd80Sopenharmony_ci           "  --dump_bgsrv       Trigger the dump trace task of the trace_service.\n"
271b0e7dd80Sopenharmony_ci           "  --stop_bgsrv       Disable trace_service in snapshot mode.\n"
272b0e7dd80Sopenharmony_ci           "  --file_size        Sets the size of the raw trace (KB). The default file size is 102400 KB.\n"
273b0e7dd80Sopenharmony_ci           "                     Only effective in raw trace mode\n"
274b0e7dd80Sopenharmony_ci    );
275b0e7dd80Sopenharmony_ci}
276b0e7dd80Sopenharmony_ci
277b0e7dd80Sopenharmony_citemplate <typename T>
278b0e7dd80Sopenharmony_ciinline bool StrToNum(const std::string& sString, T &tX)
279b0e7dd80Sopenharmony_ci{
280b0e7dd80Sopenharmony_ci    std::istringstream iStream(sString);
281b0e7dd80Sopenharmony_ci    return (iStream >> tX) ? true : false;
282b0e7dd80Sopenharmony_ci}
283b0e7dd80Sopenharmony_ci
284b0e7dd80Sopenharmony_cistatic bool SetRunningState(const RunningState& setValue)
285b0e7dd80Sopenharmony_ci{
286b0e7dd80Sopenharmony_ci    if (g_runningState != STATE_NULL) {
287b0e7dd80Sopenharmony_ci        ConsoleLog("error: the parameter is set incorrectly, " + GetStateInfo(g_runningState) +
288b0e7dd80Sopenharmony_ci                   " and " + GetStateInfo(setValue) + " cannot coexist.");
289b0e7dd80Sopenharmony_ci        return false;
290b0e7dd80Sopenharmony_ci    }
291b0e7dd80Sopenharmony_ci    g_runningState = setValue;
292b0e7dd80Sopenharmony_ci    return true;
293b0e7dd80Sopenharmony_ci}
294b0e7dd80Sopenharmony_ci
295b0e7dd80Sopenharmony_cistatic bool CheckOutputFile(const char* path)
296b0e7dd80Sopenharmony_ci{
297b0e7dd80Sopenharmony_ci    struct stat buf;
298b0e7dd80Sopenharmony_ci    size_t len = strnlen(path, MAX_OUTPUT_LEN);
299b0e7dd80Sopenharmony_ci    if (len == MAX_OUTPUT_LEN || len < 1 || (stat(path, &buf) == 0 && (buf.st_mode & S_IFDIR))) {
300b0e7dd80Sopenharmony_ci        ConsoleLog("error: output file is illegal");
301b0e7dd80Sopenharmony_ci        return false;
302b0e7dd80Sopenharmony_ci    }
303b0e7dd80Sopenharmony_ci    g_traceArgs.output = path;
304b0e7dd80Sopenharmony_ci    return true;
305b0e7dd80Sopenharmony_ci}
306b0e7dd80Sopenharmony_ci
307b0e7dd80Sopenharmony_cistatic bool ParseLongOpt(const string& cmd, int optionIndex)
308b0e7dd80Sopenharmony_ci{
309b0e7dd80Sopenharmony_ci    bool isTrue = true;
310b0e7dd80Sopenharmony_ci    if (!strcmp(LONG_OPTIONS[optionIndex].name, "buffer_size")) {
311b0e7dd80Sopenharmony_ci        int bufferSizeKB = 0;
312b0e7dd80Sopenharmony_ci        int maxBufferSizeKB = MAX_BUFFER_SIZE;
313b0e7dd80Sopenharmony_ci        if (IsHmKernel()) {
314b0e7dd80Sopenharmony_ci            maxBufferSizeKB = HM_MAX_BUFFER_SIZE;
315b0e7dd80Sopenharmony_ci        }
316b0e7dd80Sopenharmony_ci        if (!StrToNum(optarg, bufferSizeKB)) {
317b0e7dd80Sopenharmony_ci            ConsoleLog("error: buffer size is illegal input. eg: \"--buffer_size 18432\".");
318b0e7dd80Sopenharmony_ci            isTrue = false;
319b0e7dd80Sopenharmony_ci        } else if (bufferSizeKB < MIN_BUFFER_SIZE || bufferSizeKB > maxBufferSizeKB) {
320b0e7dd80Sopenharmony_ci            ConsoleLog("error: buffer size must be from 256 KB to " + std::to_string(maxBufferSizeKB / KB_PER_MB) +
321b0e7dd80Sopenharmony_ci                " MB. eg: \"--buffer_size 18432\".");
322b0e7dd80Sopenharmony_ci            isTrue = false;
323b0e7dd80Sopenharmony_ci        }
324b0e7dd80Sopenharmony_ci        g_traceArgs.bufferSize = bufferSizeKB / PAGE_SIZE_KB * PAGE_SIZE_KB;
325b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "trace_clock")) {
326b0e7dd80Sopenharmony_ci        regex re("[a-zA-Z]{4,6}");
327b0e7dd80Sopenharmony_ci        if (regex_match(optarg, re)) {
328b0e7dd80Sopenharmony_ci            g_traceArgs.clockType = optarg;
329b0e7dd80Sopenharmony_ci        } else {
330b0e7dd80Sopenharmony_ci            ConsoleLog("error: \"--trace_clock\" is illegal input. eg: \"--trace_clock boot\".");
331b0e7dd80Sopenharmony_ci            isTrue = false;
332b0e7dd80Sopenharmony_ci        }
333b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "help")) {
334b0e7dd80Sopenharmony_ci        isTrue = SetRunningState(SHOW_HELP);
335b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "time")) {
336b0e7dd80Sopenharmony_ci        if (!StrToNum(optarg, g_traceArgs.duration)) {
337b0e7dd80Sopenharmony_ci            ConsoleLog("error: the time is illegal input. eg: \"--time 5\".");
338b0e7dd80Sopenharmony_ci            isTrue = false;
339b0e7dd80Sopenharmony_ci        } else if (g_traceArgs.duration < 1) {
340b0e7dd80Sopenharmony_ci            ConsoleLog("error: \"-t " + std::string(optarg) + "\" to be greater than zero. eg: \"--time 5\".");
341b0e7dd80Sopenharmony_ci            isTrue = false;
342b0e7dd80Sopenharmony_ci        }
343b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "list_categories")) {
344b0e7dd80Sopenharmony_ci        isTrue = SetRunningState(SHOW_LIST_CATEGORY);
345b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "output")) {
346b0e7dd80Sopenharmony_ci        isTrue = CheckOutputFile(optarg);
347b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "overwrite")) {
348b0e7dd80Sopenharmony_ci        g_traceArgs.overwrite = false;
349b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "trace_begin")) {
350b0e7dd80Sopenharmony_ci        isTrue = SetRunningState(RECORDING_LONG_BEGIN);
351b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "trace_finish")) {
352b0e7dd80Sopenharmony_ci        isTrue = SetRunningState(RECORDING_LONG_FINISH);
353b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "trace_finish_nodump")) {
354b0e7dd80Sopenharmony_ci        isTrue = SetRunningState(RECORDING_LONG_FINISH_NODUMP);
355b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "trace_dump")) {
356b0e7dd80Sopenharmony_ci        isTrue = SetRunningState(RECORDING_LONG_DUMP);
357b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "record")) {
358b0e7dd80Sopenharmony_ci        if (g_runningState == RECORDING_LONG_BEGIN) {
359b0e7dd80Sopenharmony_ci            g_runningState = RECORDING_LONG_BEGIN_RECORD;
360b0e7dd80Sopenharmony_ci        } else if (g_runningState == RECORDING_LONG_FINISH) {
361b0e7dd80Sopenharmony_ci            g_runningState = RECORDING_LONG_FINISH_RECORD;
362b0e7dd80Sopenharmony_ci        } else {
363b0e7dd80Sopenharmony_ci            ConsoleLog("error: \"--record\" is set incorrectly. eg: \"--trace_begin --record\","
364b0e7dd80Sopenharmony_ci                       " \"--trace_finish --record\".");
365b0e7dd80Sopenharmony_ci            isTrue = false;
366b0e7dd80Sopenharmony_ci        }
367b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "start_bgsrv")) {
368b0e7dd80Sopenharmony_ci        isTrue = SetRunningState(SNAPSHOT_START);
369b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "dump_bgsrv")) {
370b0e7dd80Sopenharmony_ci        isTrue = SetRunningState(SNAPSHOT_DUMP);
371b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "stop_bgsrv")) {
372b0e7dd80Sopenharmony_ci        isTrue = SetRunningState(SNAPSHOT_STOP);
373b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "text")) {
374b0e7dd80Sopenharmony_ci        isTrue = SetRunningState(RECORDING_SHORT_TEXT);
375b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "raw")) {
376b0e7dd80Sopenharmony_ci        isTrue = SetRunningState(RECORDING_SHORT_RAW);
377b0e7dd80Sopenharmony_ci    } else if (!strcmp(LONG_OPTIONS[optionIndex].name, "file_size")) {
378b0e7dd80Sopenharmony_ci        int fileSizeKB = 0;
379b0e7dd80Sopenharmony_ci        if (!StrToNum(optarg, fileSizeKB)) {
380b0e7dd80Sopenharmony_ci            ConsoleLog("error: file size is illegal input. eg: \"--file_size 102400\".");
381b0e7dd80Sopenharmony_ci            isTrue = false;
382b0e7dd80Sopenharmony_ci        } else if (fileSizeKB < MIN_FILE_SIZE || fileSizeKB > MAX_FILE_SIZE) {
383b0e7dd80Sopenharmony_ci            ConsoleLog("error: file size must be from 50 MB to 500 MB. eg: \"--file_size 102400\".");
384b0e7dd80Sopenharmony_ci            isTrue = false;
385b0e7dd80Sopenharmony_ci        }
386b0e7dd80Sopenharmony_ci        g_traceArgs.fileSize = fileSizeKB;
387b0e7dd80Sopenharmony_ci    }
388b0e7dd80Sopenharmony_ci
389b0e7dd80Sopenharmony_ci    return isTrue;
390b0e7dd80Sopenharmony_ci}
391b0e7dd80Sopenharmony_ci
392b0e7dd80Sopenharmony_cistatic bool ParseOpt(int opt, char** argv, int optIndex)
393b0e7dd80Sopenharmony_ci{
394b0e7dd80Sopenharmony_ci    bool isTrue = true;
395b0e7dd80Sopenharmony_ci    switch (opt) {
396b0e7dd80Sopenharmony_ci        case 'b': {
397b0e7dd80Sopenharmony_ci            int bufferSizeKB = 0;
398b0e7dd80Sopenharmony_ci            int maxBufferSizeKB = MAX_BUFFER_SIZE;
399b0e7dd80Sopenharmony_ci            if (IsHmKernel()) {
400b0e7dd80Sopenharmony_ci                maxBufferSizeKB = HM_MAX_BUFFER_SIZE;
401b0e7dd80Sopenharmony_ci            }
402b0e7dd80Sopenharmony_ci            if (!StrToNum(optarg, bufferSizeKB)) {
403b0e7dd80Sopenharmony_ci                ConsoleLog("error: buffer size is illegal input. eg: \"--buffer_size 18432\".");
404b0e7dd80Sopenharmony_ci                isTrue = false;
405b0e7dd80Sopenharmony_ci            } else if (bufferSizeKB < MIN_BUFFER_SIZE || bufferSizeKB > maxBufferSizeKB) {
406b0e7dd80Sopenharmony_ci                ConsoleLog("error: buffer size must be from 256 KB to " + std::to_string(maxBufferSizeKB / KB_PER_MB) +
407b0e7dd80Sopenharmony_ci                " MB. eg: \"--buffer_size 18432\".");
408b0e7dd80Sopenharmony_ci                isTrue = false;
409b0e7dd80Sopenharmony_ci            }
410b0e7dd80Sopenharmony_ci            g_traceArgs.bufferSize = bufferSizeKB / PAGE_SIZE_KB * PAGE_SIZE_KB;
411b0e7dd80Sopenharmony_ci            break;
412b0e7dd80Sopenharmony_ci        }
413b0e7dd80Sopenharmony_ci        case 'h':
414b0e7dd80Sopenharmony_ci            isTrue = SetRunningState(SHOW_HELP);
415b0e7dd80Sopenharmony_ci            break;
416b0e7dd80Sopenharmony_ci        case 'l':
417b0e7dd80Sopenharmony_ci            isTrue = SetRunningState(SHOW_LIST_CATEGORY);
418b0e7dd80Sopenharmony_ci            break;
419b0e7dd80Sopenharmony_ci        case 't': {
420b0e7dd80Sopenharmony_ci            if (!StrToNum(optarg, g_traceArgs.duration)) {
421b0e7dd80Sopenharmony_ci                ConsoleLog("error: the time is illegal input. eg: \"--time 5\".");
422b0e7dd80Sopenharmony_ci                isTrue = false;
423b0e7dd80Sopenharmony_ci            } else if (g_traceArgs.duration < 1) {
424b0e7dd80Sopenharmony_ci                ConsoleLog("error: \"-t " + std::string(optarg) + "\" to be greater than zero. eg: \"--time 5\".");
425b0e7dd80Sopenharmony_ci                isTrue = false;
426b0e7dd80Sopenharmony_ci            }
427b0e7dd80Sopenharmony_ci            break;
428b0e7dd80Sopenharmony_ci        }
429b0e7dd80Sopenharmony_ci        case 'o': {
430b0e7dd80Sopenharmony_ci            isTrue = CheckOutputFile(optarg);
431b0e7dd80Sopenharmony_ci            break;
432b0e7dd80Sopenharmony_ci        }
433b0e7dd80Sopenharmony_ci        case 'z':
434b0e7dd80Sopenharmony_ci            g_traceArgs.isCompress = true;
435b0e7dd80Sopenharmony_ci            break;
436b0e7dd80Sopenharmony_ci        case 0: // long options
437b0e7dd80Sopenharmony_ci            isTrue = ParseLongOpt(argv[0], optIndex);
438b0e7dd80Sopenharmony_ci            break;
439b0e7dd80Sopenharmony_ci        case '?':
440b0e7dd80Sopenharmony_ci            isTrue = false;
441b0e7dd80Sopenharmony_ci            break;
442b0e7dd80Sopenharmony_ci        default:
443b0e7dd80Sopenharmony_ci            break;
444b0e7dd80Sopenharmony_ci    }
445b0e7dd80Sopenharmony_ci    return isTrue;
446b0e7dd80Sopenharmony_ci}
447b0e7dd80Sopenharmony_ci
448b0e7dd80Sopenharmony_cistatic bool AddTagItems(int argc, char** argv)
449b0e7dd80Sopenharmony_ci{
450b0e7dd80Sopenharmony_ci    for (int i = optind; i < argc; i++) {
451b0e7dd80Sopenharmony_ci        std::string tag = std::string(argv[i]);
452b0e7dd80Sopenharmony_ci        if (g_allTags.find(tag) == g_allTags.end()) {
453b0e7dd80Sopenharmony_ci            std::string errorInfo = "error: " + tag + " is not support category on this device.";
454b0e7dd80Sopenharmony_ci            ConsoleLog(errorInfo);
455b0e7dd80Sopenharmony_ci            return false;
456b0e7dd80Sopenharmony_ci        }
457b0e7dd80Sopenharmony_ci
458b0e7dd80Sopenharmony_ci        if (i == optind) {
459b0e7dd80Sopenharmony_ci            g_traceArgs.tags = tag;
460b0e7dd80Sopenharmony_ci        } else {
461b0e7dd80Sopenharmony_ci            g_traceArgs.tags += ("," + tag);
462b0e7dd80Sopenharmony_ci        }
463b0e7dd80Sopenharmony_ci    }
464b0e7dd80Sopenharmony_ci    return true;
465b0e7dd80Sopenharmony_ci}
466b0e7dd80Sopenharmony_ci
467b0e7dd80Sopenharmony_cistatic bool HandleOpt(int argc, char** argv)
468b0e7dd80Sopenharmony_ci{
469b0e7dd80Sopenharmony_ci    bool isTrue = true;
470b0e7dd80Sopenharmony_ci    int opt = 0;
471b0e7dd80Sopenharmony_ci    int optionIndex = 0;
472b0e7dd80Sopenharmony_ci    string shortOption = "b:c:hlo:t:z";
473b0e7dd80Sopenharmony_ci    int argcSize = argc;
474b0e7dd80Sopenharmony_ci    while (isTrue && argcSize-- > 0) {
475b0e7dd80Sopenharmony_ci        opt = getopt_long(argc, argv, shortOption.c_str(), LONG_OPTIONS, &optionIndex);
476b0e7dd80Sopenharmony_ci        if (opt < 0 && (!AddTagItems(argc, argv))) {
477b0e7dd80Sopenharmony_ci            isTrue = false;
478b0e7dd80Sopenharmony_ci            break;
479b0e7dd80Sopenharmony_ci        }
480b0e7dd80Sopenharmony_ci        isTrue = ParseOpt(opt, argv, optionIndex);
481b0e7dd80Sopenharmony_ci    }
482b0e7dd80Sopenharmony_ci
483b0e7dd80Sopenharmony_ci    return isTrue;
484b0e7dd80Sopenharmony_ci}
485b0e7dd80Sopenharmony_ci
486b0e7dd80Sopenharmony_cistatic void StopTrace()
487b0e7dd80Sopenharmony_ci{
488b0e7dd80Sopenharmony_ci    const int napTime = 10000;
489b0e7dd80Sopenharmony_ci    usleep(napTime);
490b0e7dd80Sopenharmony_ci    SetTraceTagsEnabled(0);
491b0e7dd80Sopenharmony_ci    SetFtraceEnabled(TRACING_ON_PATH, false);
492b0e7dd80Sopenharmony_ci}
493b0e7dd80Sopenharmony_ci
494b0e7dd80Sopenharmony_cistatic void DumpCompressedTrace(int traceFd, int outFd)
495b0e7dd80Sopenharmony_ci{
496b0e7dd80Sopenharmony_ci    z_stream zs { nullptr };
497b0e7dd80Sopenharmony_ci    int flush = Z_NO_FLUSH;
498b0e7dd80Sopenharmony_ci    ssize_t bytesWritten;
499b0e7dd80Sopenharmony_ci    ssize_t bytesRead;
500b0e7dd80Sopenharmony_ci    if (memset_s(&zs, sizeof(zs), 0, sizeof(zs)) != 0) {
501b0e7dd80Sopenharmony_ci        ConsoleLog("error: zip stream buffer init failed.");
502b0e7dd80Sopenharmony_ci        return;
503b0e7dd80Sopenharmony_ci    }
504b0e7dd80Sopenharmony_ci    int ret = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
505b0e7dd80Sopenharmony_ci    if (ret != Z_OK) {
506b0e7dd80Sopenharmony_ci        ConsoleLog("error: initializing zlib failed ret " + std::to_string(ret));
507b0e7dd80Sopenharmony_ci        return;
508b0e7dd80Sopenharmony_ci    }
509b0e7dd80Sopenharmony_ci    std::unique_ptr<uint8_t[]>  in = std::make_unique<uint8_t[]>(CHUNK_SIZE);
510b0e7dd80Sopenharmony_ci    std::unique_ptr<uint8_t[]>  out = std::make_unique<uint8_t[]>(CHUNK_SIZE);
511b0e7dd80Sopenharmony_ci    if (!in || !out) {
512b0e7dd80Sopenharmony_ci        ConsoleLog("error: couldn't allocate buffers.");
513b0e7dd80Sopenharmony_ci        return;
514b0e7dd80Sopenharmony_ci    }
515b0e7dd80Sopenharmony_ci    zs.next_out = reinterpret_cast<Bytef*>(out.get());
516b0e7dd80Sopenharmony_ci    zs.avail_out = CHUNK_SIZE;
517b0e7dd80Sopenharmony_ci
518b0e7dd80Sopenharmony_ci    do {
519b0e7dd80Sopenharmony_ci        if (zs.avail_in == 0 && flush == Z_NO_FLUSH) {
520b0e7dd80Sopenharmony_ci            bytesRead = TEMP_FAILURE_RETRY(read(traceFd, in.get(), CHUNK_SIZE));
521b0e7dd80Sopenharmony_ci            if (bytesRead == 0) {
522b0e7dd80Sopenharmony_ci                flush = Z_FINISH;
523b0e7dd80Sopenharmony_ci            } else if (bytesRead == -1) {
524b0e7dd80Sopenharmony_ci                ConsoleLog("error: reading trace, errno " + std::to_string(errno));
525b0e7dd80Sopenharmony_ci                break;
526b0e7dd80Sopenharmony_ci            } else {
527b0e7dd80Sopenharmony_ci                zs.next_in = reinterpret_cast<Bytef*>(in.get());
528b0e7dd80Sopenharmony_ci                zs.avail_in = bytesRead;
529b0e7dd80Sopenharmony_ci            }
530b0e7dd80Sopenharmony_ci        }
531b0e7dd80Sopenharmony_ci        if (zs.avail_out == 0) {
532b0e7dd80Sopenharmony_ci            bytesWritten = TEMP_FAILURE_RETRY(write(outFd, out.get(), CHUNK_SIZE));
533b0e7dd80Sopenharmony_ci            if (bytesWritten < static_cast<ssize_t>(CHUNK_SIZE)) {
534b0e7dd80Sopenharmony_ci                ConsoleLog("error: writing deflated trace, errno " + std::to_string(errno));
535b0e7dd80Sopenharmony_ci                break;
536b0e7dd80Sopenharmony_ci            }
537b0e7dd80Sopenharmony_ci            zs.next_out = reinterpret_cast<Bytef*>(out.get());
538b0e7dd80Sopenharmony_ci            zs.avail_out = CHUNK_SIZE;
539b0e7dd80Sopenharmony_ci        }
540b0e7dd80Sopenharmony_ci        ret = deflate(&zs, flush);
541b0e7dd80Sopenharmony_ci        if (flush == Z_FINISH && ret == Z_STREAM_END) {
542b0e7dd80Sopenharmony_ci            size_t have = CHUNK_SIZE - zs.avail_out;
543b0e7dd80Sopenharmony_ci            bytesWritten = TEMP_FAILURE_RETRY(write(outFd, out.get(), have));
544b0e7dd80Sopenharmony_ci            if (static_cast<size_t>(bytesWritten) < have) {
545b0e7dd80Sopenharmony_ci                ConsoleLog("error: writing deflated trace, errno " + std::to_string(errno));
546b0e7dd80Sopenharmony_ci            }
547b0e7dd80Sopenharmony_ci            break;
548b0e7dd80Sopenharmony_ci        } else if (ret != Z_OK) {
549b0e7dd80Sopenharmony_ci            if (ret == Z_ERRNO) {
550b0e7dd80Sopenharmony_ci                ConsoleLog("error: deflate failed with errno " + std::to_string(errno));
551b0e7dd80Sopenharmony_ci            } else {
552b0e7dd80Sopenharmony_ci                ConsoleLog("error: deflate failed return " + std::to_string(ret));
553b0e7dd80Sopenharmony_ci            }
554b0e7dd80Sopenharmony_ci            break;
555b0e7dd80Sopenharmony_ci        }
556b0e7dd80Sopenharmony_ci    } while (ret == Z_OK);
557b0e7dd80Sopenharmony_ci
558b0e7dd80Sopenharmony_ci    ret = deflateEnd(&zs);
559b0e7dd80Sopenharmony_ci    if (ret != Z_OK) {
560b0e7dd80Sopenharmony_ci        ConsoleLog("error: cleaning up zlib return " + std::to_string(ret));
561b0e7dd80Sopenharmony_ci    }
562b0e7dd80Sopenharmony_ci}
563b0e7dd80Sopenharmony_ci
564b0e7dd80Sopenharmony_cistatic void DumpTrace()
565b0e7dd80Sopenharmony_ci{
566b0e7dd80Sopenharmony_ci    std::string tracePath = g_traceRootPath + TRACE_PATH;
567b0e7dd80Sopenharmony_ci    string traceSpecPath = OHOS::HiviewDFX::Hitrace::CanonicalizeSpecPath(tracePath.c_str());
568b0e7dd80Sopenharmony_ci    int traceFd = open(traceSpecPath.c_str(), O_RDONLY);
569b0e7dd80Sopenharmony_ci    if (traceFd == -1) {
570b0e7dd80Sopenharmony_ci        ConsoleLog("error: opening " + tracePath + ", errno: " + std::to_string(errno));
571b0e7dd80Sopenharmony_ci        return;
572b0e7dd80Sopenharmony_ci    }
573b0e7dd80Sopenharmony_ci
574b0e7dd80Sopenharmony_ci    int outFd = STDOUT_FILENO;
575b0e7dd80Sopenharmony_ci    if (g_traceArgs.output.size() > 0) {
576b0e7dd80Sopenharmony_ci        string outSpecPath = OHOS::HiviewDFX::Hitrace::CanonicalizeSpecPath(g_traceArgs.output.c_str());
577b0e7dd80Sopenharmony_ci        outFd = open(outSpecPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
578b0e7dd80Sopenharmony_ci    }
579b0e7dd80Sopenharmony_ci
580b0e7dd80Sopenharmony_ci    if (outFd == -1) {
581b0e7dd80Sopenharmony_ci        ConsoleLog("error: opening " + g_traceArgs.output + ", errno: " + std::to_string(errno));
582b0e7dd80Sopenharmony_ci        close(traceFd);
583b0e7dd80Sopenharmony_ci        return;
584b0e7dd80Sopenharmony_ci    }
585b0e7dd80Sopenharmony_ci
586b0e7dd80Sopenharmony_ci    ssize_t bytesWritten;
587b0e7dd80Sopenharmony_ci    ssize_t bytesRead;
588b0e7dd80Sopenharmony_ci    if (g_traceArgs.isCompress) {
589b0e7dd80Sopenharmony_ci        DumpCompressedTrace(traceFd, outFd);
590b0e7dd80Sopenharmony_ci    } else {
591b0e7dd80Sopenharmony_ci        const int blockSize = 4096;
592b0e7dd80Sopenharmony_ci        char buffer[blockSize];
593b0e7dd80Sopenharmony_ci        do {
594b0e7dd80Sopenharmony_ci            bytesRead = TEMP_FAILURE_RETRY(read(traceFd, buffer, blockSize));
595b0e7dd80Sopenharmony_ci            if ((bytesRead == 0) || (bytesRead == -1)) {
596b0e7dd80Sopenharmony_ci                break;
597b0e7dd80Sopenharmony_ci            }
598b0e7dd80Sopenharmony_ci            bytesWritten = TEMP_FAILURE_RETRY(write(outFd, buffer, bytesRead));
599b0e7dd80Sopenharmony_ci        } while (bytesWritten > 0);
600b0e7dd80Sopenharmony_ci    }
601b0e7dd80Sopenharmony_ci
602b0e7dd80Sopenharmony_ci    if (outFd != STDOUT_FILENO) {
603b0e7dd80Sopenharmony_ci        ConsoleLog("trace read done, output: " + g_traceArgs.output);
604b0e7dd80Sopenharmony_ci        close(outFd);
605b0e7dd80Sopenharmony_ci    }
606b0e7dd80Sopenharmony_ci    close(traceFd);
607b0e7dd80Sopenharmony_ci}
608b0e7dd80Sopenharmony_ci
609b0e7dd80Sopenharmony_cistatic bool InitAllSupportTags()
610b0e7dd80Sopenharmony_ci{
611b0e7dd80Sopenharmony_ci    if (!OHOS::HiviewDFX::Hitrace::ParseTagInfo(g_allTags, g_allTagGroups)) {
612b0e7dd80Sopenharmony_ci        ConsoleLog("error: hitrace_utils.json file is damaged.");
613b0e7dd80Sopenharmony_ci        return false;
614b0e7dd80Sopenharmony_ci    }
615b0e7dd80Sopenharmony_ci    return true;
616b0e7dd80Sopenharmony_ci}
617b0e7dd80Sopenharmony_ci
618b0e7dd80Sopenharmony_cistatic std::string ReloadTraceArgs()
619b0e7dd80Sopenharmony_ci{
620b0e7dd80Sopenharmony_ci    if (g_traceArgs.tags.size() == 0) {
621b0e7dd80Sopenharmony_ci        ConsoleLog("error: tag is empty, please add.");
622b0e7dd80Sopenharmony_ci        return "";
623b0e7dd80Sopenharmony_ci    }
624b0e7dd80Sopenharmony_ci    std::string args = "tags:" + g_traceArgs.tags;
625b0e7dd80Sopenharmony_ci
626b0e7dd80Sopenharmony_ci    if (g_traceArgs.bufferSize > 0) {
627b0e7dd80Sopenharmony_ci        args += (" bufferSize:" + std::to_string(g_traceArgs.bufferSize));
628b0e7dd80Sopenharmony_ci    } else {
629b0e7dd80Sopenharmony_ci        args += (" bufferSize:" + std::to_string(DEFAULT_BUFFER_SIZE));
630b0e7dd80Sopenharmony_ci    }
631b0e7dd80Sopenharmony_ci
632b0e7dd80Sopenharmony_ci    if (g_traceArgs.clockType.size() > 0) {
633b0e7dd80Sopenharmony_ci        args += (" clockType:" + g_traceArgs.clockType);
634b0e7dd80Sopenharmony_ci    }
635b0e7dd80Sopenharmony_ci
636b0e7dd80Sopenharmony_ci    if (g_traceArgs.overwrite) {
637b0e7dd80Sopenharmony_ci        args += " overwrite:";
638b0e7dd80Sopenharmony_ci        args += "1";
639b0e7dd80Sopenharmony_ci    } else {
640b0e7dd80Sopenharmony_ci        args += " overwrite:";
641b0e7dd80Sopenharmony_ci        args += "0";
642b0e7dd80Sopenharmony_ci    }
643b0e7dd80Sopenharmony_ci
644b0e7dd80Sopenharmony_ci    if (g_traceArgs.fileSize > 0) {
645b0e7dd80Sopenharmony_ci        if (g_runningState == RECORDING_SHORT_RAW || g_runningState == RECORDING_LONG_BEGIN_RECORD) {
646b0e7dd80Sopenharmony_ci            args += (" fileSize:" + std::to_string(g_traceArgs.fileSize));
647b0e7dd80Sopenharmony_ci        } else {
648b0e7dd80Sopenharmony_ci            ConsoleLog("warning: The current state does not support specifying the file size, file size: " +
649b0e7dd80Sopenharmony_ci                std::to_string(g_traceArgs.fileSize) + " is invalid.");
650b0e7dd80Sopenharmony_ci        }
651b0e7dd80Sopenharmony_ci    }
652b0e7dd80Sopenharmony_ci
653b0e7dd80Sopenharmony_ci    if (g_runningState != RECORDING_SHORT_TEXT) {
654b0e7dd80Sopenharmony_ci        ConsoleLog("args: " + args);
655b0e7dd80Sopenharmony_ci    }
656b0e7dd80Sopenharmony_ci    return args;
657b0e7dd80Sopenharmony_ci}
658b0e7dd80Sopenharmony_ci
659b0e7dd80Sopenharmony_cistatic bool HandleRecordingShortRaw()
660b0e7dd80Sopenharmony_ci{
661b0e7dd80Sopenharmony_ci    std::string args = ReloadTraceArgs();
662b0e7dd80Sopenharmony_ci    if (g_traceArgs.output.size() > 0) {
663b0e7dd80Sopenharmony_ci        ConsoleLog("warning: The current state does not support specifying the output file path, " +
664b0e7dd80Sopenharmony_ci                   g_traceArgs.output + " is invalid.");
665b0e7dd80Sopenharmony_ci    }
666b0e7dd80Sopenharmony_ci    auto openRet = g_traceCollector->OpenRecording(args);
667b0e7dd80Sopenharmony_ci    if (openRet.retCode != OHOS::HiviewDFX::UCollect::UcError::SUCCESS) {
668b0e7dd80Sopenharmony_ci        ConsoleLog("error: OpenRecording failed, errorCode(" + std::to_string(openRet.retCode) +")");
669b0e7dd80Sopenharmony_ci        if (openRet.retCode == OHOS::HiviewDFX::UCollect::UcError::TRACE_IS_OCCUPIED ||
670b0e7dd80Sopenharmony_ci            openRet.retCode == OHOS::HiviewDFX::UCollect::UcError::TRACE_CALL_ERROR) {
671b0e7dd80Sopenharmony_ci            return false;
672b0e7dd80Sopenharmony_ci        } else {
673b0e7dd80Sopenharmony_ci            g_traceCollector->Recover();
674b0e7dd80Sopenharmony_ci            return false;
675b0e7dd80Sopenharmony_ci        }
676b0e7dd80Sopenharmony_ci    }
677b0e7dd80Sopenharmony_ci
678b0e7dd80Sopenharmony_ci    auto recOnRet = g_traceCollector->RecordingOn();
679b0e7dd80Sopenharmony_ci    if (recOnRet.retCode != OHOS::HiviewDFX::UCollect::UcError::SUCCESS) {
680b0e7dd80Sopenharmony_ci        ConsoleLog("error: RecordingOn failed, errorCode(" + std::to_string(recOnRet.retCode) +")");
681b0e7dd80Sopenharmony_ci        g_traceCollector->Recover();
682b0e7dd80Sopenharmony_ci        return false;
683b0e7dd80Sopenharmony_ci    }
684b0e7dd80Sopenharmony_ci    ConsoleLog("start capture, please wait " + std::to_string(g_traceArgs.duration) +"s ...");
685b0e7dd80Sopenharmony_ci    sleep(g_traceArgs.duration);
686b0e7dd80Sopenharmony_ci
687b0e7dd80Sopenharmony_ci    auto recOffRet = g_traceCollector->RecordingOff();
688b0e7dd80Sopenharmony_ci    if (recOffRet.retCode != OHOS::HiviewDFX::UCollect::UcError::SUCCESS) {
689b0e7dd80Sopenharmony_ci        ConsoleLog("error: RecordingOff failed, errorCode(" + std::to_string(recOffRet.retCode) +")");
690b0e7dd80Sopenharmony_ci        g_traceCollector->Recover();
691b0e7dd80Sopenharmony_ci        return false;
692b0e7dd80Sopenharmony_ci    }
693b0e7dd80Sopenharmony_ci    ConsoleLog("capture done, output files:");
694b0e7dd80Sopenharmony_ci    for (std::string item : recOffRet.data) {
695b0e7dd80Sopenharmony_ci        std::cout << "    " << item << std::endl;
696b0e7dd80Sopenharmony_ci    }
697b0e7dd80Sopenharmony_ci    g_traceCollector->Recover();
698b0e7dd80Sopenharmony_ci    return true;
699b0e7dd80Sopenharmony_ci}
700b0e7dd80Sopenharmony_ci
701b0e7dd80Sopenharmony_cistatic bool HandleRecordingShortText()
702b0e7dd80Sopenharmony_ci{
703b0e7dd80Sopenharmony_ci    std::string args = ReloadTraceArgs();
704b0e7dd80Sopenharmony_ci    auto openRet = g_traceCollector->OpenRecording(args);
705b0e7dd80Sopenharmony_ci    if (openRet.retCode != OHOS::HiviewDFX::UCollect::UcError::SUCCESS) {
706b0e7dd80Sopenharmony_ci        ConsoleLog("error: OpenRecording failed, errorCode(" + std::to_string(openRet.retCode) +")");
707b0e7dd80Sopenharmony_ci        if (openRet.retCode == OHOS::HiviewDFX::UCollect::UcError::TRACE_IS_OCCUPIED ||
708b0e7dd80Sopenharmony_ci            openRet.retCode == OHOS::HiviewDFX::UCollect::UcError::TRACE_CALL_ERROR) {
709b0e7dd80Sopenharmony_ci            return false;
710b0e7dd80Sopenharmony_ci        } else {
711b0e7dd80Sopenharmony_ci            g_traceCollector->Recover();
712b0e7dd80Sopenharmony_ci            return false;
713b0e7dd80Sopenharmony_ci        }
714b0e7dd80Sopenharmony_ci    }
715b0e7dd80Sopenharmony_ci    ConsoleLog("start capture, please wait " + std::to_string(g_traceArgs.duration) +"s ...");
716b0e7dd80Sopenharmony_ci    sleep(g_traceArgs.duration);
717b0e7dd80Sopenharmony_ci
718b0e7dd80Sopenharmony_ci    OHOS::HiviewDFX::Hitrace::MarkClockSync(g_traceRootPath);
719b0e7dd80Sopenharmony_ci    StopTrace();
720b0e7dd80Sopenharmony_ci
721b0e7dd80Sopenharmony_ci    if (g_traceArgs.output.size() > 0) {
722b0e7dd80Sopenharmony_ci        ConsoleLog("capture done, start to read trace.");
723b0e7dd80Sopenharmony_ci    }
724b0e7dd80Sopenharmony_ci    DumpTrace();
725b0e7dd80Sopenharmony_ci    g_traceCollector->Recover();
726b0e7dd80Sopenharmony_ci    return true;
727b0e7dd80Sopenharmony_ci}
728b0e7dd80Sopenharmony_ci
729b0e7dd80Sopenharmony_cistatic bool HandleRecordingLongBegin()
730b0e7dd80Sopenharmony_ci{
731b0e7dd80Sopenharmony_ci    std::string args = ReloadTraceArgs();
732b0e7dd80Sopenharmony_ci    if (g_traceArgs.output.size() > 0) {
733b0e7dd80Sopenharmony_ci        ConsoleLog("warning: The current state does not support specifying the output file path, " +
734b0e7dd80Sopenharmony_ci                   g_traceArgs.output + " is invalid.");
735b0e7dd80Sopenharmony_ci    }
736b0e7dd80Sopenharmony_ci    auto openRet = g_traceCollector->OpenRecording(args);
737b0e7dd80Sopenharmony_ci    if (openRet.retCode != OHOS::HiviewDFX::UCollect::UcError::SUCCESS) {
738b0e7dd80Sopenharmony_ci        ConsoleLog("error: OpenRecording failed, errorCode(" + std::to_string(openRet.retCode) +")");
739b0e7dd80Sopenharmony_ci        if (openRet.retCode == OHOS::HiviewDFX::UCollect::UcError::TRACE_IS_OCCUPIED ||
740b0e7dd80Sopenharmony_ci            openRet.retCode == OHOS::HiviewDFX::UCollect::UcError::TRACE_CALL_ERROR) {
741b0e7dd80Sopenharmony_ci            return false;
742b0e7dd80Sopenharmony_ci        } else {
743b0e7dd80Sopenharmony_ci            g_traceCollector->Recover();
744b0e7dd80Sopenharmony_ci            return false;
745b0e7dd80Sopenharmony_ci        }
746b0e7dd80Sopenharmony_ci    }
747b0e7dd80Sopenharmony_ci    ConsoleLog("OpenRecording done.");
748b0e7dd80Sopenharmony_ci    return true;
749b0e7dd80Sopenharmony_ci}
750b0e7dd80Sopenharmony_ci
751b0e7dd80Sopenharmony_cistatic bool HandleRecordingLongDump()
752b0e7dd80Sopenharmony_ci{
753b0e7dd80Sopenharmony_ci    OHOS::HiviewDFX::Hitrace::MarkClockSync(g_traceRootPath);
754b0e7dd80Sopenharmony_ci    ConsoleLog("start to read trace.");
755b0e7dd80Sopenharmony_ci    DumpTrace();
756b0e7dd80Sopenharmony_ci    return true;
757b0e7dd80Sopenharmony_ci}
758b0e7dd80Sopenharmony_ci
759b0e7dd80Sopenharmony_cistatic bool HandleRecordingLongFinish()
760b0e7dd80Sopenharmony_ci{
761b0e7dd80Sopenharmony_ci    OHOS::HiviewDFX::Hitrace::MarkClockSync(g_traceRootPath);
762b0e7dd80Sopenharmony_ci    StopTrace();
763b0e7dd80Sopenharmony_ci    ConsoleLog("start to read trace.");
764b0e7dd80Sopenharmony_ci    DumpTrace();
765b0e7dd80Sopenharmony_ci    g_traceCollector->Recover();
766b0e7dd80Sopenharmony_ci    return true;
767b0e7dd80Sopenharmony_ci}
768b0e7dd80Sopenharmony_ci
769b0e7dd80Sopenharmony_cistatic bool HandleRecordingLongFinishNodump()
770b0e7dd80Sopenharmony_ci{
771b0e7dd80Sopenharmony_ci    g_traceCollector->Recover();
772b0e7dd80Sopenharmony_ci    ConsoleLog("end capture trace.");
773b0e7dd80Sopenharmony_ci    return true;
774b0e7dd80Sopenharmony_ci}
775b0e7dd80Sopenharmony_ci
776b0e7dd80Sopenharmony_cistatic bool HandleRecordingLongBeginRecord()
777b0e7dd80Sopenharmony_ci{
778b0e7dd80Sopenharmony_ci    std::string args = ReloadTraceArgs();
779b0e7dd80Sopenharmony_ci    if (g_traceArgs.output.size() > 0) {
780b0e7dd80Sopenharmony_ci        ConsoleLog("warning: The current state does not support specifying the output file path, " +
781b0e7dd80Sopenharmony_ci                   g_traceArgs.output + " is invalid.");
782b0e7dd80Sopenharmony_ci    }
783b0e7dd80Sopenharmony_ci    auto openRet = g_traceCollector->OpenRecording(args);
784b0e7dd80Sopenharmony_ci    if (openRet.retCode != OHOS::HiviewDFX::UCollect::UcError::SUCCESS) {
785b0e7dd80Sopenharmony_ci        ConsoleLog("error: OpenRecording failed, errorCode(" + std::to_string(openRet.retCode) +")");
786b0e7dd80Sopenharmony_ci        g_traceCollector->Recover();
787b0e7dd80Sopenharmony_ci        return false;
788b0e7dd80Sopenharmony_ci    }
789b0e7dd80Sopenharmony_ci
790b0e7dd80Sopenharmony_ci    auto recOnRet = g_traceCollector->RecordingOn();
791b0e7dd80Sopenharmony_ci    if (recOnRet.retCode != OHOS::HiviewDFX::UCollect::UcError::SUCCESS) {
792b0e7dd80Sopenharmony_ci        ConsoleLog("error: RecordingOn failed, errorCode(" + std::to_string(recOnRet.retCode) +")");
793b0e7dd80Sopenharmony_ci        g_traceCollector->Recover();
794b0e7dd80Sopenharmony_ci        return false;
795b0e7dd80Sopenharmony_ci    }
796b0e7dd80Sopenharmony_ci    ConsoleLog("trace capturing. ");
797b0e7dd80Sopenharmony_ci    return true;
798b0e7dd80Sopenharmony_ci}
799b0e7dd80Sopenharmony_ci
800b0e7dd80Sopenharmony_cistatic bool HandleRecordingLongFinishRecord()
801b0e7dd80Sopenharmony_ci{
802b0e7dd80Sopenharmony_ci    auto recOffRet = g_traceCollector->RecordingOff();
803b0e7dd80Sopenharmony_ci    if (recOffRet.retCode != OHOS::HiviewDFX::UCollect::UcError::SUCCESS) {
804b0e7dd80Sopenharmony_ci        ConsoleLog("error: RecordingOff failed, errorCode(" + std::to_string(recOffRet.retCode) +")");
805b0e7dd80Sopenharmony_ci        g_traceCollector->Recover();
806b0e7dd80Sopenharmony_ci        return false;
807b0e7dd80Sopenharmony_ci    }
808b0e7dd80Sopenharmony_ci    ConsoleLog("capture done, output files:");
809b0e7dd80Sopenharmony_ci    for (std::string item : recOffRet.data) {
810b0e7dd80Sopenharmony_ci        std::cout << "    " << item << std::endl;
811b0e7dd80Sopenharmony_ci    }
812b0e7dd80Sopenharmony_ci    g_traceCollector->Recover();
813b0e7dd80Sopenharmony_ci    return true;
814b0e7dd80Sopenharmony_ci}
815b0e7dd80Sopenharmony_ci
816b0e7dd80Sopenharmony_cistatic bool HandleOpenSnapshot()
817b0e7dd80Sopenharmony_ci{
818b0e7dd80Sopenharmony_ci    std::vector<std::string> tagGroups = { "scene_performance" };
819b0e7dd80Sopenharmony_ci    auto openRet = g_traceCollector->OpenSnapshot(tagGroups);
820b0e7dd80Sopenharmony_ci    if (openRet.retCode != OHOS::HiviewDFX::UCollect::UcError::SUCCESS) {
821b0e7dd80Sopenharmony_ci        ConsoleLog("error: OpenSnapshot failed, errorCode(" + std::to_string(openRet.retCode) +")");
822b0e7dd80Sopenharmony_ci        if (openRet.retCode == OHOS::HiviewDFX::UCollect::UcError::TRACE_IS_OCCUPIED ||
823b0e7dd80Sopenharmony_ci            openRet.retCode == OHOS::HiviewDFX::UCollect::UcError::TRACE_CALL_ERROR) {
824b0e7dd80Sopenharmony_ci            return false;
825b0e7dd80Sopenharmony_ci        } else {
826b0e7dd80Sopenharmony_ci            g_traceCollector->Recover();
827b0e7dd80Sopenharmony_ci            return false;
828b0e7dd80Sopenharmony_ci        }
829b0e7dd80Sopenharmony_ci    }
830b0e7dd80Sopenharmony_ci    ConsoleLog("OpenSnapshot done.");
831b0e7dd80Sopenharmony_ci    return true;
832b0e7dd80Sopenharmony_ci}
833b0e7dd80Sopenharmony_ci
834b0e7dd80Sopenharmony_cistatic bool HandleDumpSnapshot()
835b0e7dd80Sopenharmony_ci{
836b0e7dd80Sopenharmony_ci    bool isSuccess = true;
837b0e7dd80Sopenharmony_ci    auto dumpRet = g_traceCollector->DumpSnapshot(OHOS::HiviewDFX::UCollect::TraceCaller::DEVELOP);
838b0e7dd80Sopenharmony_ci    if (dumpRet.retCode != OHOS::HiviewDFX::UCollect::UcError::SUCCESS) {
839b0e7dd80Sopenharmony_ci        ConsoleLog("error: DumpSnapshot failed, errorCode(" + std::to_string(dumpRet.retCode) +")");
840b0e7dd80Sopenharmony_ci        isSuccess = false;
841b0e7dd80Sopenharmony_ci    } else {
842b0e7dd80Sopenharmony_ci        ConsoleLog("DumpSnapshot done, output:");
843b0e7dd80Sopenharmony_ci        for (std::string item : dumpRet.data) {
844b0e7dd80Sopenharmony_ci            std::cout << "    " << item << std::endl;
845b0e7dd80Sopenharmony_ci        }
846b0e7dd80Sopenharmony_ci    }
847b0e7dd80Sopenharmony_ci    return isSuccess;
848b0e7dd80Sopenharmony_ci}
849b0e7dd80Sopenharmony_ci
850b0e7dd80Sopenharmony_cistatic bool HandleCloseSnapshot()
851b0e7dd80Sopenharmony_ci{
852b0e7dd80Sopenharmony_ci    bool isSuccess = true;
853b0e7dd80Sopenharmony_ci    auto closeRet = g_traceCollector->Close();
854b0e7dd80Sopenharmony_ci    if (closeRet.retCode != OHOS::HiviewDFX::UCollect::UcError::SUCCESS) {
855b0e7dd80Sopenharmony_ci        ConsoleLog("error: CloseSnapshot failed, errorCode(" + std::to_string(closeRet.retCode) +")");
856b0e7dd80Sopenharmony_ci        isSuccess = false;
857b0e7dd80Sopenharmony_ci    } else {
858b0e7dd80Sopenharmony_ci        ConsoleLog("CloseSnapshot done.");
859b0e7dd80Sopenharmony_ci    }
860b0e7dd80Sopenharmony_ci    return isSuccess;
861b0e7dd80Sopenharmony_ci}
862b0e7dd80Sopenharmony_ci
863b0e7dd80Sopenharmony_cistatic void InterruptExit(int signo)
864b0e7dd80Sopenharmony_ci{
865b0e7dd80Sopenharmony_ci    /**
866b0e7dd80Sopenharmony_ci     * trace reset.
867b0e7dd80Sopenharmony_ci    */
868b0e7dd80Sopenharmony_ci    g_traceCollector->Recover();
869b0e7dd80Sopenharmony_ci    _exit(-1);
870b0e7dd80Sopenharmony_ci}
871b0e7dd80Sopenharmony_ci
872b0e7dd80Sopenharmony_ciint main(int argc, char **argv)
873b0e7dd80Sopenharmony_ci{
874b0e7dd80Sopenharmony_ci    if (!IsDeveloperMode()) {
875b0e7dd80Sopenharmony_ci        ConsoleLog("error: not in developermode, exit");
876b0e7dd80Sopenharmony_ci        return -1;
877b0e7dd80Sopenharmony_ci    }
878b0e7dd80Sopenharmony_ci
879b0e7dd80Sopenharmony_ci    if (argc < 0 || argc > 256) { // 256 : max input argument counts
880b0e7dd80Sopenharmony_ci        ConsoleLog("error: the number of input arguments exceeds the upper limit.");
881b0e7dd80Sopenharmony_ci        return -1;
882b0e7dd80Sopenharmony_ci    }
883b0e7dd80Sopenharmony_ci    bool isSuccess = true;
884b0e7dd80Sopenharmony_ci    g_traceCollector = OHOS::HiviewDFX::UCollectClient::TraceCollector::Create();
885b0e7dd80Sopenharmony_ci    if (g_traceCollector == nullptr) {
886b0e7dd80Sopenharmony_ci        ConsoleLog("error: traceCollector create failed, exit.");
887b0e7dd80Sopenharmony_ci        return -1;
888b0e7dd80Sopenharmony_ci    }
889b0e7dd80Sopenharmony_ci    (void)signal(SIGKILL, InterruptExit);
890b0e7dd80Sopenharmony_ci    (void)signal(SIGINT, InterruptExit);
891b0e7dd80Sopenharmony_ci
892b0e7dd80Sopenharmony_ci    if (!IsTraceMounted()) {
893b0e7dd80Sopenharmony_ci        ConsoleLog("error: trace isn't mounted, exit.");
894b0e7dd80Sopenharmony_ci        return -1;
895b0e7dd80Sopenharmony_ci    }
896b0e7dd80Sopenharmony_ci
897b0e7dd80Sopenharmony_ci    if (!InitAllSupportTags()) {
898b0e7dd80Sopenharmony_ci        return -1;
899b0e7dd80Sopenharmony_ci    }
900b0e7dd80Sopenharmony_ci
901b0e7dd80Sopenharmony_ci    if (!HandleOpt(argc, argv)) {
902b0e7dd80Sopenharmony_ci        ConsoleLog("error: parsing args failed, exit.");
903b0e7dd80Sopenharmony_ci        return -1;
904b0e7dd80Sopenharmony_ci    }
905b0e7dd80Sopenharmony_ci
906b0e7dd80Sopenharmony_ci    if (g_runningState == STATE_NULL) {
907b0e7dd80Sopenharmony_ci        g_runningState = RECORDING_SHORT_TEXT;
908b0e7dd80Sopenharmony_ci    }
909b0e7dd80Sopenharmony_ci
910b0e7dd80Sopenharmony_ci    if (g_runningState != RECORDING_SHORT_TEXT && g_runningState != RECORDING_LONG_DUMP &&
911b0e7dd80Sopenharmony_ci        g_runningState != RECORDING_LONG_FINISH) {
912b0e7dd80Sopenharmony_ci        ConsoleLog(std::string(argv[0]) + " enter, running_state is " + GetStateInfo(g_runningState));
913b0e7dd80Sopenharmony_ci    }
914b0e7dd80Sopenharmony_ci
915b0e7dd80Sopenharmony_ci    switch (g_runningState) {
916b0e7dd80Sopenharmony_ci        case RECORDING_SHORT_RAW:
917b0e7dd80Sopenharmony_ci            isSuccess = HandleRecordingShortRaw();
918b0e7dd80Sopenharmony_ci            break;
919b0e7dd80Sopenharmony_ci        case RECORDING_SHORT_TEXT:
920b0e7dd80Sopenharmony_ci            isSuccess = HandleRecordingShortText();
921b0e7dd80Sopenharmony_ci            break;
922b0e7dd80Sopenharmony_ci        case RECORDING_LONG_BEGIN:
923b0e7dd80Sopenharmony_ci            isSuccess = HandleRecordingLongBegin();
924b0e7dd80Sopenharmony_ci            break;
925b0e7dd80Sopenharmony_ci        case RECORDING_LONG_DUMP:
926b0e7dd80Sopenharmony_ci            isSuccess = HandleRecordingLongDump();
927b0e7dd80Sopenharmony_ci            break;
928b0e7dd80Sopenharmony_ci        case RECORDING_LONG_FINISH:
929b0e7dd80Sopenharmony_ci            isSuccess = HandleRecordingLongFinish();
930b0e7dd80Sopenharmony_ci            break;
931b0e7dd80Sopenharmony_ci        case RECORDING_LONG_FINISH_NODUMP:
932b0e7dd80Sopenharmony_ci            isSuccess = HandleRecordingLongFinishNodump();
933b0e7dd80Sopenharmony_ci            break;
934b0e7dd80Sopenharmony_ci        case RECORDING_LONG_BEGIN_RECORD:
935b0e7dd80Sopenharmony_ci            isSuccess = HandleRecordingLongBeginRecord();
936b0e7dd80Sopenharmony_ci            break;
937b0e7dd80Sopenharmony_ci        case RECORDING_LONG_FINISH_RECORD:
938b0e7dd80Sopenharmony_ci            isSuccess = HandleRecordingLongFinishRecord();
939b0e7dd80Sopenharmony_ci            break;
940b0e7dd80Sopenharmony_ci        case SNAPSHOT_START:
941b0e7dd80Sopenharmony_ci            isSuccess = HandleOpenSnapshot();
942b0e7dd80Sopenharmony_ci            break;
943b0e7dd80Sopenharmony_ci        case SNAPSHOT_DUMP:
944b0e7dd80Sopenharmony_ci            isSuccess = HandleDumpSnapshot();
945b0e7dd80Sopenharmony_ci            break;
946b0e7dd80Sopenharmony_ci        case SNAPSHOT_STOP:
947b0e7dd80Sopenharmony_ci            isSuccess = HandleCloseSnapshot();
948b0e7dd80Sopenharmony_ci            break;
949b0e7dd80Sopenharmony_ci        case SHOW_HELP:
950b0e7dd80Sopenharmony_ci            ShowHelp(argv[0]);
951b0e7dd80Sopenharmony_ci            break;
952b0e7dd80Sopenharmony_ci        case SHOW_LIST_CATEGORY:
953b0e7dd80Sopenharmony_ci            ShowListCategory();
954b0e7dd80Sopenharmony_ci            break;
955b0e7dd80Sopenharmony_ci        default:
956b0e7dd80Sopenharmony_ci            ShowHelp(argv[0]);
957b0e7dd80Sopenharmony_ci            isSuccess = false;
958b0e7dd80Sopenharmony_ci            break;
959b0e7dd80Sopenharmony_ci    }
960b0e7dd80Sopenharmony_ci    return isSuccess ? 0 : -1;
961b0e7dd80Sopenharmony_ci}
962