Add F2fs Metrics for Counters and Writes

Test: <trace_processer_shell> --run-metrics android_io_unagg <trace>
Test: tools/diff_test_trace_processor.py <trace_processer_shell> --name-filter=.*f2fs_aggregate_write_stats*
Change-Id: Icb9a420f9a05252bcaccf5dea635a6738ae98427
diff --git a/Android.bp b/Android.bp
index b40e467..b78249c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -4405,6 +4405,8 @@
         "protos/perfetto/metrics/android/gpu_metric.proto",
         "protos/perfetto/metrics/android/hwcomposer.proto",
         "protos/perfetto/metrics/android/hwui_metric.proto",
+        "protos/perfetto/metrics/android/io_metric.proto",
+        "protos/perfetto/metrics/android/io_unagg_metric.proto",
         "protos/perfetto/metrics/android/ion_metric.proto",
         "protos/perfetto/metrics/android/irq_runtime_metric.proto",
         "protos/perfetto/metrics/android/jank_cuj_metric.proto",
@@ -4482,6 +4484,8 @@
         "protos/perfetto/metrics/android/gpu_metric.proto",
         "protos/perfetto/metrics/android/hwcomposer.proto",
         "protos/perfetto/metrics/android/hwui_metric.proto",
+        "protos/perfetto/metrics/android/io_metric.proto",
+        "protos/perfetto/metrics/android/io_unagg_metric.proto",
         "protos/perfetto/metrics/android/ion_metric.proto",
         "protos/perfetto/metrics/android/irq_runtime_metric.proto",
         "protos/perfetto/metrics/android/jank_cuj_metric.proto",
@@ -4541,6 +4545,8 @@
         "protos/perfetto/metrics/android/gpu_metric.proto",
         "protos/perfetto/metrics/android/hwcomposer.proto",
         "protos/perfetto/metrics/android/hwui_metric.proto",
+        "protos/perfetto/metrics/android/io_metric.proto",
+        "protos/perfetto/metrics/android/io_unagg_metric.proto",
         "protos/perfetto/metrics/android/ion_metric.proto",
         "protos/perfetto/metrics/android/irq_runtime_metric.proto",
         "protos/perfetto/metrics/android/jank_cuj_metric.proto",
@@ -10177,6 +10183,8 @@
         "src/trace_processor/metrics/sql/android/android_hwcomposer.sql",
         "src/trace_processor/metrics/sql/android/android_hwui_metric.sql",
         "src/trace_processor/metrics/sql/android/android_hwui_threads.sql",
+        "src/trace_processor/metrics/sql/android/android_io.sql",
+        "src/trace_processor/metrics/sql/android/android_io_unagg.sql",
         "src/trace_processor/metrics/sql/android/android_ion.sql",
         "src/trace_processor/metrics/sql/android/android_irq_runtime.sql",
         "src/trace_processor/metrics/sql/android/android_jank_cuj.sql",
diff --git a/BUILD b/BUILD
index 1d0f2e7..a28f7f3 100644
--- a/BUILD
+++ b/BUILD
@@ -1849,6 +1849,8 @@
         "src/trace_processor/metrics/sql/android/android_hwcomposer.sql",
         "src/trace_processor/metrics/sql/android/android_hwui_metric.sql",
         "src/trace_processor/metrics/sql/android/android_hwui_threads.sql",
+        "src/trace_processor/metrics/sql/android/android_io.sql",
+        "src/trace_processor/metrics/sql/android/android_io_unagg.sql",
         "src/trace_processor/metrics/sql/android/android_ion.sql",
         "src/trace_processor/metrics/sql/android/android_irq_runtime.sql",
         "src/trace_processor/metrics/sql/android/android_jank_cuj.sql",
@@ -4067,6 +4069,8 @@
         "protos/perfetto/metrics/android/gpu_metric.proto",
         "protos/perfetto/metrics/android/hwcomposer.proto",
         "protos/perfetto/metrics/android/hwui_metric.proto",
+        "protos/perfetto/metrics/android/io_metric.proto",
+        "protos/perfetto/metrics/android/io_unagg_metric.proto",
         "protos/perfetto/metrics/android/ion_metric.proto",
         "protos/perfetto/metrics/android/irq_runtime_metric.proto",
         "protos/perfetto/metrics/android/jank_cuj_metric.proto",
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index a9e9d2c..3c18498 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -39,6 +39,8 @@
     "gpu_metric.proto",
     "hwcomposer.proto",
     "hwui_metric.proto",
+    "io_metric.proto",
+    "io_unagg_metric.proto",
     "ion_metric.proto",
     "irq_runtime_metric.proto",
     "jank_cuj_metric.proto",
