• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "hitrace_option/hitrace_option.h"
17 
18 #include <fcntl.h>
19 #include <sstream>
20 #include <filesystem>
21 #include <unistd.h>
22 
23 #include "hilog/log.h"
24 #include "parameters.h"
25 
26 namespace OHOS {
27 namespace HiviewDFX {
28 namespace Hitrace {
29 
30 #ifdef LOG_DOMAIN
31 #undef LOG_DOMAIN
32 #define LOG_DOMAIN 0xD002D33
33 #endif
34 #ifdef LOG_TAG
35 #undef LOG_TAG
36 #define LOG_TAG "HitraceOption"
37 #endif
38 
39 static const char* TELEMETRY_APP_PARAM = "debug.hitrace.telemetry.app";
40 static const char* SET_EVENT_PID = "/sys/kernel/tracing/set_event_pid";
41 static const char* DEBUG_SET_EVENT_PID = "/sys/kernel/debug/tracing/set_event_pid";
42 
43 class FileLock {
44 private:
45     int fd_ = -1;
46 public:
FileLock(const std::string & filename,int flags)47     explicit FileLock(const std::string& filename, int flags)
48     {
49         char canonicalPath[PATH_MAX + 1] = {0};
50         if (realpath(filename.c_str(), canonicalPath) == nullptr) {
51             HILOG_ERROR(LOG_CORE, "FileLock: %{public}s realpath failed, errno%{public}d", filename.c_str(), errno);
52             return;
53         }
54         fd_ = open(canonicalPath, flags);
55         if (fd_ == -1) {
56             HILOG_ERROR(LOG_CORE, "FileLock: %{public}s open failed, errno%{public}d", filename.c_str(), errno);
57             return;
58         }
59 
60 #ifdef ENABLE_LOCK
61         if (flock(fd_, LOCK_EX) != 0) {
62             HILOG_ERROR(LOG_CORE, "FileLock: %{public}s lock failed.", filename.c_str());
63             close(fd_);
64             fd_ = -1;
65         }
66         HILOG_INFO(LOG_CORE, "FileLock: %{public}s lock succ, fd = %{public}d", filename.c_str(), fd_);
67 #endif
68     }
69 
~FileLock()70     ~FileLock()
71     {
72         if (fd_ != -1) {
73 #ifdef ENABLE_LOCK
74             flock(fd_, LOCK_UN);
75             HILOG_INFO(LOG_CORE, "FileLock: %{public}d unlock succ", fd_);
76 #endif
77             close(fd_);
78         }
79     }
80 
Fd()81     int Fd()
82     {
83         return fd_;
84     }
85 };
86 
GetSubThreadIds(const std::string & pid)87 std::vector<std::string> GetSubThreadIds(const std::string& pid)
88 {
89     std::vector<std::string> ret;
90     std::string path = "/proc/" + pid + "/task/";
91 
92     if (std::filesystem::exists(path) && std::filesystem::is_directory(path)) {
93         for (const auto& entry : std::filesystem::directory_iterator(path)) {
94             ret.emplace_back(entry.path().filename());
95         }
96     }
97 
98     return ret;
99 }
100 
AppendToFile(const std::string & filename,const std::string & str)101 bool AppendToFile(const std::string& filename, const std::string& str)
102 {
103     FileLock fileLock(filename, O_RDWR);
104 
105     int fd = fileLock.Fd();
106     if (fd == -1) {
107         return false;
108     }
109 
110     if (write(fd, str.c_str(), str.size()) < 0) {
111         HILOG_ERROR(LOG_CORE, "AppendToFile: %{public}s write failed %{public}d", filename.c_str(), errno);
112         return false;
113     }
114     return true;
115 }
116 
SetFilterAppName(const std::string & app)117 int32_t SetFilterAppName(const std::string& app)
118 {
119     bool ret = OHOS::system::SetParameter(TELEMETRY_APP_PARAM, app);
120     HILOG_INFO(LOG_CORE, "SetTelemetryAppName %{public}s ret=%{public}d", app.c_str(), ret);
121     return ret ? HITRACE_NO_ERROR : HITRACE_SET_PARAM_ERROR;
122 }
123 
AddFilterPid(const pid_t pid)124 int32_t AddFilterPid(const pid_t pid)
125 {
126     std::vector<std::string> vec = { std::to_string(pid) };
127     return AddFilterPids(vec);
128 }
129 
AddFilterPids(const std::vector<std::string> & pids)130 int32_t AddFilterPids(const std::vector<std::string>& pids)
131 {
132     std::stringstream ss(" ");
133     for (const auto& pid : pids) {
134         for (const auto& tid : GetSubThreadIds(pid)) {
135             ss << tid << " ";
136         }
137     }
138 
139     std::string pidStr = ss.str();
140     if (AppendToFile(DEBUG_SET_EVENT_PID, pidStr) || AppendToFile(SET_EVENT_PID, pidStr)) {
141         HILOG_INFO(LOG_CORE, "AddFilterPids %{public}s success", pidStr.c_str());
142         return HITRACE_NO_ERROR;
143     }
144 
145     HILOG_INFO(LOG_CORE, "AddFilterPids %{public}s fail", pidStr.c_str());
146     return HITRACE_WRITE_FILE_ERROR;
147 }
148 
ClearFilterPid()149 int32_t ClearFilterPid()
150 {
151     int fd = creat(DEBUG_SET_EVENT_PID, 0);
152     if (fd != -1) {
153         close(fd);
154         HILOG_INFO(LOG_CORE, "ClearFilterPid success");
155         return HITRACE_NO_ERROR;
156     }
157 
158     fd = creat(SET_EVENT_PID, 0);
159     if (fd != -1) {
160         close(fd);
161         HILOG_INFO(LOG_CORE, "ClearFilterPid success");
162         return HITRACE_NO_ERROR;
163     }
164 
165     HILOG_INFO(LOG_CORE, "ClearFilterPid fail");
166     return HITRACE_WRITE_FILE_ERROR;
167 }
168 
FilterAppTrace(const char * app,pid_t pid)169 void FilterAppTrace(const char* app, pid_t pid)
170 {
171     if (app == nullptr) {
172         HILOG_INFO(LOG_CORE, "FilterAppTrace: app is null");
173         return;
174     }
175     HILOG_INFO(LOG_CORE, "FilterAppTrace %{public}s %{public}d", app, pid);
176     std::string paramApp = OHOS::system::GetParameter(TELEMETRY_APP_PARAM, "");
177     if (paramApp == app) {
178         AddFilterPid(pid);
179     }
180 }
181 
182 } // namespace Hitrace
183 } // namespace HiviewDFX
184 } // namespace OHOS
185