metrics: add g2d metrics

Add metrics to calculate g2d hw and sw execution time.

Bug: 178088675
Test: tools/diff_test_trace_processor.py <trace_processor_shell> \
      --trace-filter='g2d_metrics'
Test: <trace_processor_shell> --run-metrics g2d \
      <perfetto trace>
Change-Id: I0ae1f2d723d7342b1148b1362991340f385b76bd
diff --git a/Android.bp b/Android.bp
index 9c7df36..24dfc02 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3604,6 +3604,7 @@
     "protos/perfetto/metrics/android/batt_metric.proto",
     "protos/perfetto/metrics/android/cpu_metric.proto",
     "protos/perfetto/metrics/android/display_metrics.proto",
+    "protos/perfetto/metrics/android/g2d_metric.proto",
     "protos/perfetto/metrics/android/gpu_metric.proto",
     "protos/perfetto/metrics/android/heap_profile_callsites.proto",
     "protos/perfetto/metrics/android/hwcomposer.proto",
@@ -3648,6 +3649,7 @@
     "protos/perfetto/metrics/android/batt_metric.proto",
     "protos/perfetto/metrics/android/cpu_metric.proto",
     "protos/perfetto/metrics/android/display_metrics.proto",
+    "protos/perfetto/metrics/android/g2d_metric.proto",
     "protos/perfetto/metrics/android/gpu_metric.proto",
     "protos/perfetto/metrics/android/heap_profile_callsites.proto",
     "protos/perfetto/metrics/android/hwcomposer.proto",
@@ -7607,6 +7609,8 @@
     "src/trace_processor/metrics/android/cpu_info.sql",
     "src/trace_processor/metrics/android/display_metrics.sql",
     "src/trace_processor/metrics/android/frame_missed.sql",
+    "src/trace_processor/metrics/android/g2d.sql",
+    "src/trace_processor/metrics/android/g2d_duration.sql",
     "src/trace_processor/metrics/android/global_counter_span_view.sql",
     "src/trace_processor/metrics/android/heap_profile_callsites.sql",
     "src/trace_processor/metrics/android/hsc_startups.sql",
diff --git a/BUILD b/BUILD
index 35e71df..b1cf949 100644
--- a/BUILD
+++ b/BUILD
@@ -913,6 +913,8 @@
         "src/trace_processor/metrics/android/cpu_info.sql",
         "src/trace_processor/metrics/android/display_metrics.sql",
         "src/trace_processor/metrics/android/frame_missed.sql",
+        "src/trace_processor/metrics/android/g2d.sql",
+        "src/trace_processor/metrics/android/g2d_duration.sql",
         "src/trace_processor/metrics/android/global_counter_span_view.sql",
         "src/trace_processor/metrics/android/heap_profile_callsites.sql",
         "src/trace_processor/metrics/android/hsc_startups.sql",
@@ -2302,6 +2304,7 @@
         "protos/perfetto/metrics/android/batt_metric.proto",
         "protos/perfetto/metrics/android/cpu_metric.proto",
         "protos/perfetto/metrics/android/display_metrics.proto",
+        "protos/perfetto/metrics/android/g2d_metric.proto",
         "protos/perfetto/metrics/android/gpu_metric.proto",
         "protos/perfetto/metrics/android/heap_profile_callsites.proto",
         "protos/perfetto/metrics/android/hwcomposer.proto",
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index ce5a28a..14ed487 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -23,6 +23,7 @@
     "batt_metric.proto",
     "cpu_metric.proto",
     "display_metrics.proto",
+    "g2d_metric.proto",
     "gpu_metric.proto",
     "heap_profile_callsites.proto",
     "hwcomposer.proto",
diff --git a/protos/perfetto/metrics/android/g2d_metric.proto b/protos/perfetto/metrics/android/g2d_metric.proto
new file mode 100644
index 0000000..e7a2d6a
--- /dev/null
+++ b/protos/perfetto/metrics/android/g2d_metric.proto
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 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
+ *
+ *      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 G2dMetrics {
+  message G2dInstance {
+    // G2d name.
+    optional string name = 1;
+
+    optional int64 max_dur_ns = 2;
+    optional int64 min_dur_ns = 3;
+    optional int64 avg_dur_ns = 4;
+    optional uint32 frame_count = 5;
+    optional uint32 error_count = 6;
+  }
+  message G2dMetric {
+    // G2D Metric for each G2D Instance.
+    repeated G2dInstance instances = 1;
+
+    // max/min/avg G2d frame durations for all instances.
+    optional int64 max_dur_ns = 2;
+    optional int64 min_dur_ns = 3;
+    optional int64 avg_dur_ns = 4;
+
+    // the number of frames processed by G2D
+    optional uint32 frame_count = 5;
+    // the number of error events
+    optional uint32 error_count = 6;
+  }
+
+  optional G2dMetric g2d_hw = 1;
+  optional G2dMetric g2d_sw = 2;
+}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index a1b6e19..ba6972e 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -21,6 +21,7 @@
 import "protos/perfetto/metrics/android/batt_metric.proto";
 import "protos/perfetto/metrics/android/cpu_metric.proto";
 import "protos/perfetto/metrics/android/display_metrics.proto";
