• 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 #include "src/java_sdk/main/cpp/utils.h"
18 
19 #include <functional>
20 
21 #include "perfetto/public/abi/heap_buffer.h"
22 #include "perfetto/public/abi/tracing_session_abi.h"
23 #include "perfetto/public/pb_msg.h"
24 #include "perfetto/public/protos/config/data_source_config.pzc.h"
25 #include "perfetto/public/protos/config/trace_config.pzc.h"
26 #include "perfetto/public/protos/config/track_event/track_event_config.pzc.h"
27 
28 // Implementation copied from src/shared_lib/test/utils.cc
29 
30 namespace perfetto {
31 namespace java_sdk {
32 namespace utils {
Build()33 TracingSession TracingSession::Builder::Build() {
34   struct PerfettoPbMsgWriter writer;
35   struct PerfettoHeapBuffer* hb = PerfettoHeapBufferCreate(&writer.writer);
36 
37   struct perfetto_protos_TraceConfig cfg;
38   PerfettoPbMsgInit(&cfg.msg, &writer);
39   {
40     struct perfetto_protos_TraceConfig_BufferConfig buffers;
41     perfetto_protos_TraceConfig_begin_buffers(&cfg, &buffers);
42 
43     perfetto_protos_TraceConfig_BufferConfig_set_size_kb(&buffers, 1024);
44 
45     perfetto_protos_TraceConfig_end_buffers(&cfg, &buffers);
46   }
47   {
48     struct perfetto_protos_TraceConfig_DataSource data_sources;
49     perfetto_protos_TraceConfig_begin_data_sources(&cfg, &data_sources);
50     {
51       struct perfetto_protos_DataSourceConfig ds_cfg;
52       perfetto_protos_TraceConfig_DataSource_begin_config(&data_sources,
53                                                           &ds_cfg);
54 
55       perfetto_protos_DataSourceConfig_set_cstr_name(&ds_cfg,
56                                                      data_source_name_.c_str());
57       if (!enabled_categories_.empty() || !disabled_categories_.empty()) {
58         perfetto_protos_TrackEventConfig te_cfg;
59         perfetto_protos_DataSourceConfig_begin_track_event_config(&ds_cfg,
60                                                                   &te_cfg);
61         for (const std::string& cat : enabled_categories_) {
62           perfetto_protos_TrackEventConfig_set_enabled_categories(
63               &te_cfg, cat.data(), cat.size());
64         }
65         for (const std::string& cat : disabled_categories_) {
66           perfetto_protos_TrackEventConfig_set_disabled_categories(
67               &te_cfg, cat.data(), cat.size());
68         }
69         perfetto_protos_DataSourceConfig_end_track_event_config(&ds_cfg,
70                                                                 &te_cfg);
71       }
72 
73       perfetto_protos_TraceConfig_DataSource_end_config(&data_sources, &ds_cfg);
74     }
75 
76     perfetto_protos_TraceConfig_end_data_sources(&cfg, &data_sources);
77   }
78   size_t cfg_size = PerfettoStreamWriterGetWrittenSize(&writer.writer);
79   std::unique_ptr<uint8_t[]> ser(new uint8_t[cfg_size]);
80   PerfettoHeapBufferCopyInto(hb, &writer.writer, ser.get(), cfg_size);
81   PerfettoHeapBufferDestroy(hb, &writer.writer);
82 
83   struct PerfettoTracingSessionImpl* ts =
84       PerfettoTracingSessionInProcessCreate();
85 
86   PerfettoTracingSessionSetup(ts, ser.get(), cfg_size);
87 
88   PerfettoTracingSessionStartBlocking(ts);
89 
90   return TracingSession::Adopt(ts);
91 }
92 
Adopt(struct PerfettoTracingSessionImpl * session)93 TracingSession TracingSession::Adopt(
94     struct PerfettoTracingSessionImpl* session) {
95   TracingSession ret;
96   ret.session_ = session;
97   ret.stopped_ = std::make_unique<WaitableEvent>();
98   PerfettoTracingSessionSetStopCb(
99       ret.session_,
100       [](struct PerfettoTracingSessionImpl*, void* arg) {
101         static_cast<WaitableEvent*>(arg)->Notify();
102       },
103       ret.stopped_.get());
104   return ret;
105 }
106 
TracingSession(TracingSession && other)107 TracingSession::TracingSession(TracingSession&& other) noexcept {
108   session_ = other.session_;
109   other.session_ = nullptr;
110   stopped_ = std::move(other.stopped_);
111   other.stopped_ = nullptr;
112 }
113 
~TracingSession()114 TracingSession::~TracingSession() {
115   if (!session_) {
116     return;
117   }
118   if (!stopped_->IsNotified()) {
119     PerfettoTracingSessionStopBlocking(session_);
120     stopped_->WaitForNotification();
121   }
122   PerfettoTracingSessionDestroy(session_);
123 }
124 
FlushBlocking(uint32_t timeout_ms)125 bool TracingSession::FlushBlocking(uint32_t timeout_ms) {
126   WaitableEvent notification;
127   bool result;
128   auto* cb = new std::function<void(bool)>([&](bool success) {
129     result = success;
130     notification.Notify();
131   });
132   PerfettoTracingSessionFlushAsync(
133       session_, timeout_ms,
134       [](PerfettoTracingSessionImpl*, bool success, void* user_arg) {
135         auto* f = reinterpret_cast<std::function<void(bool)>*>(user_arg);
136         (*f)(success);
137         delete f;
138       },
139       cb);
140   notification.WaitForNotification();
141   return result;
142 }
143 
WaitForStopped()144 void TracingSession::WaitForStopped() {
145   stopped_->WaitForNotification();
146 }
147 
StopAsync()148 void TracingSession::StopAsync() {
149   PerfettoTracingSessionStopAsync(session_);
150 }
151 
StopBlocking()152 void TracingSession::StopBlocking() {
153   PerfettoTracingSessionStopBlocking(session_);
154 }
155 
ReadBlocking()156 std::vector<uint8_t> TracingSession::ReadBlocking() {
157   std::vector<uint8_t> data;
158   PerfettoTracingSessionReadTraceBlocking(
159       session_,
160       [](struct PerfettoTracingSessionImpl*, const void* trace_data,
161          size_t size, bool, void* user_arg) {
162         auto& dst = *static_cast<std::vector<uint8_t>*>(user_arg);
163         auto* src = static_cast<const uint8_t*>(trace_data);
164         dst.insert(dst.end(), src, src + size);
165       },
166       &data);
167   return data;
168 }
169 }  // namespace utils
170 }  // namespace java_sdk
171 }  // namespace perfetto
172