diff --git a/protos/perfetto/metrics/android/io_metric.proto b/protos/perfetto/metrics/android/io_metric.proto
new file mode 100644
index 0000000..4f35243
--- /dev/null
+++ b/protos/perfetto/metrics/android/io_metric.proto
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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;
+
+// Measure Android IO stats in a trace.
+// Note: This is an aggregated metric, for unaggregated metrics look at AndroidIoUnaggregated
+// in io_unagg_metric.proto.
+message AndroidIo {
+  // Next id: 3
+  // Stats for Counters in an f2fs file system.
+  // Counters are available for various operations.
+  message F2fsCounterStats {
+    optional string name = 1;
+    optional double max = 2;
+    optional double sum = 3;
+    optional double min = 5;
+    optional int64 dur = 6;
+    optional int64 count = 7;
+    optional double avg = 8;
+  }
+  // Aggregated stats for write operations in an f2fs file system.
+  message F2fsWriteStats {
+    optional int64 total_write_count = 1;
+    optional int64 distinct_processes = 2;
+    optional int64 total_bytes_written = 3;
+    optional int64 distinct_device_count = 4;
+    optional int64 distict_inode_count = 5;
+    optional int64 distinct_thread_count = 6;
+  }
+  repeated F2fsCounterStats f2fs_counter_stats = 1;
+  repeated F2fsWriteStats f2fs_write_stats = 2;
+}
diff --git a/protos/perfetto/metrics/android/io_unagg_metric.proto b/protos/perfetto/metrics/android/io_unagg_metric.proto
new file mode 100644
index 0000000..9afa7eb
--- /dev/null
+++ b/protos/perfetto/metrics/android/io_unagg_metric.proto
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 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;
+
+// IO metrics on Android in unaggregated form.
+// Note: this generates a lot of data so should not be requested unless it
+// is clear that this data is necessary.
+message AndroidIoUnaggregated {
+    // Next id: 2
+    message F2fsWriteUnaggreagatedStat {
+      optional uint32 tid = 1;
+      optional string thread_name = 2;
+      optional uint32 pid = 3;
+      optional string process_name = 4;
+      optional int64 ino = 5;
+      optional int64 dev = 6;
+    }
+    // F2fs write stats which are grouped by thread and inode.
+    repeated F2fsWriteUnaggreagatedStat f2fs_write_unaggregated_stats = 1;
+}
\ No newline at end of file
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index 6e7ef02..dfad850 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -34,6 +34,8 @@
 import "protos/perfetto/metrics/android/gpu_metric.proto";
 import "protos/perfetto/metrics/android/hwcomposer.proto";
 import "protos/perfetto/metrics/android/hwui_metric.proto";
+import "protos/perfetto/metrics/android/io_metric.proto";
+import "protos/perfetto/metrics/android/io_unagg_metric.proto";
 import "protos/perfetto/metrics/android/ion_metric.proto";
 import "protos/perfetto/metrics/android/irq_runtime_metric.proto";
 import "protos/perfetto/metrics/android/jank_cuj_metric.proto";