+import "protos/perfetto/metrics/android/g2d_metric.proto";
 import "protos/perfetto/metrics/android/gpu_metric.proto";
 import "protos/perfetto/metrics/android/heap_profile_callsites.proto";
 import "protos/perfetto/metrics/android/hwcomposer.proto";
@@ -57,7 +58,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 29
+// Next id: 31
 message TraceMetrics {
   reserved 4, 10, 13, 14, 19;
 
@@ -132,6 +133,9 @@
   // Detects common bad patterns that might lead to jank.
   optional AndroidJankMetrics android_jank = 29;
 
+  // G2D metrics.
+  optional G2dMetrics g2d = 30;
+
   // 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 8c5f037..c6a3694 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -137,6 +137,40 @@
 
 // End of protos/perfetto/metrics/android/display_metrics.proto
 
+// Begin of protos/perfetto/metrics/android/g2d_metric.proto
+
+message G2dMetrics {
+  message G2dInstance {
+    // G2d name.
+    optional string name = 1;
+
+    optional int64 max_dur_ns = 2;
+    optional int64 min_dur_ns = 3;
+    optional int64 avg_dur_ns = 4;
+    optional uint32 frame_count = 5;
+    optional uint32 error_count = 6;
+  }
+  message G2dMetric {
+    // G2D Metric for each G2D Instance.
+    repeated G2dInstance instances = 1;
+
+    // max/min/avg G2d frame durations for all instances.
+    optional int64 max_dur_ns = 2;
+    optional int64 min_dur_ns = 3;
+    optional int64 avg_dur_ns = 4;
+
+    // the number of frames processed by G2D
+    optional uint32 frame_count = 5;
+    // the number of error events
+    optional uint32 error_count = 6;
+  }
+
+  optional G2dMetric g2d_hw = 1;
+  optional G2dMetric g2d_sw = 2;
+}
+
+// End of protos/perfetto/metrics/android/g2d_metric.proto
+
 // Begin of protos/perfetto/metrics/android/gpu_metric.proto
 
 message AndroidGpuMetric {
@@ -856,7 +890,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 29
+// Next id: 31
 message TraceMetrics {
   reserved 4, 10, 13, 14, 19;
 
@@ -931,6 +965,9 @@
   // Detects common bad patterns that might lead to jank.
   optional AndroidJankMetrics android_jank = 29;
 
+  // G2D metrics.
+  optional G2dMetrics g2d = 30;
+
   // Demo extensions.
   extensions 450 to 499;
 
diff --git a/src/trace_processor/metrics/BUILD.gn b/src/trace_processor/metrics/BUILD.gn
index fcd4244..d4d68dc 100644
--- a/src/trace_processor/metrics/BUILD.gn
+++ b/src/trace_processor/metrics/BUILD.gn
@@ -42,6 +42,8 @@
   "android/android_thread_time_in_state.sql",
   "android/cpu_info.sql",
   "android/display_metrics.sql",
+  "android/g2d.sql",
+  "android/g2d_duration.sql",
   "android/heap_profile_callsites.sql",
   "android/hsc_startups.sql",
   "android/android_hwcomposer.sql",
diff --git a/src/trace_processor/metrics/android/g2d.sql b/src/trace_processor/metrics/android/g2d.sql
new file mode 100644
index 0000000..5e474b7
--- /dev/null
+++ b/src/trace_processor/metrics/android/g2d.sql
@@ -0,0 +1,34 @@
+--
+-- 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.
+
+
+SELECT RUN_METRIC(
+  'android/g2d_duration.sql',
+  'g2d_type', 'sw',
+  'output_table', 'g2d_sw_duration_metric'
+);
+
+SELECT RUN_METRIC(
+  'android/g2d_duration.sql',
+  'g2d_type', 'hw',
+  'output_table', 'g2d_hw_duration_metric'
+);
+
+DROP VIEW IF EXISTS g2d_output;
+CREATE VIEW g2d_output AS
+SELECT G2dMetrics(
+  'g2d_hw', (SELECT metric FROM g2d_hw_duration_metric),
+  'g2d_sw', (SELECT metric FROM g2d_sw_duration_metric)
+);
diff --git a/src/trace_processor/metrics/android/g2d_duration.sql b/src/trace_processor/metrics/android/g2d_duration.sql
new file mode 100644
index 0000000..7d96d06
--- /dev/null
+++ b/src/trace_processor/metrics/android/g2d_duration.sql
@@ -0,0 +1,68 @@
+--
+-- 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 raw_g2d_{{g2d_type}}_spans;
+CREATE VIEW raw_g2d_{{g2d_type}}_spans AS
+SELECT
+  ts,
+  t.name AS track_name,
+  LEAD(ts, 1, 0) OVER (PARTITION BY name ORDER BY ts) - ts AS dur,
+  LAG(value, 1, -1) OVER (PARTITION BY name ORDER BY ts) AS prev_g2d_value,
+  value AS g2d_value,
+  LEAD(value, 1, -1) OVER (PARTITION BY name ORDER BY ts) AS next_g2d_value
+FROM counter c JOIN thread_counter_track t ON t.id = c.track_id
+WHERE t.name LIKE 'g2d_frame_{{g2d_type}}%';
+
+
+DROP VIEW IF EXISTS g2d_{{g2d_type}}_spans;
+CREATE VIEW g2d_{{g2d_type}}_spans AS
+SELECT ts, track_name, dur
+FROM raw_g2d_{{g2d_type}}_spans
+WHERE g2d_value = 1 AND next_g2d_value = 0;
+
+
+DROP VIEW IF EXISTS g2d_{{g2d_type}}_errors;
+CREATE VIEW g2d_{{g2d_type}}_errors AS
+SELECT ts, track_name, g2d_value
+FROM raw_g2d_{{g2d_type}}_spans
+WHERE (g2d_value = 1 AND next_g2d_value = 1) OR (prev_g2d_value = 0 AND g2d_value = 0);
+
+
+DROP VIEW IF EXISTS g2d_{{g2d_type}}_instances;
+CREATE VIEW g2d_{{g2d_type}}_instances AS
+SELECT
+  G2dMetrics_G2dInstance(
+    'name', g.track_name,
+    'max_dur_ns', CAST(MAX(g.dur) AS INT64),
+    'min_dur_ns', CAST(MIN(g.dur) AS INT64),
+    'avg_dur_ns', CAST(AVG(g.dur) AS INT64),
+    'frame_count', COUNT(*),
+    'error_count', (SELECT COUNT(*) FROM g2d_{{g2d_type}}_errors e WHERE e.track_name = g.track_name)
+  ) AS instance
+FROM g2d_{{g2d_type}}_spans g GROUP BY g.track_name;
+
+
+DROP VIEW IF EXISTS {{output_table}};
+CREATE VIEW {{output_table}} AS
+SELECT
+  G2dMetrics_G2dMetric(
+    'instances', (SELECT RepeatedField(instance) FROM g2d_{{g2d_type}}_instances),
+    'max_dur_ns', CAST(MAX(dur) AS INT64),
+    'min_dur_ns', CAST(MIN(dur) AS INT64),
+    'avg_dur_ns', CAST(AVG(dur) AS INT64),
+    'frame_count', COUNT(*),
+    'error_count', (SELECT COUNT(*) FROM g2d_{{g2d_type}}_errors)
+  ) AS metric
+FROM g2d_{{g2d_type}}_spans;
diff --git a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
index 128dd8c..222cf60 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 e87349c..d8d964c 100644
--- a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1
+++ b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1
@@ -2,4 +2,4 @@
 // SHA1(tools/gen_binary_descriptors)
 // d50111afcc6af211b5bcd8a6935780af8fc96d9d
 // SHA1(protos/perfetto/metrics/metrics.proto)
-// dc5f60a304848e44572924b88f4b1493c8e99588
+// b1c108f54258a70d1dc0d4a7499ad211d2021002
diff --git a/test/trace_processor/graphics/g2d_metrics.out b/test/trace_processor/graphics/g2d_metrics.out
new file mode 100644
index 0000000..a28e4fd
--- /dev/null
+++ b/test/trace_processor/graphics/g2d_metrics.out
@@ -0,0 +1,40 @@
+g2d {
+    g2d_hw {
+        instances {
+            name: "g2d_frame_hw#10"
+            max_dur_ns: 20
+            min_dur_ns: 20
+            avg_dur_ns: 20
+            frame_count: 1
+            error_count: 0
+        }
+        max_dur_ns: 20
+        min_dur_ns: 20
+        avg_dur_ns: 20
+        frame_count: 1
+        error_count: 0
+    }
+    g2d_sw {
+        instances {
+            name: "g2d_frame_sw#10"
+            max_dur_ns: 40
+            min_dur_ns: 20
+            avg_dur_ns: 30
+            frame_count: 2
+            error_count: 0
+        }
+        instances {
+            name: "g2d_frame_sw#11"
+            max_dur_ns: 40
+            min_dur_ns: 40
+            avg_dur_ns: 40
+            frame_count: 1
+            error_count: 2
+        }
+        max_dur_ns: 40
+        min_dur_ns: 20
+        avg_dur_ns: 33
+        frame_count: 3
+        error_count: 2
+    }
+}
diff --git a/test/trace_processor/graphics/g2d_metrics.textproto b/test/trace_processor/graphics/g2d_metrics.textproto
new file mode 100644
index 0000000..9ed87bf
--- /dev/null
+++ b/test/trace_processor/graphics/g2d_metrics.textproto
@@ -0,0 +1,127 @@
+packet {
+  ftrace_events {
+    cpu: 2
+    event {
+      timestamp: 1000
+      pid: 237
+      g2d_tracing_mark_write {
+        pid: 237
+        name: "g2d_frame_sw#11"
+        type: 67
+        value: 0
+      }
+    }
+    event {
+      timestamp: 1003
+      pid: 237
+      g2d_tracing_mark_write {
+        pid: 237
+        name: "g2d_frame_sw#11"
+        type: 67
+        value: 0
+      }
+    }
+    event {
+      timestamp: 1005
+      pid: 237
+      g2d_tracing_mark_write {
+        pid: 237
+        name: "g2d_frame_sw#11"
+        type: 67
+        value: 1
+      }
+    }
+    event {
+      timestamp: 1010
+      pid: 237
+      g2d_tracing_mark_write {
+        pid: 237
+        name: "g2d_frame_sw#10"
+        type: 67
+        value: 1
+      }
+    }
+    event {
+      timestamp: 1020
+      pid: 237
+      g2d_tracing_mark_write {
+        pid: 237
+        name: "g2d_frame_sw#11"
+        type: 67
+        value: 1
+      }
+    }
+    event {
+      timestamp: 1030
+      pid: 237
+      g2d_tracing_mark_write {
+        pid: 237
+        name: "g2d_frame_sw#10"
+        type: 67
+        value: 0
+      }
+    }
+    event {
+      timestamp: 1040
+      pid: 237
+      g2d_tracing_mark_write {
+        pid: 237
+        name: "g2d_frame_sw#10"
+        type: 67
+        value: 1
+      }
+    }
+    event {
+      timestamp: 1050
+      pid: 237
+      g2d_tracing_mark_write {
+        pid: 237
+        name: "g2d_frame_hw#10"
+        type: 67
+        value: 1
+      }
+    }
+    event {
+      timestamp: 1060
+      pid: 237
+      g2d_tracing_mark_write {
+        pid: 237
+        name: "g2d_frame_sw#11"
+        type: 67
+        value: 0
+      }
+    }
+    event {
+      timestamp: 1070
+      pid: 237
+      g2d_tracing_mark_write {
+        pid: 237
+        name: "g2d_frame_hw#10"
+        type: 67
+        value: 0
+      }
+    }
+    event {
+      timestamp: 1080
+      pid: 237
+      g2d_tracing_mark_write {
+        pid: 237
+        name: "g2d_frame_sw#10"
+        type: 67
+        value: 0
+      }
+    }
+    event {
+      timestamp: 1085
+      pid: 237
+      g2d_tracing_mark_write {
+        pid: 237
+        name: "g2d_frame_sw#11"
+        type: 67
+        value: 1
+      }
+    }
+  }
+  trusted_uid: 9999
+  trusted_packet_sequence_id: 3
+}
\ No newline at end of file
diff --git a/test/trace_processor/graphics/index b/test/trace_processor/graphics/index
index 01edbd3..6c6d8d4 100644
--- a/test/trace_processor/graphics/index
+++ b/test/trace_processor/graphics/index
@@ -36,3 +36,6 @@
 
 # Android Jank metrics
 android_jank.py android_jank android_jank.out
+
+# G2D metrics
+g2d_metrics.textproto g2d g2d_metrics.out