Parse ion_stat metric

Tracepoint introduced for 4.19+ kernels. The intent is to eventually replace
the existing ion_heap_grow / shrink events.

This tracepoint tracks allocations across heaps and can therefore be
complemented with reading /sys/kernel/ion/total_heaps_kb

Bug: 154302786
Change-Id: I787064db833cc9fc9276d86c254354e0998067cd
diff --git a/Android.bp b/Android.bp
index 0434316..265894a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3596,6 +3596,7 @@
     "protos/perfetto/trace/ftrace/ftrace_stats.proto",
     "protos/perfetto/trace/ftrace/generic.proto",
     "protos/perfetto/trace/ftrace/i2c.proto",
+    "protos/perfetto/trace/ftrace/ion.proto",
     "protos/perfetto/trace/ftrace/ipi.proto",
     "protos/perfetto/trace/ftrace/irq.proto",
     "protos/perfetto/trace/ftrace/kmem.proto",
@@ -3637,6 +3638,7 @@
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/generic.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/i2c.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/ion.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ipi.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/irq.gen.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/kmem.gen.cc",
@@ -3678,6 +3680,7 @@
     "protos/perfetto/trace/ftrace/ftrace_stats.proto",
     "protos/perfetto/trace/ftrace/generic.proto",
     "protos/perfetto/trace/ftrace/i2c.proto",
+    "protos/perfetto/trace/ftrace/ion.proto",
     "protos/perfetto/trace/ftrace/ipi.proto",
     "protos/perfetto/trace/ftrace/irq.proto",
     "protos/perfetto/trace/ftrace/kmem.proto",
@@ -3719,6 +3722,7 @@
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/generic.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/i2c.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/ion.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ipi.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/irq.gen.h",
     "external/perfetto/protos/perfetto/trace/ftrace/kmem.gen.h",
@@ -3764,6 +3768,7 @@
     "protos/perfetto/trace/ftrace/ftrace_stats.proto",
     "protos/perfetto/trace/ftrace/generic.proto",
     "protos/perfetto/trace/ftrace/i2c.proto",
+    "protos/perfetto/trace/ftrace/ion.proto",
     "protos/perfetto/trace/ftrace/ipi.proto",
     "protos/perfetto/trace/ftrace/irq.proto",
     "protos/perfetto/trace/ftrace/kmem.proto",
@@ -3804,6 +3809,7 @@
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/generic.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/i2c.pb.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/ion.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ipi.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/irq.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/kmem.pb.cc",
@@ -3845,6 +3851,7 @@
     "protos/perfetto/trace/ftrace/ftrace_stats.proto",
     "protos/perfetto/trace/ftrace/generic.proto",
     "protos/perfetto/trace/ftrace/i2c.proto",
+    "protos/perfetto/trace/ftrace/ion.proto",
     "protos/perfetto/trace/ftrace/ipi.proto",
     "protos/perfetto/trace/ftrace/irq.proto",
     "protos/perfetto/trace/ftrace/kmem.proto",
@@ -3885,6 +3892,7 @@
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/generic.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/i2c.pb.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/ion.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ipi.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/irq.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/kmem.pb.h",
@@ -3930,6 +3938,7 @@
     "protos/perfetto/trace/ftrace/ftrace_stats.proto",
     "protos/perfetto/trace/ftrace/generic.proto",
     "protos/perfetto/trace/ftrace/i2c.proto",
+    "protos/perfetto/trace/ftrace/ion.proto",
     "protos/perfetto/trace/ftrace/ipi.proto",
     "protos/perfetto/trace/ftrace/irq.proto",
     "protos/perfetto/trace/ftrace/kmem.proto",
@@ -3971,6 +3980,7 @@
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/generic.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/i2c.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/ion.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/ipi.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/irq.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/kmem.pbzero.cc",
@@ -4012,6 +4022,7 @@
     "protos/perfetto/trace/ftrace/ftrace_stats.proto",
     "protos/perfetto/trace/ftrace/generic.proto",
     "protos/perfetto/trace/ftrace/i2c.proto",
