metrics: Add frequency residency metric

Frequency Residency is a useful normalized metric to find
the predominantly frequency and frequency distribution for
devices with dynamic voltage and frequency scaling. This
patch extracts metadata from the clock_set_rate ftrace
events to generate frequency residency metrics.

Bug: 205778323
Test: <trace_processor_shell> --run-metrics android_dvfs \
      <perfetto_trace>
Test: tools/diff_test_trace_processor.py <trace_processor_shell> \
      --trace-filter='dvfs_metric'
Change-Id: Icc6465e23b748b95f774068b9545339fdf2aab9f
Signed-off-by: Luke Chang <lukechang@google.com>
diff --git a/Android.bp b/Android.bp
index f3f47ef..1b10e3d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3655,6 +3655,7 @@
         "protos/perfetto/metrics/android/cpu_metric.proto",
         "protos/perfetto/metrics/android/display_metrics.proto",
         "protos/perfetto/metrics/android/dma_heap_metric.proto",
+        "protos/perfetto/metrics/android/dvfs_metric.proto",
         "protos/perfetto/metrics/android/fastrpc_metric.proto",
         "protos/perfetto/metrics/android/g2d_metric.proto",
         "protos/perfetto/metrics/android/gpu_metric.proto",
@@ -3711,6 +3712,7 @@
         "protos/perfetto/metrics/android/cpu_metric.proto",
         "protos/perfetto/metrics/android/display_metrics.proto",
         "protos/perfetto/metrics/android/dma_heap_metric.proto",
+        "protos/perfetto/metrics/android/dvfs_metric.proto",
         "protos/perfetto/metrics/android/fastrpc_metric.proto",
         "protos/perfetto/metrics/android/g2d_metric.proto",
         "protos/perfetto/metrics/android/gpu_metric.proto",
@@ -8007,6 +8009,7 @@
         "src/trace_processor/metrics/sql/android/android_cpu_agg.sql",
         "src/trace_processor/metrics/sql/android/android_cpu_raw_metrics_per_core.sql",
         "src/trace_processor/metrics/sql/android/android_dma_heap.sql",
+        "src/trace_processor/metrics/sql/android/android_dvfs.sql",
         "src/trace_processor/metrics/sql/android/android_fastrpc.sql",
         "src/trace_processor/metrics/sql/android/android_gpu.sql",
         "src/trace_processor/metrics/sql/android/android_hwcomposer.sql",
diff --git a/BUILD b/BUILD
index 10d6905..c818210 100644
--- a/BUILD
+++ b/BUILD
@@ -1009,6 +1009,7 @@
         "src/trace_processor/metrics/sql/android/android_cpu_agg.sql",
         "src/trace_processor/metrics/sql/android/android_cpu_raw_metrics_per_core.sql",
         "src/trace_processor/metrics/sql/android/android_dma_heap.sql",
+        "src/trace_processor/metrics/sql/android/android_dvfs.sql",
         "src/trace_processor/metrics/sql/android/android_fastrpc.sql",
         "src/trace_processor/metrics/sql/android/android_gpu.sql",
         "src/trace_processor/metrics/sql/android/android_hwcomposer.sql",
@@ -2562,6 +2563,7 @@
         "protos/perfetto/metrics/android/cpu_metric.proto",
         "protos/perfetto/metrics/android/display_metrics.proto",
         "protos/perfetto/metrics/android/dma_heap_metric.proto",
+        "protos/perfetto/metrics/android/dvfs_metric.proto",
         "protos/perfetto/metrics/android/fastrpc_metric.proto",
         "protos/perfetto/metrics/android/g2d_metric.proto",
         "protos/perfetto/metrics/android/gpu_metric.proto",
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index 9b0c5c0..c217438 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -25,6 +25,7 @@
     "cpu_metric.proto",
     "display_metrics.proto",
     "dma_heap_metric.proto",
+    "dvfs_metric.proto",
     "fastrpc_metric.proto",
     "g2d_metric.proto",
     "gpu_metric.proto",
diff --git a/protos/perfetto/metrics/android/dvfs_metric.proto b/protos/perfetto/metrics/android/dvfs_metric.proto
new file mode 100644
index 0000000..e7bb625
--- /dev/null
+++ b/protos/perfetto/metrics/android/dvfs_metric.proto
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package perfetto.protos;
+
+message AndroidDvfsMetric {
+
+  message BandStat {
+    // Operating frequency
+    optional int32 freq_value = 1;
+
+    // Percentage of duration in this operating frequency compared to all frequencies
+    optional double percentage = 2;
+
+    // Total duration in ns when the state was in this operating frequency
+    optional int64 duration_ns = 3;
+  }
+
+  message FrequencyResidency {
+    // Frequency representative name
+    optional string freq_name = 1;
+    // Each band statistics meta
+    repeated BandStat band_stat = 2;
+  }
+
+  // Frequency residency metrics from clock_set_rate ftrace event.
+  repeated FrequencyResidency freq_residencies = 1;
+}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index 36b131b..c948145 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -23,6 +23,7 @@
 import "protos/perfetto/metrics/android/camera_metric.proto";
 import "protos/perfetto/metrics/android/display_metrics.proto";
 import "protos/perfetto/metrics/android/dma_heap_metric.proto";
