Merge "trace_processor: show cpu_frequency_limits ftrace event on Perfetto UI"
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index 9d5e382..1008761 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -676,6 +676,10 @@
         ParseNapiGroReceiveExit(cpu, ts, data);
         break;
       }
+      case FtraceEvent::kCpuFrequencyLimitsFieldNumber: {
+        ParseCpuFrequencyLimits(ts, data);
+        break;
+      }
       default:
         break;
     }
@@ -1853,5 +1857,28 @@
                                args_inserter);
 }
 
+void FtraceParser::ParseCpuFrequencyLimits(int64_t timestamp,
+                                           protozero::ConstBytes blob) {
+  protos::pbzero::CpuFrequencyLimitsFtraceEvent::Decoder evt(blob.data,
+                                                             blob.size);
+  base::StackString<255> max_counter_name("Cpu %" PRIu32 " Max Freq Limit",
+                                          evt.cpu_id());
+  base::StackString<255> min_counter_name("Cpu %" PRIu32 " Min Freq Limit",
+                                          evt.cpu_id());
+  // Push max freq to global counter.
+  StringId max_name = context_->storage->InternString(max_counter_name.c_str());
+  TrackId max_track =
+      context_->track_tracker->InternGlobalCounterTrack(max_name);
+  context_->event_tracker->PushCounter(
+      timestamp, static_cast<double>(evt.max_freq()), max_track);
+
+  // Push min freq to global counter.
+  StringId min_name = context_->storage->InternString(min_counter_name.c_str());
+  TrackId min_track =
+      context_->track_tracker->InternGlobalCounterTrack(min_name);
+  context_->event_tracker->PushCounter(
+      timestamp, static_cast<double>(evt.min_freq()), min_track);
+}
+
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.h b/src/trace_processor/importers/ftrace/ftrace_parser.h
index cb040de..934bb07 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.h
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.h
@@ -167,6 +167,7 @@
   void ParseNapiGroReceiveExit(uint32_t cpu,
                                int64_t timestamp,
                                protozero::ConstBytes);
+  void ParseCpuFrequencyLimits(int64_t timestamp, protozero::ConstBytes);
 
   TraceProcessorContext* context_;
   RssStatTracker rss_stat_tracker_;
diff --git a/test/trace_processor/performance/cpu_frequency_limits.out b/test/trace_processor/performance/cpu_frequency_limits.out
new file mode 100644
index 0000000..1c4348f
--- /dev/null
+++ b/test/trace_processor/performance/cpu_frequency_limits.out
@@ -0,0 +1,13 @@
+"ts","value","cpu"
+90000000,2800000.000000,"Cpu 6 Max"
+90000000,500000.000000,"Cpu 6 Min"
+100000000,1700000.000000,"Cpu 6 Max"
+100000000,500000.000000,"Cpu 6 Min"
+110000000,2800000.000000,"Cpu 6 Max"
+110000000,1400000.000000,"Cpu 6 Min"
+120000000,1500000.000000,"Cpu 6 Max"
+120000000,500000.000000,"Cpu 6 Min"
+120000000,1400000.000000,"Cpu 4 Max"
+120000000,600000.000000,"Cpu 4 Min"
+130000000,2200000.000000,"Cpu 4 Max"
+130000000,800000.000000,"Cpu 4 Min"
diff --git a/test/trace_processor/performance/cpu_frequency_limits.sql b/test/trace_processor/performance/cpu_frequency_limits.sql
new file mode 100644
index 0000000..06e1852
--- /dev/null
+++ b/test/trace_processor/performance/cpu_frequency_limits.sql
@@ -0,0 +1,12 @@
+SELECT
+  ts,
+  value, 
+  REPLACE(name, " Freq Limit", "") AS cpu
+FROM
+  counter AS c
+  LEFT JOIN
+  counter_track AS t
+  ON c.track_id = t.id
+WHERE
+  name GLOB "* Freq Limit"
+ORDER BY ts;
diff --git a/test/trace_processor/performance/cpu_frequency_limits.textproto b/test/trace_processor/performance/cpu_frequency_limits.textproto
new file mode 100644
index 0000000..2ad9ac0
--- /dev/null
+++ b/test/trace_processor/performance/cpu_frequency_limits.textproto
@@ -0,0 +1,84 @@
+packet {
+  ftrace_events {
+    cpu: 0
+    event {
+      timestamp: 90000000
+      pid: 200
+      cpu_frequency_limits {
+        max_freq: 2800000
+        min_freq: 500000
+        cpu_id: 6
+      }
+    }
+  }
+}
+packet {
+  ftrace_events {
+    cpu: 0
+    event {
+      timestamp: 100000000
+      pid: 500
+      cpu_frequency_limits {
+        max_freq: 1700000
+        min_freq: 500000
+        cpu_id: 6
+      }
+    }
+  }
+}
+packet {
+  ftrace_events {
+    cpu: 0
+    event {
+      timestamp: 110000000
+      pid: 80
+      cpu_frequency_limits {
+        max_freq: 2800000
+        min_freq: 1400000
+        cpu_id: 6
+      }
+    }
+  }
+}
+packet {
+  ftrace_events {
+    cpu: 0
+    event {
+      timestamp: 120000000
+      pid: 300
+      cpu_frequency_limits {
+        max_freq: 1500000
+        min_freq: 500000
+        cpu_id: 6
+      }
+    }
+  }
+}
+packet {
+  ftrace_events {
+    cpu: 4
+    event {
+      timestamp: 120000000
+      pid: 300
+      cpu_frequency_limits {
+        max_freq: 1400000
+        min_freq: 600000
+        cpu_id: 4
+      }
+    }
+  }
+}
+packet {
+  ftrace_events {
+    cpu: 4
+    event {
+      timestamp: 130000000
+      pid: 600
+      cpu_frequency_limits {
+        max_freq: 2200000
+        min_freq: 800000
+        cpu_id: 4
+      }
+    }
+  }
+}
diff --git a/test/trace_processor/performance/index b/test/trace_processor/performance/index
index 9687108..484f717 100644
--- a/test/trace_processor/performance/index
+++ b/test/trace_processor/performance/index
@@ -1,2 +1,4 @@
 # IRQ max runtime and count over 1ms
 irq_runtime_metric.textproto android_irq_runtime irq_runtime_metric.out
+# CPU frequency maximum & minimum limits change
+cpu_frequency_limits.textproto cpu_frequency_limits.sql cpu_frequency_limits.out