@@ -104,7 +106,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 52
+// Next id: 55
 message TraceMetrics {
   reserved 4, 10, 13, 14, 16, 19;
 
@@ -246,6 +248,14 @@
   // Metrics to track codec framework.
   optional AndroidCodecMetrics codec_metrics = 52;
 
+  // Metric to track Android IO.
+  optional AndroidIo android_io = 53;
+
+  // IO metrics on Android in unaggregated form.
+  // Note: this generates a lot of data so should not be requested unless it
+  // is clear that this data is necessary.
+  optional AndroidIoUnaggregated android_io_unagg = 54;
+
   // 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 4182a94..bc9ae02 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -898,6 +898,59 @@
 
 // End of protos/perfetto/metrics/android/hwui_metric.proto
 
+// Begin of protos/perfetto/metrics/android/io_metric.proto
+
+// Measure Android IO stats in a trace.
+// Note: This is an aggregated metric, for unaggregated metrics look at AndroidIoUnaggregated
+// in io_unagg_metric.proto.
+message AndroidIo {
+  // Next id: 3
+  // Stats for Counters in an f2fs file system.
+  // Counters are available for various operations.
+  message F2fsCounterStats {
+    optional string name = 1;
+    optional double max = 2;
+    optional double sum = 3;
+    optional double min = 5;
+    optional int64 dur = 6;
+    optional int64 count = 7;
+    optional double avg = 8;
+  }
+  // Aggregated stats for write operations in an f2fs file system.
+  message F2fsWriteStats {
+    optional int64 total_write_count = 1;
+    optional int64 distinct_processes = 2;
+    optional int64 total_bytes_written = 3;
+    optional int64 distinct_device_count = 4;
+    optional int64 distict_inode_count = 5;
+    optional int64 distinct_thread_count = 6;
+  }
+  repeated F2fsCounterStats f2fs_counter_stats = 1;
+  repeated F2fsWriteStats f2fs_write_stats = 2;
+}
+
+// End of protos/perfetto/metrics/android/io_metric.proto
+
+// Begin of protos/perfetto/metrics/android/io_unagg_metric.proto
+
+// IO metrics on Android in unaggregated form.
+// Note: this generates a lot of data so should not be requested unless it
+// is clear that this data is necessary.
+message AndroidIoUnaggregated {
+    // Next id: 2
+    message F2fsWriteUnaggreagatedStat {
+      optional uint32 tid = 1;
+      optional string thread_name = 2;
+      optional uint32 pid = 3;
+      optional string process_name = 4;
+      optional int64 ino = 5;
+      optional int64 dev = 6;
+    }
+    // F2fs write stats which are grouped by thread and inode.
+    repeated F2fsWriteUnaggreagatedStat f2fs_write_unaggregated_stats = 1;
+}
+// End of protos/perfetto/metrics/android/io_unagg_metric.proto
+
 // Begin of protos/perfetto/metrics/android/ion_metric.proto
 
 // ion memory stats on Android.
@@ -2164,7 +2217,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 52
+// Next id: 55
 message TraceMetrics {
   reserved 4, 10, 13, 14, 16, 19;
 
@@ -2306,6 +2359,14 @@
   // Metrics to track codec framework.
   optional AndroidCodecMetrics codec_metrics = 52;
 
+  // Metric to track Android IO.
+  optional AndroidIo android_io = 53;
+
+  // IO metrics on Android in unaggregated form.
+  // Note: this generates a lot of data so should not be requested unless it
+  // is clear that this data is necessary.
+  optional AndroidIoUnaggregated android_io_unagg = 54;
+
   // Demo extensions.
   extensions 450 to 499;
 
diff --git a/python/perfetto/trace_processor/metrics.descriptor b/python/perfetto/trace_processor/metrics.descriptor
index 6143157..6192efc 100644
--- a/python/perfetto/trace_processor/metrics.descriptor
+++ b/python/perfetto/trace_processor/metrics.descriptor
Binary files differ
diff --git a/src/trace_processor/metrics/sql/android/BUILD.gn b/src/trace_processor/metrics/sql/android/BUILD.gn
index 147b688..444fd95 100644
--- a/src/trace_processor/metrics/sql/android/BUILD.gn
+++ b/src/trace_processor/metrics/sql/android/BUILD.gn
@@ -35,6 +35,8 @@
     "android_hwcomposer.sql",
     "android_hwui_metric.sql",
     "android_hwui_threads.sql",
+    "android_io.sql",
+    "android_io_unagg.sql",
     "android_ion.sql",
     "android_irq_runtime.sql",
     "android_jank_cuj.sql",
diff --git a/src/trace_processor/metrics/sql/android/android_io.sql b/src/trace_processor/metrics/sql/android/android_io.sql
new file mode 100644
index 0000000..a09cc08
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/android_io.sql
@@ -0,0 +1,49 @@
+--
+-- Copyright 2023 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 IMPORT('android.io');
+
+DROP VIEW IF EXISTS android_io_output;
+CREATE VIEW android_io_output AS
+SELECT AndroidIo(
+    'f2fs_counter_stats', (
+        SELECT RepeatedField(
+            AndroidIo_F2fsCounterStats(
+                'name', name,
+                'sum', sum,
+                'max', max,
+                'min', min,
+                'dur', dur,
+                'count', count,
+                'avg', avg
+            )
+        )
+        FROM android_io_f2fs_counter_stats
+    ),
+    'f2fs_write_stats', (
+        SELECT RepeatedField(
+            AndroidIo_F2fsWriteStats(
+                'total_write_count', total_write_count,
+                'distinct_processes', distinct_processes,
+                'total_bytes_written', total_bytes_written,
+                'distinct_device_count', distinct_device_count,
+                'distict_inode_count', distict_inode_count,
+                'distinct_thread_count', distinct_thread_count
+            )
+        )
+        FROM android_io_f2fs_aggregate_write_stats
+    )
+);
\ No newline at end of file
diff --git a/src/trace_processor/metrics/sql/android/android_io_unagg.sql b/src/trace_processor/metrics/sql/android/android_io_unagg.sql
new file mode 100644
index 0000000..50e3b59
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/android_io_unagg.sql
@@ -0,0 +1,35 @@
+--
+-- Copyright 2023 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 IMPORT('android.io');
+
+DROP VIEW IF EXISTS android_io_unagg_output;
+CREATE VIEW android_io_unagg_output AS
+SELECT AndroidIoUnaggregated(
+    'f2fs_write_unaggregated_stats', (
+        SELECT RepeatedField(
+            AndroidIoUnaggregated_F2fsWriteUnaggreagatedStat(
+                'tid', tid,
+                'thread_name', thread_name,
+                'pid', pid,
+                'process_name', process_name,
+                'ino', ino,
+                'dev', dev
+            )
+        )
+        FROM android_io_f2fs_write_stats
+    )
+);
\ No newline at end of file
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/io.sql b/src/trace_processor/perfetto_sql/stdlib/android/io.sql
index c6953b1..624ebea 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/io.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/io.sql
@@ -24,18 +24,18 @@
 -- @column counter_avg    Avergate of all the counter values for the counter name.
 CREATE VIEW android_io_f2fs_counter_stats AS
 SELECT
-  STR_SPLIT(counter_track.name, '].', 1) AS counter_name,
-  SUM(counter.value) AS counter_sum,
-  MAX(counter.value) AS counter_max,
-  MIN(counter.value) AS counter_min,
-  MAX(ts) - MIN(ts) AS counter_dur,
-  COUNT(ts) AS counter_count,
-  AVG(counter.value) AS counter_avg
+  STR_SPLIT(counter_track.name, '].', 1) AS name,
+  SUM(counter.value) AS sum,
+  MAX(counter.value) AS max,
+  MIN(counter.value) AS min,
+  MAX(ts) - MIN(ts) AS dur,
+  COUNT(ts) AS count,
+  AVG(counter.value) AS avg
 FROM counter
 JOIN counter_track
   ON counter_track.id = counter.track_id AND counter_track.name LIKE '%f2fs%'
-GROUP BY counter_name
-ORDER BY counter_sum DESC;
+GROUP BY name
+ORDER BY sum DESC;
 
 -- Aggregates f2fs_write stats by inode and thread.
 --
@@ -79,3 +79,22 @@
   USING (upid)
 GROUP BY utid, ino, dev
 ORDER BY bytes DESC;
+
+-- Aggregates f2fs write stats. Counts distinct datapoints, total write operations,
+-- and bytes written
+--
+-- @column total_write_count        Total number of writes in the trace.
+-- @column distinct_processes       Number of distinct processes.
+-- @column total_bytes_written      Total number of bytes written.
+-- @column distinct_device_count    Count of distinct devices written to.
+-- @column distict_inode_count      Count of distinct inodes written to.
+-- @column distinct_thread_count    Count of distinct threads writing.
+
+CREATE VIEW android_io_f2fs_aggregate_write_stats AS
+select SUM(write_count) as total_write_count,
+      COUNT(DISTINCT pid) distinct_processes,
+      SUM(bytes) as total_bytes_written,
+      COUNT(DISTINCT dev) as distinct_device_count,
+      COUNT(DISTINCT ino) distict_inode_count,
+      COUNT(DISTINCT tid) distinct_thread_count
+from android_io_f2fs_write_stats;
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/android/tests.py b/test/trace_processor/diff_tests/android/tests.py
index bb9d675..f0ce4ca 100644
--- a/test/trace_processor/diff_tests/android/tests.py
+++ b/test/trace_processor/diff_tests/android/tests.py
@@ -523,7 +523,7 @@
       SELECT * FROM android_io_f2fs_counter_stats;
       """,
         out=Csv("""
-        "counter_name","counter_sum","counter_max","counter_min","counter_dur","counter_count","counter_avg"
+        "name","sum","max","min","dur","count","avg"
         "read_app_total",580966.000000,567184.000000,13782.000000,2515275969,2,290483.000000
         "read_app_buffered",580966.000000,567184.000000,13782.000000,2515275969,2,290483.000000
         "write_cp_node",94208.000000,94208.000000,0.000000,2515275969,2,47104.000000
@@ -600,6 +600,20 @@
         3548,"AsyncTask #1",3487,"com.android.providers.media.module",2643,65077,8,8
       """))
 
+  def test_f2fs_aggregate_write_stats(self):
+      return DiffTestBlueprint(
+        trace=DataPath('android_monitor_contention_trace.atr'),
+        query= """
+        SELECT IMPORT('android.io');
+        SELECT total_write_count, distinct_processes, total_bytes_written,
+               distinct_devices, distict_inodes, distinct_threads
+        FROM android_io_f2fs_aggregate_write_stats
+        """,
+        out= Csv("""
+        "total_write_count","distinct_processes","total_bytes_written","distinct_devices","distict_inodes","distinct_threads"
+        203,3,375180,1,13,6
+        """))
+
   def test_binder_async_txns(self):
     return DiffTestBlueprint(
         trace=DataPath('android_binder_metric_trace.atr'),