1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/common/proc_utils.h"
18*6dbdd20aSAndroid Build Coastguard Worker
19*6dbdd20aSAndroid Build Coastguard Worker #include <sys/stat.h>
20*6dbdd20aSAndroid Build Coastguard Worker #include <unistd.h>
21*6dbdd20aSAndroid Build Coastguard Worker
22*6dbdd20aSAndroid Build Coastguard Worker #include <cinttypes>
23*6dbdd20aSAndroid Build Coastguard Worker #include <optional>
24*6dbdd20aSAndroid Build Coastguard Worker
25*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/file_utils.h"
26*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_utils.h"
27*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/common/proc_cmdline.h"
28*6dbdd20aSAndroid Build Coastguard Worker
29*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
30*6dbdd20aSAndroid Build Coastguard Worker namespace profiling {
31*6dbdd20aSAndroid Build Coastguard Worker namespace {
32*6dbdd20aSAndroid Build Coastguard Worker
ParseProcStatusSize(const std::string & status,const std::string & key)33*6dbdd20aSAndroid Build Coastguard Worker std::optional<uint32_t> ParseProcStatusSize(const std::string& status,
34*6dbdd20aSAndroid Build Coastguard Worker const std::string& key) {
35*6dbdd20aSAndroid Build Coastguard Worker auto entry_idx = status.find(key);
36*6dbdd20aSAndroid Build Coastguard Worker if (entry_idx == std::string::npos)
37*6dbdd20aSAndroid Build Coastguard Worker return {};
38*6dbdd20aSAndroid Build Coastguard Worker entry_idx = status.find_first_not_of(" \t", entry_idx + key.size());
39*6dbdd20aSAndroid Build Coastguard Worker if (entry_idx == std::string::npos)
40*6dbdd20aSAndroid Build Coastguard Worker return {};
41*6dbdd20aSAndroid Build Coastguard Worker int32_t val = atoi(status.c_str() + entry_idx);
42*6dbdd20aSAndroid Build Coastguard Worker if (val < 0) {
43*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Unexpected value reading %s", key.c_str());
44*6dbdd20aSAndroid Build Coastguard Worker return {};
45*6dbdd20aSAndroid Build Coastguard Worker }
46*6dbdd20aSAndroid Build Coastguard Worker return static_cast<uint32_t>(val);
47*6dbdd20aSAndroid Build Coastguard Worker }
48*6dbdd20aSAndroid Build Coastguard Worker } // namespace
49*6dbdd20aSAndroid Build Coastguard Worker
ReadStatus(pid_t pid)50*6dbdd20aSAndroid Build Coastguard Worker std::optional<std::string> ReadStatus(pid_t pid) {
51*6dbdd20aSAndroid Build Coastguard Worker std::string path = "/proc/" + std::to_string(pid) + "/status";
52*6dbdd20aSAndroid Build Coastguard Worker std::string status;
53*6dbdd20aSAndroid Build Coastguard Worker bool read_proc = base::ReadFile(path, &status);
54*6dbdd20aSAndroid Build Coastguard Worker if (!read_proc) {
55*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Failed to read %s", path.c_str());
56*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
57*6dbdd20aSAndroid Build Coastguard Worker }
58*6dbdd20aSAndroid Build Coastguard Worker return std::optional<std::string>(status);
59*6dbdd20aSAndroid Build Coastguard Worker }
60*6dbdd20aSAndroid Build Coastguard Worker
GetRssAnonAndSwap(const std::string & status)61*6dbdd20aSAndroid Build Coastguard Worker std::optional<uint32_t> GetRssAnonAndSwap(const std::string& status) {
62*6dbdd20aSAndroid Build Coastguard Worker auto anon_rss = ParseProcStatusSize(status, "RssAnon:");
63*6dbdd20aSAndroid Build Coastguard Worker auto swap = ParseProcStatusSize(status, "VmSwap:");
64*6dbdd20aSAndroid Build Coastguard Worker if (anon_rss.has_value() && swap.has_value()) {
65*6dbdd20aSAndroid Build Coastguard Worker return *anon_rss + *swap;
66*6dbdd20aSAndroid Build Coastguard Worker }
67*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
68*6dbdd20aSAndroid Build Coastguard Worker }
69*6dbdd20aSAndroid Build Coastguard Worker
RemoveUnderAnonThreshold(uint32_t min_size_kb,std::set<pid_t> * pids)70*6dbdd20aSAndroid Build Coastguard Worker void RemoveUnderAnonThreshold(uint32_t min_size_kb, std::set<pid_t>* pids) {
71*6dbdd20aSAndroid Build Coastguard Worker for (auto it = pids->begin(); it != pids->end();) {
72*6dbdd20aSAndroid Build Coastguard Worker const pid_t pid = *it;
73*6dbdd20aSAndroid Build Coastguard Worker
74*6dbdd20aSAndroid Build Coastguard Worker std::optional<std::string> status = ReadStatus(pid);
75*6dbdd20aSAndroid Build Coastguard Worker std::optional<uint32_t> rss_and_swap;
76*6dbdd20aSAndroid Build Coastguard Worker if (status)
77*6dbdd20aSAndroid Build Coastguard Worker rss_and_swap = GetRssAnonAndSwap(*status);
78*6dbdd20aSAndroid Build Coastguard Worker
79*6dbdd20aSAndroid Build Coastguard Worker if (rss_and_swap && rss_and_swap < min_size_kb) {
80*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_LOG("Removing pid %d from profiled set (anon: %d kB < %" PRIu32
81*6dbdd20aSAndroid Build Coastguard Worker ")",
82*6dbdd20aSAndroid Build Coastguard Worker pid, *rss_and_swap, min_size_kb);
83*6dbdd20aSAndroid Build Coastguard Worker it = pids->erase(it);
84*6dbdd20aSAndroid Build Coastguard Worker } else {
85*6dbdd20aSAndroid Build Coastguard Worker ++it;
86*6dbdd20aSAndroid Build Coastguard Worker }
87*6dbdd20aSAndroid Build Coastguard Worker }
88*6dbdd20aSAndroid Build Coastguard Worker }
89*6dbdd20aSAndroid Build Coastguard Worker
GetUids(const std::string & status)90*6dbdd20aSAndroid Build Coastguard Worker std::optional<Uids> GetUids(const std::string& status) {
91*6dbdd20aSAndroid Build Coastguard Worker auto entry_idx = status.find("Uid:");
92*6dbdd20aSAndroid Build Coastguard Worker if (entry_idx == std::string::npos)
93*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
94*6dbdd20aSAndroid Build Coastguard Worker
95*6dbdd20aSAndroid Build Coastguard Worker Uids uids;
96*6dbdd20aSAndroid Build Coastguard Worker const char* str = &status[entry_idx + 4];
97*6dbdd20aSAndroid Build Coastguard Worker char* endptr;
98*6dbdd20aSAndroid Build Coastguard Worker
99*6dbdd20aSAndroid Build Coastguard Worker uids.real = strtoull(str, &endptr, 10);
100*6dbdd20aSAndroid Build Coastguard Worker if (*endptr != ' ' && *endptr != '\t')
101*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
102*6dbdd20aSAndroid Build Coastguard Worker
103*6dbdd20aSAndroid Build Coastguard Worker str = endptr;
104*6dbdd20aSAndroid Build Coastguard Worker uids.effective = strtoull(str, &endptr, 10);
105*6dbdd20aSAndroid Build Coastguard Worker if (*endptr != ' ' && *endptr != '\t')
106*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
107*6dbdd20aSAndroid Build Coastguard Worker
108*6dbdd20aSAndroid Build Coastguard Worker str = endptr;
109*6dbdd20aSAndroid Build Coastguard Worker uids.saved_set = strtoull(str, &endptr, 10);
110*6dbdd20aSAndroid Build Coastguard Worker if (*endptr != ' ' && *endptr != '\t')
111*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
112*6dbdd20aSAndroid Build Coastguard Worker
113*6dbdd20aSAndroid Build Coastguard Worker str = endptr;
114*6dbdd20aSAndroid Build Coastguard Worker uids.filesystem = strtoull(str, &endptr, 10);
115*6dbdd20aSAndroid Build Coastguard Worker if (*endptr != '\n' && *endptr != '\0')
116*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
117*6dbdd20aSAndroid Build Coastguard Worker return uids;
118*6dbdd20aSAndroid Build Coastguard Worker }
119*6dbdd20aSAndroid Build Coastguard Worker
120*6dbdd20aSAndroid Build Coastguard Worker // Normalize cmdline in place. Stores new beginning of string in *cmdline_ptr.
121*6dbdd20aSAndroid Build Coastguard Worker // Returns new size of string (from new beginning).
122*6dbdd20aSAndroid Build Coastguard Worker // Modifies string in *cmdline_ptr.
NormalizeCmdLine(char ** cmdline_ptr,size_t size)123*6dbdd20aSAndroid Build Coastguard Worker ssize_t NormalizeCmdLine(char** cmdline_ptr, size_t size) {
124*6dbdd20aSAndroid Build Coastguard Worker char* cmdline = *cmdline_ptr;
125*6dbdd20aSAndroid Build Coastguard Worker char* first_arg = static_cast<char*>(memchr(cmdline, '\0', size));
126*6dbdd20aSAndroid Build Coastguard Worker if (first_arg == nullptr) {
127*6dbdd20aSAndroid Build Coastguard Worker errno = EOVERFLOW;
128*6dbdd20aSAndroid Build Coastguard Worker return -1;
129*6dbdd20aSAndroid Build Coastguard Worker }
130*6dbdd20aSAndroid Build Coastguard Worker // For consistency with what we do with Java app cmdlines, trim everything
131*6dbdd20aSAndroid Build Coastguard Worker // after the @ sign of the first arg.
132*6dbdd20aSAndroid Build Coastguard Worker char* first_at = static_cast<char*>(memchr(cmdline, '@', size));
133*6dbdd20aSAndroid Build Coastguard Worker if (first_at != nullptr && first_at < first_arg) {
134*6dbdd20aSAndroid Build Coastguard Worker *first_at = '\0';
135*6dbdd20aSAndroid Build Coastguard Worker first_arg = first_at;
136*6dbdd20aSAndroid Build Coastguard Worker }
137*6dbdd20aSAndroid Build Coastguard Worker char* start = static_cast<char*>(
138*6dbdd20aSAndroid Build Coastguard Worker memrchr(cmdline, '/', static_cast<size_t>(first_arg - cmdline)));
139*6dbdd20aSAndroid Build Coastguard Worker if (start == nullptr) {
140*6dbdd20aSAndroid Build Coastguard Worker start = cmdline;
141*6dbdd20aSAndroid Build Coastguard Worker } else {
142*6dbdd20aSAndroid Build Coastguard Worker // Skip the /.
143*6dbdd20aSAndroid Build Coastguard Worker start++;
144*6dbdd20aSAndroid Build Coastguard Worker }
145*6dbdd20aSAndroid Build Coastguard Worker *cmdline_ptr = start;
146*6dbdd20aSAndroid Build Coastguard Worker return first_arg - start;
147*6dbdd20aSAndroid Build Coastguard Worker }
148*6dbdd20aSAndroid Build Coastguard Worker
NormalizeCmdlines(const std::vector<std::string> & cmdlines)149*6dbdd20aSAndroid Build Coastguard Worker std::optional<std::vector<std::string>> NormalizeCmdlines(
150*6dbdd20aSAndroid Build Coastguard Worker const std::vector<std::string>& cmdlines) {
151*6dbdd20aSAndroid Build Coastguard Worker std::vector<std::string> normalized_cmdlines;
152*6dbdd20aSAndroid Build Coastguard Worker normalized_cmdlines.reserve(cmdlines.size());
153*6dbdd20aSAndroid Build Coastguard Worker
154*6dbdd20aSAndroid Build Coastguard Worker for (size_t i = 0; i < cmdlines.size(); i++) {
155*6dbdd20aSAndroid Build Coastguard Worker std::string cmdline = cmdlines[i]; // mutable copy
156*6dbdd20aSAndroid Build Coastguard Worker // Add nullbyte to make sure it's a C string.
157*6dbdd20aSAndroid Build Coastguard Worker cmdline.resize(cmdline.size() + 1, '\0');
158*6dbdd20aSAndroid Build Coastguard Worker char* cmdline_cstr = &(cmdline[0]);
159*6dbdd20aSAndroid Build Coastguard Worker ssize_t size = NormalizeCmdLine(&cmdline_cstr, cmdline.size());
160*6dbdd20aSAndroid Build Coastguard Worker if (size == -1) {
161*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_PLOG("Failed to normalize cmdline %s. Stopping the parse.",
162*6dbdd20aSAndroid Build Coastguard Worker cmdlines[i].c_str());
163*6dbdd20aSAndroid Build Coastguard Worker return std::nullopt;
164*6dbdd20aSAndroid Build Coastguard Worker }
165*6dbdd20aSAndroid Build Coastguard Worker normalized_cmdlines.emplace_back(cmdline_cstr, static_cast<size_t>(size));
166*6dbdd20aSAndroid Build Coastguard Worker }
167*6dbdd20aSAndroid Build Coastguard Worker return std::make_optional(normalized_cmdlines);
168*6dbdd20aSAndroid Build Coastguard Worker }
169*6dbdd20aSAndroid Build Coastguard Worker
170*6dbdd20aSAndroid Build Coastguard Worker // This is mostly the same as GetHeapprofdProgramProperty in
171*6dbdd20aSAndroid Build Coastguard Worker // https://android.googlesource.com/platform/bionic/+/main/libc/bionic/malloc_common.cpp
172*6dbdd20aSAndroid Build Coastguard Worker // This should give the same result as GetHeapprofdProgramProperty.
GetCmdlineForPID(pid_t pid,std::string * name)173*6dbdd20aSAndroid Build Coastguard Worker bool GetCmdlineForPID(pid_t pid, std::string* name) {
174*6dbdd20aSAndroid Build Coastguard Worker std::string filename = "/proc/" + std::to_string(pid) + "/cmdline";
175*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFile fd(base::OpenFile(filename, O_RDONLY | O_CLOEXEC));
176*6dbdd20aSAndroid Build Coastguard Worker if (!fd) {
177*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DPLOG("Failed to open %s", filename.c_str());
178*6dbdd20aSAndroid Build Coastguard Worker return false;
179*6dbdd20aSAndroid Build Coastguard Worker }
180*6dbdd20aSAndroid Build Coastguard Worker char cmdline[512];
181*6dbdd20aSAndroid Build Coastguard Worker const size_t max_read_size = sizeof(cmdline) - 1;
182*6dbdd20aSAndroid Build Coastguard Worker ssize_t rd = read(*fd, cmdline, max_read_size);
183*6dbdd20aSAndroid Build Coastguard Worker if (rd == -1) {
184*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DPLOG("Failed to read %s", filename.c_str());
185*6dbdd20aSAndroid Build Coastguard Worker return false;
186*6dbdd20aSAndroid Build Coastguard Worker }
187*6dbdd20aSAndroid Build Coastguard Worker
188*6dbdd20aSAndroid Build Coastguard Worker if (rd == 0) {
189*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DLOG("Empty cmdline for %" PRIdMAX ". Skipping.",
190*6dbdd20aSAndroid Build Coastguard Worker static_cast<intmax_t>(pid));
191*6dbdd20aSAndroid Build Coastguard Worker return false;
192*6dbdd20aSAndroid Build Coastguard Worker }
193*6dbdd20aSAndroid Build Coastguard Worker
194*6dbdd20aSAndroid Build Coastguard Worker // In some buggy kernels (before http://bit.ly/37R7qwL) /proc/pid/cmdline is
195*6dbdd20aSAndroid Build Coastguard Worker // not NUL-terminated (see b/147438623). If we read < max_read_size bytes
196*6dbdd20aSAndroid Build Coastguard Worker // assume we are hitting the aforementioned kernel bug and terminate anyways.
197*6dbdd20aSAndroid Build Coastguard Worker const size_t rd_u = static_cast<size_t>(rd);
198*6dbdd20aSAndroid Build Coastguard Worker if (rd_u >= max_read_size && memchr(cmdline, '\0', rd_u) == nullptr) {
199*6dbdd20aSAndroid Build Coastguard Worker // We did not manage to read the first argument.
200*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DLOG("Overflow reading cmdline for %" PRIdMAX,
201*6dbdd20aSAndroid Build Coastguard Worker static_cast<intmax_t>(pid));
202*6dbdd20aSAndroid Build Coastguard Worker errno = EOVERFLOW;
203*6dbdd20aSAndroid Build Coastguard Worker return false;
204*6dbdd20aSAndroid Build Coastguard Worker }
205*6dbdd20aSAndroid Build Coastguard Worker
206*6dbdd20aSAndroid Build Coastguard Worker cmdline[rd] = '\0';
207*6dbdd20aSAndroid Build Coastguard Worker char* cmdline_start = cmdline;
208*6dbdd20aSAndroid Build Coastguard Worker ssize_t size = NormalizeCmdLine(&cmdline_start, rd_u);
209*6dbdd20aSAndroid Build Coastguard Worker if (size == -1)
210*6dbdd20aSAndroid Build Coastguard Worker return false;
211*6dbdd20aSAndroid Build Coastguard Worker name->assign(cmdline_start, static_cast<size_t>(size));
212*6dbdd20aSAndroid Build Coastguard Worker return true;
213*6dbdd20aSAndroid Build Coastguard Worker }
214*6dbdd20aSAndroid Build Coastguard Worker
FindAllProfilablePids(std::set<pid_t> * pids)215*6dbdd20aSAndroid Build Coastguard Worker void FindAllProfilablePids(std::set<pid_t>* pids) {
216*6dbdd20aSAndroid Build Coastguard Worker ForEachPid([pids](pid_t pid) {
217*6dbdd20aSAndroid Build Coastguard Worker if (pid == getpid())
218*6dbdd20aSAndroid Build Coastguard Worker return;
219*6dbdd20aSAndroid Build Coastguard Worker
220*6dbdd20aSAndroid Build Coastguard Worker char filename_buf[128];
221*6dbdd20aSAndroid Build Coastguard Worker snprintf(filename_buf, sizeof(filename_buf), "/proc/%d/%s", pid, "cmdline");
222*6dbdd20aSAndroid Build Coastguard Worker struct stat statbuf;
223*6dbdd20aSAndroid Build Coastguard Worker // Check if we have permission to the process.
224*6dbdd20aSAndroid Build Coastguard Worker if (stat(filename_buf, &statbuf) == 0)
225*6dbdd20aSAndroid Build Coastguard Worker pids->emplace(pid);
226*6dbdd20aSAndroid Build Coastguard Worker });
227*6dbdd20aSAndroid Build Coastguard Worker }
228*6dbdd20aSAndroid Build Coastguard Worker
FindPidsForCmdlines(const std::vector<std::string> & cmdlines,std::set<pid_t> * pids)229*6dbdd20aSAndroid Build Coastguard Worker void FindPidsForCmdlines(const std::vector<std::string>& cmdlines,
230*6dbdd20aSAndroid Build Coastguard Worker std::set<pid_t>* pids) {
231*6dbdd20aSAndroid Build Coastguard Worker ForEachPid([&cmdlines, pids](pid_t pid) {
232*6dbdd20aSAndroid Build Coastguard Worker if (pid == getpid())
233*6dbdd20aSAndroid Build Coastguard Worker return;
234*6dbdd20aSAndroid Build Coastguard Worker std::string process_cmdline;
235*6dbdd20aSAndroid Build Coastguard Worker process_cmdline.reserve(512);
236*6dbdd20aSAndroid Build Coastguard Worker GetCmdlineForPID(pid, &process_cmdline);
237*6dbdd20aSAndroid Build Coastguard Worker for (const std::string& cmdline : cmdlines) {
238*6dbdd20aSAndroid Build Coastguard Worker if (process_cmdline == cmdline)
239*6dbdd20aSAndroid Build Coastguard Worker pids->emplace(static_cast<pid_t>(pid));
240*6dbdd20aSAndroid Build Coastguard Worker }
241*6dbdd20aSAndroid Build Coastguard Worker });
242*6dbdd20aSAndroid Build Coastguard Worker }
243*6dbdd20aSAndroid Build Coastguard Worker
244*6dbdd20aSAndroid Build Coastguard Worker namespace glob_aware {
FindPidsForCmdlinePatterns(const std::vector<std::string> & patterns,std::set<pid_t> * pids)245*6dbdd20aSAndroid Build Coastguard Worker void FindPidsForCmdlinePatterns(const std::vector<std::string>& patterns,
246*6dbdd20aSAndroid Build Coastguard Worker std::set<pid_t>* pids) {
247*6dbdd20aSAndroid Build Coastguard Worker ForEachPid([&patterns, pids](pid_t pid) {
248*6dbdd20aSAndroid Build Coastguard Worker if (pid == getpid())
249*6dbdd20aSAndroid Build Coastguard Worker return;
250*6dbdd20aSAndroid Build Coastguard Worker std::string cmdline;
251*6dbdd20aSAndroid Build Coastguard Worker if (!glob_aware::ReadProcCmdlineForPID(pid, &cmdline))
252*6dbdd20aSAndroid Build Coastguard Worker return;
253*6dbdd20aSAndroid Build Coastguard Worker const char* binname =
254*6dbdd20aSAndroid Build Coastguard Worker glob_aware::FindBinaryName(cmdline.c_str(), cmdline.size());
255*6dbdd20aSAndroid Build Coastguard Worker
256*6dbdd20aSAndroid Build Coastguard Worker for (const std::string& pattern : patterns) {
257*6dbdd20aSAndroid Build Coastguard Worker if (glob_aware::MatchGlobPattern(pattern.c_str(), cmdline.c_str(),
258*6dbdd20aSAndroid Build Coastguard Worker binname)) {
259*6dbdd20aSAndroid Build Coastguard Worker pids->insert(pid);
260*6dbdd20aSAndroid Build Coastguard Worker }
261*6dbdd20aSAndroid Build Coastguard Worker }
262*6dbdd20aSAndroid Build Coastguard Worker });
263*6dbdd20aSAndroid Build Coastguard Worker }
264*6dbdd20aSAndroid Build Coastguard Worker } // namespace glob_aware
265*6dbdd20aSAndroid Build Coastguard Worker
266*6dbdd20aSAndroid Build Coastguard Worker } // namespace profiling
267*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
268