tp: Parse devfreq and add to counter track

Adds frequency of Linux devices (i.e. devfreq) into counter tracks.

Bug: 370829192
Change-Id: I4e3c56b60f26d7c6337bb254d612faf75a15db32
Signed-off-by: Samuel Wu <wusamuel@google.com>
diff --git a/src/trace_processor/importers/common/track_tracker.h b/src/trace_processor/importers/common/track_tracker.h
index 0986929..7246304 100644
--- a/src/trace_processor/importers/common/track_tracker.h
+++ b/src/trace_processor/importers/common/track_tracker.h
@@ -131,7 +131,6 @@
     // General tracks.
     kThread,
     kProcess,
-    kLinuxDevice,
     kChromeProcessInstant,
     kAsync,
     kTrackEvent,
@@ -145,6 +144,10 @@
     // Gpu tracks.
     kGpuFrequency,
 
+    // Linux device tracks.
+    kLinuxDevice,
+    kLinuxDeviceFrequency,
+
     // Cpu tracks.
     kIrqCpu,
     kSoftirqCpu,
@@ -420,6 +423,8 @@
         return "chrome_process_instant";
       case TrackClassification::kLinuxDevice:
         return "linux_device";
+      case TrackClassification::kLinuxDeviceFrequency:
+        return "linux_device_frequency";
       case TrackClassification::kAsync:
         return "async";
       case TrackClassification::kTrackEvent:
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index 7635a0e..5c6824c 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -55,6 +55,7 @@
 #include "protos/perfetto/trace/ftrace/cpuhp.pbzero.h"
 #include "protos/perfetto/trace/ftrace/cros_ec.pbzero.h"
 #include "protos/perfetto/trace/ftrace/dcvsh.pbzero.h"
+#include "protos/perfetto/trace/ftrace/devfreq.pbzero.h"
 #include "protos/perfetto/trace/ftrace/dmabuf_heap.pbzero.h"
 #include "protos/perfetto/trace/ftrace/dpu.pbzero.h"
 #include "protos/perfetto/trace/ftrace/fastrpc.pbzero.h"
@@ -440,7 +441,8 @@
       suspend_resume_callback_phase_arg_name_(
           context->storage->InternString("callback_phase")),
       suspend_resume_event_type_arg_name_(
-          context->storage->InternString("event_type")) {
+          context->storage->InternString("event_type")),
+      device_name_id_(context->storage->InternString("device_name")) {
   // Build the lookup table for the strings inside ftrace events (e.g. the
   // name of ftrace event fields and the names of their args).
   for (size_t i = 0; i < GetDescriptorsSize(); i++) {
@@ -1221,6 +1223,10 @@
         ParseTrustyEnqueueNop(pid, ts, fld_bytes);
         break;
       }
+      case FtraceEvent::kDevfreqFrequencyFieldNumber: {
+        ParseDeviceFrequency(ts, fld_bytes);
+        break;
+      }
       case FtraceEvent::kMaliMaliKCPUCQSSETFieldNumber:
       case FtraceEvent::kMaliMaliKCPUCQSWAITSTARTFieldNumber:
       case FtraceEvent::kMaliMaliKCPUCQSWAITENDFieldNumber:
@@ -3692,4 +3698,32 @@
   return name_id;
 }
 
+void FtraceParser::ParseDeviceFrequency(int64_t ts,
+                                        protozero::ConstBytes blob) {
+  protos::pbzero::DevfreqFrequencyFtraceEvent::Decoder event(blob);
+  constexpr char delimiter[] = "devfreq_";
+  std::string dev_name = event.dev_name().ToStdString();
+  auto position = dev_name.find(delimiter);
+
+  if (position != std::string::npos) {
+    // Get device name by getting substring after delimiter and keep existing
+    // naming convention (e.g. cpufreq, gpufreq) consistent by adding a suffix
+    // to the devfreq name (e.g. dsufreq, bcifreq)
+    StringId device_name = context_->storage->InternString(
+        (dev_name.substr(position + sizeof(delimiter) - 1) + "freq").c_str());
+
+    TrackTracker::DimensionsBuilder dims_builder =
+        context_->track_tracker->CreateDimensionsBuilder();
+    dims_builder.AppendDimension(device_name_id_,
+                                 Variadic::String(device_name));
+    TrackTracker::Dimensions dims_id = std::move(dims_builder).Build();
+
+    TrackId track_id = context_->track_tracker->InternCounterTrack(
+        TrackTracker::TrackClassification::kLinuxDeviceFrequency, dims_id,
+        device_name);
+    context_->event_tracker->PushCounter(ts, static_cast<double>(event.freq()),
+                                         track_id);
+  }
+}
+
 }  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.h b/src/trace_processor/importers/ftrace/ftrace_parser.h
index 9469d24..d128a29 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.h
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.h
@@ -312,6 +312,7 @@
                               protozero::ConstBytes);
   void ParseGoogleIccEvent(int64_t timestamp, protozero::ConstBytes);
   void ParseGoogleIrmEvent(int64_t timestamp, protozero::ConstBytes);
+  void ParseDeviceFrequency(int64_t ts, protozero::ConstBytes blob);
 
   TraceProcessorContext* context_;
   RssStatTracker rss_stat_tracker_;
@@ -423,6 +424,7 @@
   const StringId suspend_resume_driver_arg_name_;
   const StringId suspend_resume_callback_phase_arg_name_;
   const StringId suspend_resume_event_type_arg_name_;
+  const StringId device_name_id_;
 
   std::vector<StringId> syscall_arg_name_ids_;