+    "protos/perfetto/trace/ftrace/ion.proto",
     "protos/perfetto/trace/ftrace/ipi.proto",
     "protos/perfetto/trace/ftrace/irq.proto",
     "protos/perfetto/trace/ftrace/kmem.proto",
@@ -4053,6 +4064,7 @@
     "external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/generic.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/i2c.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/ion.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/ipi.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/irq.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/kmem.pbzero.h",
diff --git a/BUILD b/BUILD
index bff4261..e2bfa69 100644
--- a/BUILD
+++ b/BUILD
@@ -2166,6 +2166,7 @@
         "protos/perfetto/trace/ftrace/ftrace_stats.proto",
         "protos/perfetto/trace/ftrace/generic.proto",
         "protos/perfetto/trace/ftrace/i2c.proto",
+        "protos/perfetto/trace/ftrace/ion.proto",
         "protos/perfetto/trace/ftrace/ipi.proto",
         "protos/perfetto/trace/ftrace/irq.proto",
         "protos/perfetto/trace/ftrace/kmem.proto",
diff --git a/protos/perfetto/trace/ftrace/all_protos.gni b/protos/perfetto/trace/ftrace/all_protos.gni
index a8ae6b4..8d58926 100644
--- a/protos/perfetto/trace/ftrace/all_protos.gni
+++ b/protos/perfetto/trace/ftrace/all_protos.gni
@@ -31,6 +31,7 @@
   "filemap.proto",
   "ftrace.proto",
   "i2c.proto",
+  "ion.proto",
   "ipi.proto",
   "irq.proto",
   "kmem.proto",
diff --git a/protos/perfetto/trace/ftrace/ftrace_event.proto b/protos/perfetto/trace/ftrace/ftrace_event.proto
index db57e3c..5cb52de 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event.proto
@@ -31,6 +31,7 @@
 import "protos/perfetto/trace/ftrace/filemap.proto";
 import "protos/perfetto/trace/ftrace/ftrace.proto";
 import "protos/perfetto/trace/ftrace/i2c.proto";
+import "protos/perfetto/trace/ftrace/ion.proto";
 import "protos/perfetto/trace/ftrace/ipi.proto";
 import "protos/perfetto/trace/ftrace/irq.proto";
 import "protos/perfetto/trace/ftrace/kmem.proto";
@@ -413,5 +414,6 @@
     GpuFrequencyFtraceEvent gpu_frequency = 332;
     SdeTracingMarkWriteFtraceEvent sde_tracing_mark_write = 333;
     MarkVictimFtraceEvent mark_victim = 334;
+    IonStatFtraceEvent ion_stat = 335;
   }
 }
diff --git a/protos/perfetto/trace/ftrace/ion.proto b/protos/perfetto/trace/ftrace/ion.proto
new file mode 100644
index 0000000..03a34be
--- /dev/null
+++ b/protos/perfetto/trace/ftrace/ion.proto
@@ -0,0 +1,12 @@
+// Autogenerated by:
+// ../../tools/ftrace_proto_gen/ftrace_proto_gen.cc
+// Do not edit.
+
+syntax = "proto2";
+package perfetto.protos;
+
+message IonStatFtraceEvent {
+  optional uint32 buffer_id = 1;
+  optional int64 len = 2;
+  optional uint64 total_allocated = 3;
+}
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index a1507dc..126e28c 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -3284,6 +3284,16 @@
 
 // End of protos/perfetto/trace/ftrace/i2c.proto
 
+// Begin of protos/perfetto/trace/ftrace/ion.proto
+
+message IonStatFtraceEvent {
+  optional uint32 buffer_id = 1;
+  optional int64 len = 2;
+  optional uint64 total_allocated = 3;
+}
+
+// End of protos/perfetto/trace/ftrace/ion.proto
+
 // Begin of protos/perfetto/trace/ftrace/ipi.proto
 
 message IpiEntryFtraceEvent {
@@ -4380,6 +4390,7 @@
     GpuFrequencyFtraceEvent gpu_frequency = 332;
     SdeTracingMarkWriteFtraceEvent sde_tracing_mark_write = 333;
     MarkVictimFtraceEvent mark_victim = 334;
+    IonStatFtraceEvent ion_stat = 335;
   }
 }
 
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index 37396a1..a1c3b89 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -31,6 +31,7 @@
 #include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
 #include "protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h"
 #include "protos/perfetto/trace/ftrace/generic.pbzero.h"
