• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 #ifndef SRC_ANDROID_SDK_PERFETTO_SDK_FOR_JNI_TRACING_SDK_H_
18 #define SRC_ANDROID_SDK_PERFETTO_SDK_FOR_JNI_TRACING_SDK_H_
19 
20 #include <stdint.h>
21 
22 #include <optional>
23 #include <string>
24 #include <vector>
25 
26 #include "perfetto/ext/base/sys_types.h"  // for pid_t
27 #include "perfetto/public/tracing_session.h"
28 #include "perfetto/public/track_event.h"
29 
30 // Macro copied from
31 // https://source.corp.google.com/h/googleplex-android/platform/superproject/main/+/main:system/libbase/include/android-base/macros.h;l=45;drc=bd641075ad60ed703baf59f63a9153d96d96b98e
32 // A macro to disallow the copy constructor and operator= functions
33 // This must be placed in the private: declarations for a class.
34 //
35 // For disallowing only assign or copy, delete the relevant operator or
36 // constructor, for example:
37 // void operator=(const TypeName&) = delete;
38 // Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken
39 // semantically, one should either use disallow both or neither. Try to
40 // avoid these in new code.
41 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
42   TypeName(const TypeName&) = delete;      \
43   void operator=(const TypeName&) = delete
44 
45 /**
46  * The objects declared here are intended to be managed by Java.
47  * This means the Java Garbage Collector is responsible for freeing the
48  * underlying native resources.
49  *
50  * The static methods prefixed with `delete_` are special. They are designed to
51  * be invoked by Java through the `NativeAllocationRegistry` when the
52  * corresponding Java object becomes unreachable.  These methods act as
53  * callbacks to ensure proper deallocation of native resources.
54  */
55 namespace perfetto {
56 namespace sdk_for_jni {
57 /**
58  * @brief Initializes the global perfetto instance.
59  * @param backend_in_process use in-process or system backend
60  */
61 void register_perfetto(bool backend_in_process = false);
62 
63 /**
64  * @brief Represents extra data associated with a trace event.
65  * This class manages a collection of PerfettoTeHlExtra pointers.
66  */
67 class Extra;
68 
69 /**
70  * @brief Emits a trace event.
71  * @param type The type of the event.
72  * @param cat The category of the event.
73  * @param name The name of the event.
74  * @param extra Pointer to Extra data.
75  */
76 void trace_event(int type,
77                  const PerfettoTeCategory* cat,
78                  const char* name,
79                  Extra* extra);
80 
81 /**
82  * @brief Gets the process track UUID.
83  */
84 uint64_t get_process_track_uuid();
85 
86 /**
87  * @brief Gets the thread track UUID for a given PID.
88  */
89 uint64_t get_thread_track_uuid(pid_t tid);
90 
91 /**
92  * @brief Holder for all the other classes in the file.
93  */
94 class Extra {
95  public:
96   Extra();
97   void push_extra(PerfettoTeHlExtra* extra);
98   void pop_extra();
99   void clear_extras();
100   static void delete_extra(Extra* extra);
101 
102   PerfettoTeHlExtra* const* get() const;
103 
104  private:
105   DISALLOW_COPY_AND_ASSIGN(Extra);
106 
107   // These PerfettoTeHlExtra pointers are really pointers to all the other
108   // types of extras: Category, DebugArg, Counter etc. Those objects are
109   // individually managed by Java.
110   std::vector<PerfettoTeHlExtra*> extras_;
111 };
112 
113 /**
114  * @brief Represents a trace event category.
115  */
116 class Category {
117  public:
118   Category(const std::string& name,
119            const std::string& tag,
120            const std::string& severity);
121 
122   ~Category();
123 
124   void register_category();
125 
126   void unregister_category();
127 
128   bool is_category_enabled();
129 
130   static void delete_category(Category* category);
131 
132   const PerfettoTeCategory* get() const;
133 
134  private:
135   DISALLOW_COPY_AND_ASSIGN(Category);
136   PerfettoTeCategory category_;
137   const std::string name_;
138   const std::string tag_;
139   const std::string severity_;
140 };
141 
142 /**
143  * @brief Represents one end of a flow between two events.
144  */
145 class Flow {
146  public:
147   Flow();
148 
149   void set_process_flow(uint64_t id);
150   void set_process_terminating_flow(uint64_t id);
151   static void delete_flow(Flow* flow);
152 
153   const PerfettoTeHlExtraFlow* get() const;
154 
155  private:
156   DISALLOW_COPY_AND_ASSIGN(Flow);
157   PerfettoTeHlExtraFlow flow_;
158 };
159 
160 /**
161  * @brief Represents a named track.
162  */
163 class NamedTrack {
164  public:
165   NamedTrack(uint64_t id, uint64_t parent_uuid, const std::string& name);
166 
167   static void delete_track(NamedTrack* track);
168 
169   const PerfettoTeHlExtraNamedTrack* get() const;
170 
171  private:
172   DISALLOW_COPY_AND_ASSIGN(NamedTrack);
173   const std::string name_;
174   PerfettoTeHlExtraNamedTrack track_;
175 };
176 
177 /**
178  * @brief Represents a registered track.
179  */
180 class RegisteredTrack {
181  public:
182   RegisteredTrack(uint64_t id,
183                   uint64_t parent_uuid,
184                   const std::string& name,
185                   bool is_counter);
186   ~RegisteredTrack();
187 
188   void register_track();
189   void unregister_track();
190   static void delete_track(RegisteredTrack* track);
191 
192   const PerfettoTeHlExtraRegisteredTrack* get() const;
193 
194  private:
195   DISALLOW_COPY_AND_ASSIGN(RegisteredTrack);
196   PerfettoTeRegisteredTrack registered_track_;
197   PerfettoTeHlExtraRegisteredTrack track_;
198   const std::string name_;
199   const uint64_t id_;
200   const uint64_t parent_uuid_;
201   const bool is_counter_;
202 };
203 
204 /**
205  * @brief Represents a counter track event.
206  * @tparam T The data type of the counter (int64_t or double).
207  */
208 template <typename T>
209 class Counter {
210  public:
211   template <typename>
212   struct always_false : std::false_type {};
213 
214   template <class I>
215   struct type_identity {
216     using type = I;
217   };
218 
219   struct TypeMap {
220     template <typename CounterT>
get_counter_typeTypeMap221     static constexpr auto get_counter_type() {
222       if constexpr (std::is_same_v<CounterT, int64_t>) {
223         return type_identity<PerfettoTeHlExtraCounterInt64>{};
224       } else if constexpr (std::is_same_v<CounterT, double>) {
225         return type_identity<PerfettoTeHlExtraCounterDouble>{};
226       } else {
227         return type_identity<void>{};
228       }
229     }
230     using type = typename decltype(get_counter_type<T>())::type;
231 
232     static constexpr int enum_value = []() {
233       if constexpr (std::is_same_v<T, int64_t>) {
234         return PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_INT64;
235       } else if constexpr (std::is_same_v<T, double>) {
236         return PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_DOUBLE;
237       } else {
238         static_assert(always_false<T>::value, "Unsupported type");
239         return 0;  // Never reached, just to satisfy return type
240       }
241     }();
242   };
243 
Counter()244   Counter() {
245     static_assert(!std::is_same_v<typename TypeMap::type, void>,
246                   "Unsupported type for Counter");
247 
248     typename TypeMap::type counter;
249     counter.header = {TypeMap::enum_value};
250     counter_ = std::move(counter);
251   }
252 
set_value(T value)253   void set_value(T value) {
254     if constexpr (std::is_same_v<T, int64_t>) {
255       counter_.value = value;
256     } else if constexpr (std::is_same_v<T, double>) {
257       counter_.value = value;
258     }
259   }
260 
delete_counter(Counter * counter)261   static void delete_counter(Counter* counter) { delete counter; }
262 
get()263   const typename TypeMap::type* get() const { return &counter_; }
264 
265  private:
266   DISALLOW_COPY_AND_ASSIGN(Counter);
267   typename TypeMap::type counter_;
268 };
269 
270 /**
271  * @brief Represents a debug argument for a trace event.
272  * @tparam T The data type of the argument (bool, int64_t, double, const char*).
273  */
274 template <typename T>
275 class DebugArg {
276  public:
277   template <typename>
278   struct always_false : std::false_type {};
279 
280   template <class I>
281   struct type_identity {
282     using type = I;
283   };
284 
285   struct TypeMap {
286     template <typename DebugArgT>
get_debug_arg_typeTypeMap287     static constexpr auto get_debug_arg_type() {
288       if constexpr (std::is_same_v<DebugArgT, bool>) {
289         return type_identity<PerfettoTeHlExtraDebugArgBool>{};
290       } else if constexpr (std::is_same_v<DebugArgT, int64_t>) {
291         return type_identity<PerfettoTeHlExtraDebugArgInt64>{};
292       } else if constexpr (std::is_same_v<DebugArgT, double>) {
293         return type_identity<PerfettoTeHlExtraDebugArgDouble>{};
294       } else if constexpr (std::is_same_v<DebugArgT, const char*>) {
295         return type_identity<PerfettoTeHlExtraDebugArgString>{};
296       } else {
297         return type_identity<void>{};
298       }
299     }
300     using type = typename decltype(get_debug_arg_type<T>())::type;
301 
302     static constexpr int enum_value = []() {
303       if constexpr (std::is_same_v<T, bool>) {
304         return PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_BOOL;
305       } else if constexpr (std::is_same_v<T, int64_t>) {
306         return PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_INT64;
307       } else if constexpr (std::is_same_v<T, double>) {
308         return PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_DOUBLE;
309       } else if constexpr (std::is_same_v<T, const char*>) {
310         return PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_STRING;
311       } else {
312         static_assert(always_false<T>::value, "Unsupported type");
313         return 0;  // Never reached, just to satisfy return type
314       }
315     }();
316   };
317 
DebugArg(const std::string & name)318   DebugArg(const std::string& name) : name_(name) {
319     static_assert(!std::is_same_v<typename TypeMap::type, void>,
320                   "Unsupported type for DebugArg");
321 
322     typename TypeMap::type arg;
323     arg.header = {TypeMap::enum_value};
324     arg.name = name_.c_str();
325     arg_ = std::move(arg);
326   }
327 
set_value(T value)328   void set_value(T value) {
329     if constexpr (std::is_same_v<T, const char*>) {
330       arg_.value = value;
331     } else if constexpr (std::is_same_v<T, int64_t>) {
332       arg_.value = value;
333     } else if constexpr (std::is_same_v<T, bool>) {
334       arg_.value = value;
335     } else if constexpr (std::is_same_v<T, double>) {
336       arg_.value = value;
337     }
338   }
339 
delete_arg(DebugArg * arg)340   static void delete_arg(DebugArg* arg) { delete arg; }
341 
get()342   const typename TypeMap::type* get() const { return &arg_; }
343 
344  private:
345   DISALLOW_COPY_AND_ASSIGN(DebugArg);
346   typename TypeMap::type arg_;
347   const std::string name_;
348 };
349 
350 template <typename T>
351 class ProtoField {
352  public:
353   template <typename>
354   struct always_false : std::false_type {};
355 
356   template <class I>
357   struct type_identity {
358     using type = I;
359   };
360 
361   struct TypeMap {
362     template <typename ProtoT>
get_proto_typeTypeMap363     static constexpr auto get_proto_type() {
364       if constexpr (std::is_same_v<ProtoT, int64_t>) {
365         return type_identity<PerfettoTeHlProtoFieldVarInt>{};
366       } else if constexpr (std::is_same_v<ProtoT, double>) {
367         return type_identity<PerfettoTeHlProtoFieldDouble>{};
368       } else if constexpr (std::is_same_v<ProtoT, const char*>) {
369         return type_identity<PerfettoTeHlProtoFieldCstr>{};
370       } else {
371         return type_identity<void>{};
372       }
373     }
374     using type = typename decltype(get_proto_type<T>())::type;
375 
376     static constexpr PerfettoTeHlProtoFieldType enum_value = []() {
377       if constexpr (std::is_same_v<T, int64_t>) {
378         return PERFETTO_TE_HL_PROTO_TYPE_VARINT;
379       } else if constexpr (std::is_same_v<T, double>) {
380         return PERFETTO_TE_HL_PROTO_TYPE_DOUBLE;
381       } else if constexpr (std::is_same_v<T, const char*>) {
382         return PERFETTO_TE_HL_PROTO_TYPE_CSTR;
383       } else {
384         static_assert(always_false<T>::value, "Unsupported type");
385         return 0;  // Never reached, just to satisfy return type
386       }
387     }();
388   };
389 
ProtoField()390   ProtoField() {
391     static_assert(!std::is_same_v<typename TypeMap::type, void>,
392                   "Unsupported type for ProtoField");
393 
394     typename TypeMap::type arg;
395     arg.header.type = TypeMap::enum_value;
396     arg_ = std::move(arg);
397   }
398 
set_value(uint32_t id,T value)399   void set_value(uint32_t id, T value) {
400     if constexpr (std::is_same_v<T, int64_t>) {
401       arg_.header.id = id;
402       arg_.value = value;
403     } else if constexpr (std::is_same_v<T, double>) {
404       arg_.header.id = id;
405       arg_.value = value;
406     } else if constexpr (std::is_same_v<T, const char*>) {
407       arg_.header.id = id;
408       arg_.str = value;
409     }
410   }
411 
delete_field(ProtoField * field)412   static void delete_field(ProtoField* field) { delete field; }
413 
get()414   const typename TypeMap::type* get() const { return &arg_; }
415 
416  private:
417   DISALLOW_COPY_AND_ASSIGN(ProtoField);
418   typename TypeMap::type arg_;
419 };
420 
421 class ProtoFieldNested {
422  public:
423   ProtoFieldNested();
424 
425   void add_field(PerfettoTeHlProtoField* field);
426   void set_id(uint32_t id);
427   static void delete_field(ProtoFieldNested* field);
428 
429   const PerfettoTeHlProtoFieldNested* get() const;
430 
431  private:
432   DISALLOW_COPY_AND_ASSIGN(ProtoFieldNested);
433   PerfettoTeHlProtoFieldNested field_;
434   // These PerfettoTeHlProtoField pointers are really pointers to all the other
435   // types of protos: PerfettoTeHlProtoFieldVarInt,
436   // PerfettoTeHlProtoFieldVarInt, PerfettoTeHlProtoFieldVarInt,
437   // PerfettoTeHlProtoFieldNested. Those objects are individually managed by
438   // Java.
439   std::vector<PerfettoTeHlProtoField*> fields_;
440 };
441 
442 class Proto {
443  public:
444   Proto();
445 
446   void add_field(PerfettoTeHlProtoField* field);
447   void clear_fields();
448   static void delete_proto(Proto* proto);
449 
450   const PerfettoTeHlExtraProtoFields* get() const;
451 
452  private:
453   DISALLOW_COPY_AND_ASSIGN(Proto);
454   PerfettoTeHlExtraProtoFields proto_;
455   // These PerfettoTeHlProtoField pointers are really pointers to all the other
456   // types of protos: PerfettoTeHlProtoFieldVarInt,
457   // PerfettoTeHlProtoFieldVarInt, PerfettoTeHlProtoFieldVarInt,
458   // PerfettoTeHlProtoFieldNested. Those objects are individually managed by
459   // Java.
460   std::vector<PerfettoTeHlProtoField*> fields_;
461 };
462 
463 class Session {
464  public:
465   Session(bool is_backend_in_process, void* buf, size_t len);
466   ~Session();
467   Session(const Session&) = delete;
468   Session& operator=(const Session&) = delete;
469 
470   bool FlushBlocking(uint32_t timeout_ms);
471   void StopBlocking();
472   std::vector<uint8_t> ReadBlocking();
473 
474   static void delete_session(Session* session);
475 
476   struct PerfettoTracingSessionImpl* session_ = nullptr;
477 };
478 
479 /**
480  * @brief Activates a trigger.
481  * @param name The name of the trigger.
482  * @param ttl_ms The time-to-live of the trigger in milliseconds.
483  */
484 void activate_trigger(const char* name, uint32_t ttl_ms);
485 }  // namespace sdk_for_jni
486 }  // namespace perfetto
487 
488 #endif  // SRC_ANDROID_SDK_PERFETTO_SDK_FOR_JNI_TRACING_SDK_H_
489