+import "protos/perfetto/metrics/android/dvfs_metric.proto";
 import "protos/perfetto/metrics/android/fastrpc_metric.proto";
 import "protos/perfetto/metrics/android/g2d_metric.proto";
 import "protos/perfetto/metrics/android/gpu_metric.proto";
@@ -93,7 +94,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 39
+// Next id: 40
 message TraceMetrics {
   reserved 4, 10, 13, 14, 16, 19;
 
@@ -192,6 +193,9 @@
   // Metrics for the Camera team.
   optional AndroidCameraMetric android_camera = 38;
 
+  // Metrics for dynamic voltage and frequency scaling.
+  optional AndroidDvfsMetric android_dvfs = 39;
+
   // Demo extensions.
   extensions 450 to 499;
 
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index 7128494..6cf96ca 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -202,6 +202,34 @@
 
 // End of protos/perfetto/metrics/android/dma_heap_metric.proto
 
+// Begin of protos/perfetto/metrics/android/dvfs_metric.proto
+
+message AndroidDvfsMetric {
+
+  message BandStat {
+    // Operating frequency
+    optional int32 freq_value = 1;
+
+    // Percentage of duration in this operating frequency compared to all frequencies
+    optional double percentage = 2;
+
+    // Total duration in ns when the state was in this operating frequency
+    optional int64 duration_ns = 3;
+  }
+
+  message FrequencyResidency {
+    // Frequency representative name
+    optional string freq_name = 1;
+    // Each band statistics meta
+    repeated BandStat band_stat = 2;
+  }
+
+  // Frequency residency metrics from clock_set_rate ftrace event.
+  repeated FrequencyResidency freq_residencies = 1;
+}
+
+// End of protos/perfetto/metrics/android/dvfs_metric.proto
+
 // Begin of protos/perfetto/metrics/android/fastrpc_metric.proto
 
 // fastrpc memory stats on Android.
@@ -1239,7 +1267,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 39
+// Next id: 40
 message TraceMetrics {
   reserved 4, 10, 13, 14, 16, 19;
 
@@ -1338,6 +1366,9 @@
   // Metrics for the Camera team.
   optional AndroidCameraMetric android_camera = 38;
 
+  // Metrics for dynamic voltage and frequency scaling.
+  optional AndroidDvfsMetric android_dvfs = 39;
+
   // Demo extensions.
   extensions 450 to 499;
 
diff --git a/src/trace_processor/metrics/sql/BUILD.gn b/src/trace_processor/metrics/sql/BUILD.gn
index 2759d24..064630b 100644
--- a/src/trace_processor/metrics/sql/BUILD.gn
+++ b/src/trace_processor/metrics/sql/BUILD.gn
@@ -24,6 +24,7 @@
   "android/android_cpu_agg.sql",
   "android/android_cpu_raw_metrics_per_core.sql",
   "android/android_dma_heap.sql",
+  "android/android_dvfs.sql",
   "android/android_fastrpc.sql",
   "android/android_gpu.sql",
   "android/android_hwui_threads.sql",
diff --git a/src/trace_processor/metrics/sql/android/android_dvfs.sql b/src/trace_processor/metrics/sql/android/android_dvfs.sql
new file mode 100644
index 0000000..a5872df
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/android_dvfs.sql
@@ -0,0 +1,92 @@
+--
+-- Copyright 2021 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+DROP VIEW IF EXISTS freq_slice;
+
+CREATE VIEW freq_slice AS
+  SELECT
+    counter.track_id AS track_id,
+    track.name AS freq_name,
+    ts,
+    value AS freq_value,
+    LEAD(ts, 1, (SELECT end_ts+1 FROM trace_bounds))
+      OVER (PARTITION by track.id ORDER BY ts)  - ts AS duration
+  FROM counter
+  LEFT JOIN track ON counter.track_id = track.id
+  WHERE track.name LIKE "% Frequency"
+  ORDER BY ts;
+
+DROP VIEW IF EXISTS freq_total_duration;
+
+CREATE VIEW freq_total_duration AS
+  SELECT
+    track_id,
+    freq_name,
+    SUM(duration) AS total_duration
+  FROM freq_slice
+  WHERE duration > 0
+  GROUP BY track_id, freq_name;
+
+DROP VIEW IF EXISTS dvfs_per_band_view;
+
+CREATE VIEW dvfs_per_band_view AS
+WITH
+freq_duration AS (
+  SELECT
+    track_id,
+    freq_name,
+    CAST(freq_value AS int) AS freq_value,
+    SUM(duration) AS duration_ns
+  FROM freq_slice
+  WHERE duration > 0
+  GROUP BY track_id, freq_name, freq_value
+)
+SELECT
+  freq_duration.track_id,
+  freq_duration.freq_name,
+  AndroidDvfsMetric_BandStat(
+     'freq_value', freq_value,
+     'percentage', duration_ns / (total_duration / 1e2),
+     'duration_ns', duration_ns
+  ) AS proto
+FROM freq_duration
+LEFT JOIN freq_total_duration
+USING(track_id)
+ORDER BY freq_duration.freq_name, freq_duration.freq_value;
+
+DROP VIEW IF EXISTS dvfs_per_freq_view;
+CREATE VIEW dvfs_per_freq_view AS
+  SELECT
+    AndroidDvfsMetric_FrequencyResidency(
+      'freq_name', freq_total_duration.freq_name,
+      'band_stat', (
+        SELECT
+          RepeatedField(proto)
+        FROM dvfs_per_band_view
+        WHERE dvfs_per_band_view.track_id = freq_total_duration.track_id
+      )
+    ) AS proto
+  FROM freq_total_duration
+  GROUP BY track_id, freq_name
+  ORDER BY freq_name;
+
+CREATE VIEW android_dvfs_output AS
+  SELECT AndroidDVFSMetric(
+    'freq_residencies', (
+      SELECT
+        RepeatedField(proto)
+      FROM dvfs_per_freq_view
+    )
+  );
diff --git a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
index c94c320..0eb8e34 100644
--- a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
+++ b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
Binary files differ
diff --git a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1 b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1
index b00e60a..5d91f78 100644
--- a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1
+++ b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1
@@ -2,5 +2,5 @@
 // SHA1(tools/gen_binary_descriptors)
 // 9fc6d77de57ec76a80b76aa282f4c7cf5ce55eec
 // SHA1(protos/perfetto/metrics/metrics.proto)
-// 8130cb1a62e55e42bb97a682ca0503161460b4ee
+// fe8af2b2dce211830488daf2357aea79b4b2a539
   
\ No newline at end of file
diff --git a/test/trace_processor/power/dvfs_metric.out b/test/trace_processor/power/dvfs_metric.out
new file mode 100644
index 0000000..4b38bd2
--- /dev/null
+++ b/test/trace_processor/power/dvfs_metric.out
@@ -0,0 +1,33 @@
+android_dvfs {
+  freq_residencies {
+    freq_name: "bus_throughput Frequency"
+    band_stat: {
+      freq_value: 1014000
+      percentage: 75.0
+      duration_ns: 3000000
+    }
+    band_stat: {
+      freq_value: 2028000
+      percentage: 25.0
+      duration_ns: 1000000
+    }
+  }
+  freq_residencies {
+    freq_name: "domain@1 Frequency"
+    band_stat: {
+      freq_value: 400000
+      percentage: 40.0
+      duration_ns: 2000000
+    }
+    band_stat: {
+      freq_value: 553000
+      percentage: 40.0
+      duration_ns: 2000000
+    }
+    band_stat: {
+      freq_value: 1024000
+      percentage: 20.0
+      duration_ns: 1000000
+    }
+  }
+}
diff --git a/test/trace_processor/power/dvfs_metric.textproto b/test/trace_processor/power/dvfs_metric.textproto
new file mode 100644
index 0000000..8301519
--- /dev/null
+++ b/test/trace_processor/power/dvfs_metric.textproto
@@ -0,0 +1,55 @@
+packet {
+  ftrace_events {
+    cpu: 0
+    event {
+      timestamp: 200001000000
+      pid: 2
+      clock_set_rate {
+        name : "domain@1"
+        state: 400000
+      }
+    }
+    event {
+      timestamp: 200002000000
+      pid: 2
+      clock_set_rate {
+        name : "bus_throughput"
+        state: 1014000
+      }
+    }
+    event {
+      timestamp: 200003000000
+      pid: 2
+      clock_set_rate {
+        name: "domain@1"
+        state: 1024000
+      }
+    }
+    event {
+      timestamp: 200004000000
+      pid: 2
+      clock_set_rate {
+        name: "domain@1"
+        state: 553000
+      }
+    }
+    event {
+      timestamp: 200005000000
+      pid: 2
+      clock_set_rate {
+        name: "bus_throughput"
+        state: 2028000
+      }
+    }
+    event {
+      timestamp: 200005999999
+      pid: 527
+      clock_set_rate {
+        name: "domain@1"
+        state: 553000
+      }
+    }
+  }
+  trusted_uid: 9999
+  trusted_packet_sequence_id: 2
+}
diff --git a/test/trace_processor/power/index b/test/trace_processor/power/index
index 004f7a3..cb4e178 100644
--- a/test/trace_processor/power/index
+++ b/test/trace_processor/power/index
@@ -3,3 +3,7 @@
 power_rails_custom_clock.textproto power_rails_event.sql power_rails_event_power_rails_custom_clock.out
 power_rails.textproto power_rails_timestamp_sort.sql power_rails_timestamp_sort.out
 power_rails_well_known.textproto power_rails.sql power_rails_well_known_power_rails.out
+
+# Dynamic Voltage and Frequency Scaling
+
+dvfs_metric.textproto android_dvfs dvfs_metric.out