5151#include " protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
5252#include " protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
5353#include " protos/perfetto/trace/ftrace/fwtp_ftrace.pbzero.h"
54+ #include " protos/perfetto/trace/ftrace/kgsl.pbzero.h"
5455#include " protos/perfetto/trace/ftrace/power.pbzero.h"
5556#include " protos/perfetto/trace/ftrace/thermal_exynos.pbzero.h"
5657#include " src/trace_processor/util/clock_synchronizer.h"
@@ -68,6 +69,7 @@ using protos::pbzero::FtraceEventBundle;
6869namespace {
6970
7071constexpr uint32_t kSequenceScopedClockId = 64 ;
72+ constexpr uint32_t kAdrenoGpuClockId = 65 ;
7173
7274// Fast path for parsing the event id of an ftrace event.
7375// Speculate on the fact that, if the timestamp was found, the common pid
@@ -154,7 +156,7 @@ base::Status FtraceTokenizer::TokenizeFtraceBundle(
154156
155157 for (auto it = decoder.event (); it; ++it) {
156158 TokenizeFtraceEvent (cpu, clock_id, bundle.slice (it->data (), it->size ()),
157- state);
159+ state, packet_sequence_id );
158160 }
159161
160162 // v50+: optional proto descriptors for generic (i.e. not known at
@@ -214,7 +216,8 @@ void FtraceTokenizer::TokenizeFtraceEvent(
214216 uint32_t cpu,
215217 ClockTracker::ClockId clock_id,
216218 TraceBlobView event,
217- RefPtr<PacketSequenceStateGeneration> state) {
219+ RefPtr<PacketSequenceStateGeneration> state,
220+ uint32_t packet_sequence_id) {
218221 constexpr auto kTimestampFieldNumber =
219222 protos::pbzero::FtraceEvent::kTimestampFieldNumber ;
220223 constexpr auto kTimestampFieldTag = MakeTagVarInt (kTimestampFieldNumber );
@@ -301,6 +304,60 @@ void FtraceTokenizer::TokenizeFtraceEvent(
301304 return ;
302305 }
303306
307+ // The submitted event provides a CPU <-> GPU clock sync point; we register
308+ // it as a sequence-scoped clock so the clock tracker can convert GPU tick
309+ // timestamps to trace time, skipping duplicates since the GPU clock runs at
310+ // a fixed frequency and a single snapshot is sufficient.
311+ // Adreno GPU ticks run at 19.2 MHz (KGSL_XO_CLK_FREQ in kgsl_pwrctrl.h).
312+ constexpr int64_t kAdrenoGpuTicksPerUs = 19200 ;
313+ if (event_id ==
314+ protos::pbzero::FtraceEvent::kKgslAdrenoCmdbatchSubmittedFieldNumber ) {
315+ auto submitted_field = GetFtraceEventField (
316+ protos::pbzero::FtraceEvent::kKgslAdrenoCmdbatchSubmittedFieldNumber ,
317+ event);
318+ if (submitted_field.has_value ()) {
319+ protos::pbzero::KgslAdrenoCmdbatchSubmittedFtraceEvent::Decoder evt (
320+ submitted_field->as_bytes ());
321+ if (!adreno_gpu_clock_registered_) {
322+ const int64_t sync_time_ns =
323+ static_cast <int64_t >(evt.secs ()) * 1000000000LL +
324+ static_cast <int64_t >(evt.usecs ()) * 1000LL ;
325+ if (sync_time_ns > 0 ) {
326+ const int64_t gpu_ticks_ns = static_cast <int64_t >(evt.ticks ()) *
327+ 1000000 / kAdrenoGpuTicksPerUs ;
328+ auto gpu_clock =
329+ ClockId::Sequence (context_->trace_id ().value , packet_sequence_id,
330+ kAdrenoGpuClockId );
331+ context_->clock_tracker ->AddSnapshot ({
332+ ClockTracker::ClockTimestamp (gpu_clock, gpu_ticks_ns),
333+ ClockTracker::ClockTimestamp (clock_id, sync_time_ns),
334+ });
335+ adreno_gpu_clock_registered_ = true ;
336+ }
337+ }
338+ }
339+ } else if (event_id == protos::pbzero::FtraceEvent::
340+ kKgslAdrenoCmdbatchRetiredFieldNumber ) {
341+ auto retired_field = GetFtraceEventField (
342+ protos::pbzero::FtraceEvent::kKgslAdrenoCmdbatchRetiredFieldNumber ,
343+ event);
344+ if (retired_field.has_value ()) {
345+ protos::pbzero::KgslAdrenoCmdbatchRetiredFtraceEvent::Decoder evt (
346+ retired_field->as_bytes ());
347+ auto gpu_clock = ClockId::Sequence (context_->trace_id ().value ,
348+ packet_sequence_id, kAdrenoGpuClockId );
349+ const int64_t gpu_start_ns =
350+ static_cast <int64_t >(evt.start ()) * 1000000 / kAdrenoGpuTicksPerUs ;
351+ auto ts = context_->clock_tracker ->ToTraceTime (
352+ gpu_clock, gpu_start_ns, std::nullopt , /* suppress_errors=*/ true );
353+ if (ts.has_value ()) {
354+ module_context_->PushFtraceEvent (
355+ cpu, *ts, TracePacketData{std::move (event), std::move (state)});
356+ return ;
357+ }
358+ }
359+ }
360+
304361 std::optional<int64_t > timestamp = context_->clock_tracker ->ToTraceTime (
305362 clock_id, static_cast <int64_t >(raw_timestamp));
306363 // ClockTracker will increment some error stats if it failed to convert the
0 commit comments