• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "tracing_sdk.h"
18 
19 #include <android-base/logging.h>
20 #include <cutils/trace.h>
21 
22 #include <cstdarg>
23 #include <cstdlib>
24 
25 #include "perfetto/public/abi/producer_abi.h"
26 #include "perfetto/public/te_category_macros.h"
27 #include "perfetto/public/te_macros.h"
28 #include "perfetto/public/track_event.h"
29 #include "tracing_perfetto.h"
30 
31 namespace tracing_perfetto {
trace_event(int type,const PerfettoTeCategory * perfettoTeCategory,const char * name,tracing_perfetto::Extra * extra)32 void trace_event(int type, const PerfettoTeCategory* perfettoTeCategory,
33                  const char* name, tracing_perfetto::Extra* extra) {
34   bool enabled = PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT(
35       perfettoTeCategory->enabled, PERFETTO_MEMORY_ORDER_RELAXED));
36   if (enabled) {
37     extra->push_extra(nullptr);
38     PerfettoTeHlEmitImpl(perfettoTeCategory->impl, type,
39                          type == PERFETTO_TE_TYPE_COUNTER ? nullptr : name,
40                          extra->get());
41     extra->clear_extras();
42   }
43 }
44 
get_process_track_uuid()45 uint64_t get_process_track_uuid() {
46   return PerfettoTeProcessTrackUuid();
47 }
48 
get_thread_track_uuid(pid_t tid)49 uint64_t get_thread_track_uuid(pid_t tid) {
50   // Cating a signed pid_t to unsigned
51   return PerfettoTeProcessTrackUuid() ^ PERFETTO_STATIC_CAST(uint64_t, tid);
52 }
53 
Extra()54 Extra::Extra() {
55 }
56 
push_extra(PerfettoTeHlExtra * ptr)57 void Extra::push_extra(PerfettoTeHlExtra* ptr) {
58   extras_.push_back(ptr);
59 }
60 
pop_extra()61 void Extra::pop_extra() {
62   extras_.pop_back();
63 }
64 
clear_extras()65 void Extra::clear_extras() {
66   extras_.clear();
67 }
68 
delete_extra(Extra * ptr)69 void Extra::delete_extra(Extra* ptr) {
70   delete ptr;
71 }
72 
get() const73 PerfettoTeHlExtra* const* Extra::get() const {
74   return extras_.data();
75 }
76 
Category(const std::string & name,const std::string & tag,const std::string & severity)77 Category::Category(const std::string& name, const std::string& tag,
78                    const std::string& severity)
79     : category_({.enabled = &perfetto_atomic_false}),
80       name_(name),
81       tag_(tag),
82       severity_(severity) {
83 }
84 
~Category()85 Category::~Category() {
86   unregister_category();
87 }
88 
register_category()89 void Category::register_category() {
90   if (category_.impl) return;
91 
92   std::vector<const char*> tags;
93   if (!tag_.empty()) tags.push_back(tag_.data());
94   if (!severity_.empty()) tags.push_back(severity_.data());
95 
96   category_.desc = {name_.c_str(), name_.c_str(), tags.data(), tags.size()};
97 
98   PerfettoTeCategoryRegister(&category_);
99   PerfettoTePublishCategories();
100 }
101 
unregister_category()102 void Category::unregister_category() {
103   if (!category_.impl) return;
104 
105   PerfettoTeCategoryUnregister(&category_);
106   PerfettoTePublishCategories();
107 }
108 
is_category_enabled()109 bool Category::is_category_enabled() {
110   return PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT(
111       (category_).enabled, PERFETTO_MEMORY_ORDER_RELAXED));
112 }
113 
get() const114 const PerfettoTeCategory* Category::get() const {
115   return &category_;
116 }
117 
delete_category(Category * ptr)118 void Category::delete_category(Category* ptr) {
119   delete ptr;
120 }
121 
Flow()122 Flow::Flow() : flow_{} {
123 }
124 
set_process_flow(uint64_t id)125 void Flow::set_process_flow(uint64_t id) {
126   flow_.header.type = PERFETTO_TE_HL_EXTRA_TYPE_FLOW;
127   PerfettoTeFlow ret = PerfettoTeProcessScopedFlow(id);
128   flow_.id = ret.id;
129 }
130 
set_process_terminating_flow(uint64_t id)131 void Flow::set_process_terminating_flow(uint64_t id) {
132   flow_.header.type = PERFETTO_TE_HL_EXTRA_TYPE_TERMINATING_FLOW;
133   PerfettoTeFlow ret = PerfettoTeProcessScopedFlow(id);
134   flow_.id = ret.id;
135 }
136 
get() const137 const PerfettoTeHlExtraFlow* Flow::get() const {
138   return &flow_;
139 }
140 
delete_flow(Flow * ptr)141 void Flow::delete_flow(Flow* ptr) {
142   delete ptr;
143 }
144 
NamedTrack(uint64_t id,uint64_t parent_uuid,const std::string & name)145 NamedTrack::NamedTrack(uint64_t id, uint64_t parent_uuid,
146                        const std::string& name)
147     : name_(name),
148       track_{{PERFETTO_TE_HL_EXTRA_TYPE_NAMED_TRACK},
149              name_.data(),
150              id,
151              parent_uuid} {
152 }
153 
get() const154 const PerfettoTeHlExtraNamedTrack* NamedTrack::get() const {
155   return &track_;
156 }
157 
delete_track(NamedTrack * ptr)158 void NamedTrack::delete_track(NamedTrack* ptr) {
159   delete ptr;
160 }
161 
RegisteredTrack(uint64_t id,uint64_t parent_uuid,const std::string & name,bool is_counter)162 RegisteredTrack::RegisteredTrack(uint64_t id, uint64_t parent_uuid,
163                                  const std::string& name, bool is_counter)
164     : registered_track_{},
165       track_{{PERFETTO_TE_HL_EXTRA_TYPE_REGISTERED_TRACK},
166              &(registered_track_.impl)},
167       name_(name),
168       id_(id),
169       parent_uuid_(parent_uuid),
170       is_counter_(is_counter) {
171   register_track();
172 }
173 
~RegisteredTrack()174 RegisteredTrack::~RegisteredTrack() {
175   unregister_track();
176 }
177 
register_track()178 void RegisteredTrack::register_track() {
179   if (registered_track_.impl.descriptor) return;
180 
181   if (is_counter_) {
182     PerfettoTeCounterTrackRegister(&registered_track_, name_.data(),
183                                    parent_uuid_);
184   } else {
185     PerfettoTeNamedTrackRegister(&registered_track_, name_.data(), id_,
186                                  parent_uuid_);
187   }
188 }
189 
unregister_track()190 void RegisteredTrack::unregister_track() {
191   if (!registered_track_.impl.descriptor) return;
192   PerfettoTeRegisteredTrackUnregister(&registered_track_);
193 }
194 
get() const195 const PerfettoTeHlExtraRegisteredTrack* RegisteredTrack::get() const {
196   return &track_;
197 }
198 
delete_track(RegisteredTrack * ptr)199 void RegisteredTrack::delete_track(RegisteredTrack* ptr) {
200   delete ptr;
201 }
202 
Proto()203 Proto::Proto() : proto_({PERFETTO_TE_HL_EXTRA_TYPE_PROTO_FIELDS}, nullptr) {
204 }
205 
add_field(PerfettoTeHlProtoField * ptr)206 void Proto::add_field(PerfettoTeHlProtoField* ptr) {
207   if (!fields_.empty()) {
208     fields_.pop_back();
209   }
210 
211   fields_.push_back(ptr);
212   fields_.push_back(nullptr);
213   proto_.fields = fields_.data();
214 }
215 
clear_fields()216 void Proto::clear_fields() {
217   fields_.clear();
218   proto_.fields = nullptr;
219 }
220 
delete_proto(Proto * ptr)221 void Proto::delete_proto(Proto* ptr) {
222   delete ptr;
223 }
224 
get() const225 const PerfettoTeHlExtraProtoFields* Proto::get() const {
226   return &proto_;
227 }
228 
ProtoFieldNested()229 ProtoFieldNested::ProtoFieldNested()
230     : field_({PERFETTO_TE_HL_PROTO_TYPE_NESTED}, nullptr) {
231 }
232 
add_field(PerfettoTeHlProtoField * ptr)233 void ProtoFieldNested::add_field(PerfettoTeHlProtoField* ptr) {
234   if (!fields_.empty()) {
235     fields_.pop_back();
236   }
237 
238   fields_.push_back(ptr);
239   fields_.push_back(nullptr);
240   field_.fields = fields_.data();
241 }
242 
set_id(uint32_t id)243 void ProtoFieldNested::set_id(uint32_t id) {
244   fields_.clear();
245   field_.header.id = id;
246   field_.fields = nullptr;
247 }
248 
delete_field(ProtoFieldNested * ptr)249 void ProtoFieldNested::delete_field(ProtoFieldNested* ptr) {
250   delete ptr;
251 }
252 
get() const253 const PerfettoTeHlProtoFieldNested* ProtoFieldNested::get() const {
254   return &field_;
255 }
256 
Session(bool is_backend_in_process,void * buf,size_t len)257 Session::Session(bool is_backend_in_process, void* buf, size_t len) {
258   session_ = PerfettoTracingSessionCreate(is_backend_in_process
259                                               ? PERFETTO_BACKEND_IN_PROCESS
260                                               : PERFETTO_BACKEND_SYSTEM);
261 
262   PerfettoTracingSessionSetup(session_, buf, len);
263 
264   PerfettoTracingSessionStartBlocking(session_);
265 }
266 
~Session()267 Session::~Session() {
268   PerfettoTracingSessionStopBlocking(session_);
269   PerfettoTracingSessionDestroy(session_);
270 }
271 
FlushBlocking(uint32_t timeout_ms)272 bool Session::FlushBlocking(uint32_t timeout_ms) {
273   return PerfettoTracingSessionFlushBlocking(session_, timeout_ms);
274 }
275 
StopBlocking()276 void Session::StopBlocking() {
277   PerfettoTracingSessionStopBlocking(session_);
278 }
279 
ReadBlocking()280 std::vector<uint8_t> Session::ReadBlocking() {
281   std::vector<uint8_t> data;
282   PerfettoTracingSessionReadTraceBlocking(
283       session_,
284       [](struct PerfettoTracingSessionImpl*, const void* trace_data,
285          size_t size, bool, void* user_arg) {
286         auto& dst = *static_cast<std::vector<uint8_t>*>(user_arg);
287         auto* src = static_cast<const uint8_t*>(trace_data);
288         dst.insert(dst.end(), src, src + size);
289       },
290       &data);
291   return data;
292 }
293 
delete_session(Session * ptr)294 void Session::delete_session(Session* ptr) {
295   delete ptr;
296 }
297 
activate_trigger(const char * name,uint32_t ttl_ms)298 void activate_trigger(const char* name, uint32_t ttl_ms) {
299   const char* names[] = {name, nullptr};
300   PerfettoProducerActivateTriggers(names, ttl_ms);
301 }
302 }  // namespace tracing_perfetto
303