+#include "protos/perfetto/trace/ftrace/ion.pbzero.h"
 #include "protos/perfetto/trace/ftrace/kmem.pbzero.h"
 #include "protos/perfetto/trace/ftrace/lowmemorykiller.pbzero.h"
 #include "protos/perfetto/trace/ftrace/mm_event.pbzero.h"
@@ -67,6 +68,8 @@
       cpu_freq_name_id_(context->storage->InternString("cpufreq")),
       gpu_freq_name_id_(context->storage->InternString("gpufreq")),
       cpu_idle_name_id_(context->storage->InternString("cpuidle")),
+      ion_total_id_(context->storage->InternString("mem.ion")),
+      ion_change_id_(context->storage->InternString("mem.ion_change")),
       ion_total_unknown_id_(context->storage->InternString("mem.ion.unknown")),
       ion_change_unknown_id_(
           context->storage->InternString("mem.ion_change.unknown")),
@@ -279,6 +282,10 @@
         ParseIonHeapGrowOrShrink(ts, pid, data, false);
         break;
       }
+      case FtraceEvent::kIonStatFieldNumber: {
+        ParseIonStat(ts, pid, data);
+        break;
+      }
       case FtraceEvent::kSignalGenerateFieldNumber: {
         ParseSignalGenerate(ts, data);
         break;
@@ -552,6 +559,7 @@
       evt.trace_name(), tgid, evt.value());
 }
 
+/** Parses ion heap events present in Pixel kernels. */
 void FtraceParser::ParseIonHeapGrowOrShrink(int64_t ts,
                                             uint32_t pid,
                                             ConstBytes blob,
@@ -606,6 +614,24 @@
       "ION field mismatch");
 }
 
+/** Parses ion heap events (introduced in 4.19 kernels). */
+void FtraceParser::ParseIonStat(int64_t ts,
+                                uint32_t pid,
+                                protozero::ConstBytes data) {
+  protos::pbzero::IonStatFtraceEvent::Decoder ion(data.data, data.size);
+  // Push the global counter.
+  TrackId track =
+      context_->track_tracker->InternGlobalCounterTrack(ion_total_id_);
+  context_->event_tracker->PushCounter(ts, ion.total_allocated(), track);
+
+  // Push the change counter.
+  // TODO(b/121331269): these should really be instant events.
+  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
+  track =
+      context_->track_tracker->InternThreadCounterTrack(ion_change_id_, utid);
+  context_->event_tracker->PushCounter(ts, ion.len(), track);
+}
+
 // This event has both the pid of the thread that sent the signal and the
 // destination of the signal. Currently storing the pid of the destination.
 void FtraceParser::ParseSignalGenerate(int64_t ts, ConstBytes blob) {
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.h b/src/trace_processor/importers/ftrace/ftrace_parser.h
index c7cd6d3..539311b 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.h
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.h
@@ -64,6 +64,7 @@
                                 uint32_t pid,
                                 protozero::ConstBytes,
                                 bool grow);
+  void ParseIonStat(int64_t ts, uint32_t pid, protozero::ConstBytes);
   void ParseSignalGenerate(int64_t ts, protozero::ConstBytes);
   void ParseSignalDeliver(int64_t ts, uint32_t pid, protozero::ConstBytes);
   void ParseLowmemoryKill(int64_t ts, protozero::ConstBytes);
@@ -88,6 +89,8 @@
   const StringId cpu_freq_name_id_;
   const StringId gpu_freq_name_id_;
   const StringId cpu_idle_name_id_;
+  const StringId ion_total_id_;
+  const StringId ion_change_id_;
   const StringId ion_total_unknown_id_;
   const StringId ion_change_unknown_id_;
   const StringId signal_generate_id_;
diff --git a/src/traced/probes/ftrace/event_info.cc b/src/traced/probes/ftrace/event_info.cc
index b6f3ef8..37a3736 100644
--- a/src/traced/probes/ftrace/event_info.cc
+++ b/src/traced/probes/ftrace/event_info.cc
@@ -4141,6 +4141,22 @@
        kUnsetFtraceId,
        34,
        kUnsetSize},
+      {"ion_stat",
+       "ion",
+       {
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "buffer_id", 1, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "len", 2, ProtoSchemaType::kInt64,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "total_allocated", 3, ProtoSchemaType::kUint64,
+            TranslationStrategy::kInvalidTranslationStrategy},
+       },
+       kUnsetFtraceId,
+       335,
+       kUnsetSize},
       {"ipi_entry",
        "ipi",
        {
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/ion/ion_stat/format b/src/traced/probes/ftrace/test/data/synthetic/events/ion/ion_stat/format
new file mode 100644
index 0000000..a326934
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/synthetic/events/ion/ion_stat/format
@@ -0,0 +1,13 @@
+name: ion_stat
+ID: 1076
+format:
+	field:unsigned short common_type;	offset:0;	size:2;	signed:0;
+	field:unsigned char common_flags;	offset:2;	size:1;	signed:0;
+	field:unsigned char common_preempt_count;	offset:3;	size:1;	signed:0;
+	field:int common_pid;	offset:4;	size:4;	signed:1;
+
+	field:unsigned int buffer_id;	offset:8;	size:4;	signed:0;
+	field:long len;	offset:16;	size:8;	signed:1;
+	field:unsigned long total_allocated;	offset:24;	size:8;	signed:0;
+
+print fmt: "buffer_id=%u len=%ldB total_allocated=%ldB", REC->buffer_id, REC->len, REC->total_allocated
diff --git a/test/trace_processor/index b/test/trace_processor/index
index 5eda8af..255481b 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -69,6 +69,7 @@
 ../data/memory_counters.pb args_string_is_not_null.sql memory_counters_args_string_is_not_null.out
 ../data/memory_counters.pb b120605557.sql memory_counters_b120605557.out
 ../data/memory_counters.pb global_memory_counter.sql global_memory_counter_memory_counters.out
+ion_stat.textproto ion_stat.sql ion_stat.out
 
 # Stats
 ../data/android_sched_and_ps.pb stats.sql android_sched_and_ps_stats.out
diff --git a/test/trace_processor/ion_stat.out b/test/trace_processor/ion_stat.out
new file mode 100644
index 0000000..90c127e
--- /dev/null
+++ b/test/trace_processor/ion_stat.out
@@ -0,0 +1,3 @@
+"name","ts","value"
+"mem.ion",1234,200.000000
+"mem.ion_change",1234,100.000000
diff --git a/test/trace_processor/ion_stat.sql b/test/trace_processor/ion_stat.sql
new file mode 100644
index 0000000..1032ac6
--- /dev/null
+++ b/test/trace_processor/ion_stat.sql
@@ -0,0 +1,4 @@
+SELECT t.name, c.ts, c.value
+FROM counter c
+JOIN track t ON c.track_id = t.id
+WHERE t.name LIKE 'mem.ion%';
diff --git a/test/trace_processor/ion_stat.textproto b/test/trace_processor/ion_stat.textproto
new file mode 100644
index 0000000..b65f5b0
--- /dev/null
+++ b/test/trace_processor/ion_stat.textproto
@@ -0,0 +1,14 @@
+packet {
+  ftrace_events {
+    cpu: 4
+    event {
+      timestamp: 1234
+      pid: 4321
+      ion_stat {
+        buffer_id: 101010
+        len: 100
+        total_allocated: 200
+      }
+    }
+  }
+}
diff --git a/tools/ftrace_proto_gen/event_whitelist b/tools/ftrace_proto_gen/event_whitelist
index 184e149..f28511d 100644
--- a/tools/ftrace_proto_gen/event_whitelist
+++ b/tools/ftrace_proto_gen/event_whitelist
@@ -329,3 +329,4 @@
 power/gpu_frequency
 sde/tracing_mark_write
 oom/mark_victim
+ion/ion_stat