processor: Extract HeapGraph parsing into module

.. so it can be disabled at compile time.

Also moves heap_graph_tracker.h/cc into importers/proto, since that's
the only importer that currently uses it.

Bug: 141459049
Change-Id: I500255f7a31e0c936f4180bf0b8cba2e674d9945
diff --git a/Android.bp b/Android.bp
index 9535112..5fe6780 100644
--- a/Android.bp
+++ b/Android.bp
@@ -4623,8 +4623,6 @@
     "src/trace_processor/forwarding_trace_parser.cc",
     "src/trace_processor/ftrace_utils.cc",
     "src/trace_processor/gzip_trace_parser.cc",
-    "src/trace_processor/heap_graph_tracker.cc",
-    "src/trace_processor/heap_graph_walker.cc",
     "src/trace_processor/heap_profile_tracker.cc",
     "src/trace_processor/importers/ftrace/ftrace_descriptors.cc",
     "src/trace_processor/importers/ftrace/ftrace_parser.cc",
@@ -4636,6 +4634,9 @@
     "src/trace_processor/importers/fuchsia/fuchsia_trace_utils.cc",
     "src/trace_processor/importers/proto/android_probes_parser.cc",
     "src/trace_processor/importers/proto/graphics_event_parser.cc",
+    "src/trace_processor/importers/proto/heap_graph_module.cc",
+    "src/trace_processor/importers/proto/heap_graph_tracker.cc",
+    "src/trace_processor/importers/proto/heap_graph_walker.cc",
     "src/trace_processor/importers/proto/proto_trace_parser.cc",
     "src/trace_processor/importers/proto/proto_trace_tokenizer.cc",
     "src/trace_processor/importers/proto/system_probes_parser.cc",
@@ -4681,9 +4682,9 @@
     "src/trace_processor/filtered_row_index_unittest.cc",
     "src/trace_processor/forwarding_trace_parser_unittest.cc",
     "src/trace_processor/ftrace_utils_unittest.cc",
-    "src/trace_processor/heap_graph_walker_unittest.cc",
     "src/trace_processor/heap_profile_tracker_unittest.cc",
     "src/trace_processor/importers/fuchsia/fuchsia_trace_utils_unittest.cc",
+    "src/trace_processor/importers/proto/heap_graph_walker_unittest.cc",
     "src/trace_processor/importers/proto/proto_trace_parser_unittest.cc",
     "src/trace_processor/importers/systrace/systrace_parser_unittest.cc",
     "src/trace_processor/metadata_table_unittest.cc",
diff --git a/BUILD b/BUILD
index a6b683e..cf821db 100644
--- a/BUILD
+++ b/BUILD
@@ -747,10 +747,6 @@
         "src/trace_processor/ftrace_utils.h",
         "src/trace_processor/gzip_trace_parser.cc",
         "src/trace_processor/gzip_trace_parser.h",
-        "src/trace_processor/heap_graph_tracker.cc",
-        "src/trace_processor/heap_graph_tracker.h",
-        "src/trace_processor/heap_graph_walker.cc",
-        "src/trace_processor/heap_graph_walker.h",
         "src/trace_processor/heap_profile_tracker.cc",
         "src/trace_processor/heap_profile_tracker.h",
         "src/trace_processor/importers/ftrace/ftrace_descriptors.cc",
@@ -782,6 +778,12 @@
         "src/trace_processor/importers/proto/graphics_event_module.h",
         "src/trace_processor/importers/proto/graphics_event_parser.cc",
         "src/trace_processor/importers/proto/graphics_event_parser.h",
+        "src/trace_processor/importers/proto/heap_graph_module.cc",
+        "src/trace_processor/importers/proto/heap_graph_module.h",
+        "src/trace_processor/importers/proto/heap_graph_tracker.cc",
+        "src/trace_processor/importers/proto/heap_graph_tracker.h",
+        "src/trace_processor/importers/proto/heap_graph_walker.cc",
+        "src/trace_processor/importers/proto/heap_graph_walker.h",
         "src/trace_processor/importers/proto/packet_sequence_state.h",
         "src/trace_processor/importers/proto/proto_importer_module.h",
         "src/trace_processor/importers/proto/proto_incremental_state.h",
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index 2e38ca4..1fba09e 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -85,6 +85,7 @@
     "PERFETTO_TP_HTTPD=$perfetto_tp_httpd",
     "PERFETTO_TP_SYSTEM_PROBES=$enable_perfetto_trace_processor_system_probes",
     "PERFETTO_TP_ANDROID_PROBES=$enable_perfetto_trace_processor_android_probes",
+    "PERFETTO_TP_HEAP_GRAPHS=$enable_perfetto_trace_processor_heap_graphs",
     "PERFETTO_TP_GRAPHICS=$enable_perfetto_trace_processor_graphics",
     "PERFETTO_TP_JSON=$enable_perfetto_trace_processor_json",
     "PERFETTO_TP_JSON_IMPORT=$enable_perfetto_trace_processor_json_import",
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index 51c1c6f..a8492e5 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -221,6 +221,10 @@
   enable_perfetto_trace_processor_android_probes =
       enable_perfetto_trace_processor && !build_with_chromium
 
+  # Enables parsing support for heap graphs in trace processor.
+  enable_perfetto_trace_processor_heap_graphs =
+      enable_perfetto_trace_processor && !build_with_chromium
+
   # Enables graphics event support in the trace processor.
   enable_perfetto_trace_processor_graphics =
       enable_perfetto_trace_processor && !build_with_chromium
diff --git a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
index c077efe..4edd028 100644
--- a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
@@ -23,6 +23,7 @@
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HTTPD() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_SYSTEM_PROBES() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_ANDROID_PROBES() (1)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HEAP_GRAPHS() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_GRAPHICS() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON_IMPORT() (0)
diff --git a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
index feb10fc..49f80f5 100644
--- a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
@@ -23,6 +23,7 @@
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HTTPD() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() || PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() || PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX())
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_SYSTEM_PROBES() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_ANDROID_PROBES() (1)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HEAP_GRAPHS() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_GRAPHICS() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON_IMPORT() (1)
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 3ffd7f9..eda227b 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -60,10 +60,6 @@
     "ftrace_utils.h",
     "gzip_trace_parser.cc",
     "gzip_trace_parser.h",
-    "heap_graph_tracker.cc",
-    "heap_graph_tracker.h",
-    "heap_graph_walker.cc",
-    "heap_graph_walker.h",
     "heap_profile_tracker.cc",
     "heap_profile_tracker.h",
     "importers/ftrace/ftrace_descriptors.h",
@@ -76,6 +72,9 @@
     "importers/proto/android_probes_parser.h",
     "importers/proto/graphics_event_module.h",
     "importers/proto/graphics_event_parser.h",
+    "importers/proto/heap_graph_module.h",
+    "importers/proto/heap_graph_tracker.h",
+    "importers/proto/heap_graph_walker.h",
     "importers/proto/packet_sequence_state.h",
     "importers/proto/proto_importer_module.h",
     "importers/proto/proto_incremental_state.h",
@@ -177,6 +176,13 @@
   if (enable_perfetto_trace_processor_android_probes) {
     sources += [ "importers/proto/android_probes_parser.cc" ]
   }
+  if (enable_perfetto_trace_processor_heap_graphs) {
+    sources += [
+      "importers/proto/heap_graph_module.cc",
+      "importers/proto/heap_graph_tracker.cc",
+      "importers/proto/heap_graph_walker.cc",
+    ]
+  }
   if (enable_perfetto_trace_processor_graphics) {
     sources += [
       "importers/proto/graphics_event_parser.cc",
@@ -356,7 +362,6 @@
     "clock_tracker_unittest.cc",
     "event_tracker_unittest.cc",
     "forwarding_trace_parser_unittest.cc",
-    "heap_graph_walker_unittest.cc",
     "heap_profile_tracker_unittest.cc",
     "importers/proto/proto_trace_parser_unittest.cc",
     "importers/systrace/systrace_parser_unittest.cc",
@@ -429,6 +434,9 @@
       "thread_table_unittest.cc",
     ]
   }
+  if (enable_perfetto_trace_processor_heap_graphs) {
+    sources += [ "importers/proto/heap_graph_walker_unittest.cc" ]
+  }
   if (enable_perfetto_trace_processor_fuchsia) {
     sources += [ "importers/fuchsia/fuchsia_trace_utils_unittest.cc" ]
   }
diff --git a/src/trace_processor/importers/proto/heap_graph_module.cc b/src/trace_processor/importers/proto/heap_graph_module.cc
new file mode 100644
index 0000000..50bba45
--- /dev/null
+++ b/src/trace_processor/importers/proto/heap_graph_module.cc
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "src/trace_processor/importers/proto/heap_graph_module.h"
+
+#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
+#include "src/trace_processor/process_tracker.h"
+#include "src/trace_processor/trace_processor_context.h"
+#include "src/trace_processor/trace_storage.h"
+
+#include "protos/perfetto/trace/profiling/heap_graph.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+namespace {
+
+const char* HeapGraphRootTypeToString(int32_t type) {
+  switch (type) {
+    case protos::pbzero::HeapGraphRoot::ROOT_UNKNOWN:
+      return "ROOT_UNKNOWN";
+    case protos::pbzero::HeapGraphRoot::ROOT_JNI_GLOBAL:
+      return "ROOT_JNI_GLOBAL";
+    case protos::pbzero::HeapGraphRoot::ROOT_JNI_LOCAL:
+      return "ROOT_JNI_LOCAL";
+    case protos::pbzero::HeapGraphRoot::ROOT_JAVA_FRAME:
+      return "ROOT_JAVA_FRAME";
+    case protos::pbzero::HeapGraphRoot::ROOT_NATIVE_STACK:
+      return "ROOT_NATIVE_STACK";
+    case protos::pbzero::HeapGraphRoot::ROOT_STICKY_CLASS:
+      return "ROOT_STICKY_CLASS";
+    case protos::pbzero::HeapGraphRoot::ROOT_THREAD_BLOCK:
+      return "ROOT_THREAD_BLOCK";
+    case protos::pbzero::HeapGraphRoot::ROOT_MONITOR_USED:
+      return "ROOT_MONITOR_USED";
+    case protos::pbzero::HeapGraphRoot::ROOT_THREAD_OBJECT:
+      return "ROOT_THREAD_OBJECT";
+    case protos::pbzero::HeapGraphRoot::ROOT_INTERNED_STRING:
+      return "ROOT_INTERNED_STRING";
+    case protos::pbzero::HeapGraphRoot::ROOT_FINALIZING:
+      return "ROOT_FINALIZING";
+    case protos::pbzero::HeapGraphRoot::ROOT_DEBUGGER:
+      return "ROOT_DEBUGGER";
+    case protos::pbzero::HeapGraphRoot::ROOT_REFERENCE_CLEANUP:
+      return "ROOT_REFERENCE_CLEANUP";
+    case protos::pbzero::HeapGraphRoot::ROOT_VM_INTERNAL:
+      return "ROOT_VM_INTERNAL";
+    case protos::pbzero::HeapGraphRoot::ROOT_JNI_MONITOR:
+      return "ROOT_JNI_MONITOR";
+    default:
+      return "ROOT_UNKNOWN";
+  }
+}
+
+}  // namespace
+
+void HeapGraphModule::ParseHeapGraph(int64_t ts, protozero::ConstBytes blob) {
+  protos::pbzero::HeapGraph::Decoder heap_graph(blob.data, blob.size);
+  UniquePid upid = context_->process_tracker->GetOrCreateProcess(
+      static_cast<uint32_t>(heap_graph.pid()));
+  context_->heap_graph_tracker->SetPacketIndex(heap_graph.index());
+  for (auto it = heap_graph.objects(); it; ++it) {
+    protos::pbzero::HeapGraphObject::Decoder object(*it);
+    HeapGraphTracker::SourceObject obj;
+    obj.object_id = object.id();
+    obj.self_size = object.self_size();
+    obj.type_id = object.type_id();
+    auto ref_field_ids_it = object.reference_field_id();
+    auto ref_object_ids_it = object.reference_object_id();
+    for (; ref_field_ids_it && ref_object_ids_it;
+         ++ref_field_ids_it, ++ref_object_ids_it) {
+      HeapGraphTracker::SourceObject::Reference ref;
+      ref.field_name_id = *ref_field_ids_it;
+      ref.owned_object_id = *ref_object_ids_it;
+      obj.references.emplace_back(std::move(ref));
+    }
+
+    if (ref_field_ids_it || ref_object_ids_it) {
+      context_->storage->IncrementIndexedStats(stats::heap_graph_missing_packet,
+                                               static_cast<int>(upid));
+      continue;
+    }
+    context_->heap_graph_tracker->AddObject(upid, ts, std::move(obj));
+  }
+  for (auto it = heap_graph.type_names(); it; ++it) {
+    protos::pbzero::InternedString::Decoder entry(*it);
+    const char* str = reinterpret_cast<const char*>(entry.str().data);
+    auto str_view = base::StringView(str, entry.str().size);
+
+    context_->heap_graph_tracker->AddInternedTypeName(
+        entry.iid(), context_->storage->InternString(str_view));
+  }
+  for (auto it = heap_graph.field_names(); it; ++it) {
+    protos::pbzero::InternedString::Decoder entry(*it);
+    const char* str = reinterpret_cast<const char*>(entry.str().data);
+    auto str_view = base::StringView(str, entry.str().size);
+
+    context_->heap_graph_tracker->AddInternedFieldName(
+        entry.iid(), context_->storage->InternString(str_view));
+  }
+  for (auto it = heap_graph.roots(); it; ++it) {
+    protos::pbzero::HeapGraphRoot::Decoder entry(*it);
+    const char* str = HeapGraphRootTypeToString(entry.root_type());
+    auto str_view = base::StringView(str);
+
+    HeapGraphTracker::SourceRoot src_root;
+    src_root.root_type = context_->storage->InternString(str_view);
+    for (auto obj_it = entry.object_ids(); obj_it; ++obj_it)
+      src_root.object_ids.emplace_back(*obj_it);
+    context_->heap_graph_tracker->AddRoot(upid, ts, std::move(src_root));
+  }
+  if (!heap_graph.continued()) {
+    context_->heap_graph_tracker->FinalizeProfile();
+  }
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/heap_graph_module.h b/src/trace_processor/importers/proto/heap_graph_module.h
new file mode 100644
index 0000000..1d80b13
--- /dev/null
+++ b/src/trace_processor/importers/proto/heap_graph_module.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_MODULE_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_MODULE_H_
+
+#include "perfetto/base/build_config.h"
+#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
+#include "src/trace_processor/importers/proto/proto_importer_module.h"
+#include "src/trace_processor/timestamped_trace_piece.h"
+
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class HeapGraphModule : public ProtoImporterModuleBase<PERFETTO_BUILDFLAG(
+                            PERFETTO_TP_HEAP_GRAPHS)> {
+ public:
+  explicit HeapGraphModule(TraceProcessorContext* context)
+      : ProtoImporterModuleBase(context) {
+    context_->heap_graph_tracker.reset(new HeapGraphTracker(context_));
+  }
+
+  ModuleResult ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
+                           const TimestampedTracePiece& ttp) {
+    if (decoder.has_heap_graph()) {
+      ParseHeapGraph(ttp.timestamp, decoder.heap_graph());
+      return ModuleResult::Handled();
+    }
+
+    return ModuleResult::Ignored();
+  }
+
+ private:
+  void ParseHeapGraph(int64_t ts, protozero::ConstBytes);
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_MODULE_H_
diff --git a/src/trace_processor/heap_graph_tracker.cc b/src/trace_processor/importers/proto/heap_graph_tracker.cc
similarity index 98%
rename from src/trace_processor/heap_graph_tracker.cc
rename to src/trace_processor/importers/proto/heap_graph_tracker.cc
index 53489c4..e2d6aef 100644
--- a/src/trace_processor/heap_graph_tracker.cc
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "src/trace_processor/heap_graph_tracker.h"
+#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
 
 namespace perfetto {
 namespace trace_processor {
diff --git a/src/trace_processor/heap_graph_tracker.h b/src/trace_processor/importers/proto/heap_graph_tracker.h
similarity index 90%
rename from src/trace_processor/heap_graph_tracker.h
rename to src/trace_processor/importers/proto/heap_graph_tracker.h
index 0cff15a..e022906 100644
--- a/src/trace_processor/heap_graph_tracker.h
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef SRC_TRACE_PROCESSOR_HEAP_GRAPH_TRACKER_H_
-#define SRC_TRACE_PROCESSOR_HEAP_GRAPH_TRACKER_H_
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_TRACKER_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_TRACKER_H_
 
 #include <map>
 #include <vector>
@@ -23,7 +23,7 @@
 #include "perfetto/ext/base/optional.h"
 
 #include "protos/perfetto/trace/profiling/heap_graph.pbzero.h"
-#include "src/trace_processor/heap_graph_walker.h"
+#include "src/trace_processor/importers/proto/heap_graph_walker.h"
 #include "src/trace_processor/trace_processor_context.h"
 #include "src/trace_processor/trace_storage.h"
 
@@ -87,4 +87,4 @@
 }  // namespace trace_processor
 }  // namespace perfetto
 
-#endif  // SRC_TRACE_PROCESSOR_HEAP_GRAPH_TRACKER_H_
+#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_TRACKER_H_
diff --git a/src/trace_processor/heap_graph_walker.cc b/src/trace_processor/importers/proto/heap_graph_walker.cc
similarity index 99%
rename from src/trace_processor/heap_graph_walker.cc
rename to src/trace_processor/importers/proto/heap_graph_walker.cc
index 1325cd1..15e8a74 100644
--- a/src/trace_processor/heap_graph_walker.cc
+++ b/src/trace_processor/importers/proto/heap_graph_walker.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "src/trace_processor/heap_graph_walker.h"
+#include "src/trace_processor/importers/proto/heap_graph_walker.h"
 #include "perfetto/base/logging.h"
 
 namespace perfetto {
diff --git a/src/trace_processor/heap_graph_walker.h b/src/trace_processor/importers/proto/heap_graph_walker.h
similarity index 95%
rename from src/trace_processor/heap_graph_walker.h
rename to src/trace_processor/importers/proto/heap_graph_walker.h
index 5bf0d22..e1a4f19 100644
--- a/src/trace_processor/heap_graph_walker.h
+++ b/src/trace_processor/importers/proto/heap_graph_walker.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef SRC_TRACE_PROCESSOR_HEAP_GRAPH_WALKER_H_
-#define SRC_TRACE_PROCESSOR_HEAP_GRAPH_WALKER_H_
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_WALKER_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_WALKER_H_
 
 #include <inttypes.h>
 #include <map>
@@ -187,4 +187,4 @@
 }  // namespace trace_processor
 }  // namespace perfetto
 
-#endif  // SRC_TRACE_PROCESSOR_HEAP_GRAPH_WALKER_H_
+#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_WALKER_H_
diff --git a/src/trace_processor/heap_graph_walker_unittest.cc b/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
similarity index 98%
rename from src/trace_processor/heap_graph_walker_unittest.cc
rename to src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
index 2e24d59..51acc39 100644
--- a/src/trace_processor/heap_graph_walker_unittest.cc
+++ b/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "src/trace_processor/heap_graph_walker.h"
+#include "src/trace_processor/importers/proto/heap_graph_walker.h"
 
 #include "perfetto/base/logging.h"
 #include "test/gtest_and_gmock.h"
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index a2f2c8d..6144550 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -31,11 +31,11 @@
 #include "perfetto/trace_processor/status.h"
 #include "src/trace_processor/args_tracker.h"
 #include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/heap_graph_tracker.h"
 #include "src/trace_processor/heap_profile_tracker.h"
 #include "src/trace_processor/importers/ftrace/ftrace_module.h"
 #include "src/trace_processor/importers/proto/android_probes_module.h"
 #include "src/trace_processor/importers/proto/graphics_event_module.h"
+#include "src/trace_processor/importers/proto/heap_graph_module.h"
 #include "src/trace_processor/importers/proto/packet_sequence_state.h"
 #include "src/trace_processor/importers/proto/system_probes_module.h"
 #include "src/trace_processor/importers/proto/track_event_module.h"
@@ -55,7 +55,6 @@
 #include "protos/perfetto/trace/clock_snapshot.pbzero.h"
 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
 #include "protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h"
-#include "protos/perfetto/trace/profiling/heap_graph.pbzero.h"
 #include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
 #include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
 #include "protos/perfetto/trace/trace.pbzero.h"
@@ -166,43 +165,6 @@
   size_t seq_state_generation_;
 };
 
-const char* HeapGraphRootTypeToString(int32_t type) {
-  switch (type) {
-    case protos::pbzero::HeapGraphRoot::ROOT_UNKNOWN:
-      return "ROOT_UNKNOWN";
-    case protos::pbzero::HeapGraphRoot::ROOT_JNI_GLOBAL:
-      return "ROOT_JNI_GLOBAL";
-    case protos::pbzero::HeapGraphRoot::ROOT_JNI_LOCAL:
-      return "ROOT_JNI_LOCAL";
-    case protos::pbzero::HeapGraphRoot::ROOT_JAVA_FRAME:
-      return "ROOT_JAVA_FRAME";
-    case protos::pbzero::HeapGraphRoot::ROOT_NATIVE_STACK:
-      return "ROOT_NATIVE_STACK";
-    case protos::pbzero::HeapGraphRoot::ROOT_STICKY_CLASS:
-      return "ROOT_STICKY_CLASS";
-    case protos::pbzero::HeapGraphRoot::ROOT_THREAD_BLOCK:
-      return "ROOT_THREAD_BLOCK";
-    case protos::pbzero::HeapGraphRoot::ROOT_MONITOR_USED:
-      return "ROOT_MONITOR_USED";
-    case protos::pbzero::HeapGraphRoot::ROOT_THREAD_OBJECT:
-      return "ROOT_THREAD_OBJECT";
-    case protos::pbzero::HeapGraphRoot::ROOT_INTERNED_STRING:
-      return "ROOT_INTERNED_STRING";
-    case protos::pbzero::HeapGraphRoot::ROOT_FINALIZING:
-      return "ROOT_FINALIZING";
-    case protos::pbzero::HeapGraphRoot::ROOT_DEBUGGER:
-      return "ROOT_DEBUGGER";
-    case protos::pbzero::HeapGraphRoot::ROOT_REFERENCE_CLEANUP:
-      return "ROOT_REFERENCE_CLEANUP";
-    case protos::pbzero::HeapGraphRoot::ROOT_VM_INTERNAL:
-      return "ROOT_VM_INTERNAL";
-    case protos::pbzero::HeapGraphRoot::ROOT_JNI_MONITOR:
-      return "ROOT_JNI_MONITOR";
-    default:
-      return "ROOT_UNKNOWN";
-  }
-}
-
 }  // namespace
 
 ProtoTraceParser::ProtoTraceParser(TraceProcessorContext* context)
@@ -254,6 +216,9 @@
   if (!context_->android_probes_module->ParsePacket(packet, ttp).ignored())
     return;
 
+  if (!context_->heap_graph_module->ParsePacket(packet, ttp).ignored())
+    return;
+
   if (!context_->graphics_event_module->ParsePacket(packet, ttp).ignored())
     return;
 
@@ -291,10 +256,6 @@
   if (packet.has_module_symbols()) {
     ParseModuleSymbols(packet.module_symbols());
   }
-
-  if (packet.has_heap_graph()) {
-    ParseHeapGraph(ts, packet.heap_graph());
-  }
 }
 
 void ProtoTraceParser::ParseFtracePacket(uint32_t cpu,
@@ -692,65 +653,5 @@
   }
 }
 
-void ProtoTraceParser::ParseHeapGraph(int64_t ts, ConstBytes blob) {
-  protos::pbzero::HeapGraph::Decoder heap_graph(blob.data, blob.size);
-  UniquePid upid = context_->process_tracker->GetOrCreateProcess(
-      static_cast<uint32_t>(heap_graph.pid()));
-  context_->heap_graph_tracker->SetPacketIndex(heap_graph.index());
-  for (auto it = heap_graph.objects(); it; ++it) {
-    protos::pbzero::HeapGraphObject::Decoder object(*it);
-    HeapGraphTracker::SourceObject obj;
-    obj.object_id = object.id();
-    obj.self_size = object.self_size();
-    obj.type_id = object.type_id();
-    auto ref_field_ids_it = object.reference_field_id();
-    auto ref_object_ids_it = object.reference_object_id();
-    for (; ref_field_ids_it && ref_object_ids_it;
-         ++ref_field_ids_it, ++ref_object_ids_it) {
-      HeapGraphTracker::SourceObject::Reference ref;
-      ref.field_name_id = *ref_field_ids_it;
-      ref.owned_object_id = *ref_object_ids_it;
-      obj.references.emplace_back(std::move(ref));
-    }
-
-    if (ref_field_ids_it || ref_object_ids_it) {
-      context_->storage->IncrementIndexedStats(stats::heap_graph_missing_packet,
-                                               static_cast<int>(upid));
-      continue;
-    }
-    context_->heap_graph_tracker->AddObject(upid, ts, std::move(obj));
-  }
-  for (auto it = heap_graph.type_names(); it; ++it) {
-    protos::pbzero::InternedString::Decoder entry(*it);
-    const char* str = reinterpret_cast<const char*>(entry.str().data);
-    auto str_view = base::StringView(str, entry.str().size);
-
-    context_->heap_graph_tracker->AddInternedTypeName(
-        entry.iid(), context_->storage->InternString(str_view));
-  }
-  for (auto it = heap_graph.field_names(); it; ++it) {
-    protos::pbzero::InternedString::Decoder entry(*it);
-    const char* str = reinterpret_cast<const char*>(entry.str().data);
-    auto str_view = base::StringView(str, entry.str().size);
-
-    context_->heap_graph_tracker->AddInternedFieldName(
-        entry.iid(), context_->storage->InternString(str_view));
-  }
-  for (auto it = heap_graph.roots(); it; ++it) {
-    protos::pbzero::HeapGraphRoot::Decoder entry(*it);
-    const char* str = HeapGraphRootTypeToString(entry.root_type());
-    auto str_view = base::StringView(str);
-
-    HeapGraphTracker::SourceRoot src_root;
-    src_root.root_type = context_->storage->InternString(str_view);
-    for (auto obj_it = entry.object_ids(); obj_it; ++obj_it)
-      src_root.object_ids.emplace_back(*obj_it);
-    context_->heap_graph_tracker->AddRoot(upid, ts, std::move(src_root));
-  }
-  if (!heap_graph.continued()) {
-    context_->heap_graph_tracker->FinalizeProfile();
-  }
-}
-
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.h b/src/trace_processor/importers/proto/proto_trace_parser.h
index a9fcb6e..bae7341 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.h
+++ b/src/trace_processor/importers/proto/proto_trace_parser.h
@@ -73,7 +73,6 @@
   void ParseMetatraceEvent(int64_t ts, ConstBytes);
   void ParseTraceConfig(ConstBytes);
   void ParseModuleSymbols(ConstBytes);
-  void ParseHeapGraph(int64_t ts, ConstBytes);
 
  private:
   TraceProcessorContext* context_;
diff --git a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
index 3538c50..8d029f5 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
@@ -26,6 +26,7 @@
 #include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
 #include "src/trace_processor/importers/proto/android_probes_module.h"
 #include "src/trace_processor/importers/proto/graphics_event_module.h"
+#include "src/trace_processor/importers/proto/heap_graph_module.h"
 #include "src/trace_processor/importers/proto/proto_importer_module.h"
 #include "src/trace_processor/importers/proto/proto_trace_parser.h"
 #include "src/trace_processor/importers/proto/system_probes_module.h"
@@ -266,12 +267,14 @@
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
     context_.ftrace_module.reset(
         new ProtoImporterModule<FtraceModule>(&context_));
+    context_.track_event_module.reset(
+        new ProtoImporterModule<TrackEventModule>(&context_));
     context_.system_probes_module.reset(
         new ProtoImporterModule<SystemProbesModule>(&context_));
     context_.android_probes_module.reset(
         new ProtoImporterModule<AndroidProbesModule>(&context_));
-    context_.track_event_module.reset(
-        new ProtoImporterModule<TrackEventModule>(&context_));
+    context_.heap_graph_module.reset(
+        new ProtoImporterModule<HeapGraphModule>(&context_));
     context_.graphics_event_module.reset(
         new ProtoImporterModule<GraphicsEventModule>(&context_));
   }
diff --git a/src/trace_processor/trace_processor_context.cc b/src/trace_processor/trace_processor_context.cc
index 67b4152..6576e6d 100644
--- a/src/trace_processor/trace_processor_context.cc
+++ b/src/trace_processor/trace_processor_context.cc
@@ -21,13 +21,14 @@
 #include "src/trace_processor/chunked_trace_reader.h"
 #include "src/trace_processor/clock_tracker.h"
 #include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/heap_graph_tracker.h"
 #include "src/trace_processor/heap_profile_tracker.h"
 #include "src/trace_processor/importers/ftrace/ftrace_module.h"
 #include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
 #include "src/trace_processor/importers/json/json_trace_parser.h"
 #include "src/trace_processor/importers/proto/android_probes_module.h"
 #include "src/trace_processor/importers/proto/graphics_event_module.h"
+#include "src/trace_processor/importers/proto/heap_graph_module.h"
+#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
 #include "src/trace_processor/importers/proto/proto_trace_parser.h"
 #include "src/trace_processor/importers/proto/system_probes_module.h"
 #include "src/trace_processor/importers/proto/track_event_module.h"
diff --git a/src/trace_processor/trace_processor_context.h b/src/trace_processor/trace_processor_context.h
index 27ebf0b..a591654 100644
--- a/src/trace_processor/trace_processor_context.h
+++ b/src/trace_processor/trace_processor_context.h
@@ -33,6 +33,7 @@
 class EventTracker;
 class FtraceModule;
 class GraphicsEventModule;
+class HeapGraphModule;
 class HeapGraphTracker;
 class HeapProfileTracker;
 class ProcessTracker;
@@ -78,6 +79,7 @@
   std::unique_ptr<ProtoImporterModule<SystemProbesModule>> system_probes_module;
   std::unique_ptr<ProtoImporterModule<AndroidProbesModule>>
       android_probes_module;
+  std::unique_ptr<ProtoImporterModule<HeapGraphModule>> heap_graph_module;
   std::unique_ptr<ProtoImporterModule<GraphicsEventModule>>
       graphics_event_module;
 };
diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc
index 0c22424..cc86e0b 100644
--- a/src/trace_processor/trace_processor_storage_impl.cc
+++ b/src/trace_processor/trace_processor_storage_impl.cc
@@ -22,12 +22,13 @@
 #include "src/trace_processor/clock_tracker.h"
 #include "src/trace_processor/event_tracker.h"
 #include "src/trace_processor/forwarding_trace_parser.h"
-#include "src/trace_processor/heap_graph_tracker.h"
 #include "src/trace_processor/heap_profile_tracker.h"
 #include "src/trace_processor/importers/ftrace/ftrace_module.h"
 #include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
 #include "src/trace_processor/importers/proto/android_probes_module.h"
 #include "src/trace_processor/importers/proto/graphics_event_module.h"
+#include "src/trace_processor/importers/proto/heap_graph_module.h"
+#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
 #include "src/trace_processor/importers/proto/proto_importer_module.h"
 #include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
 #include "src/trace_processor/importers/proto/system_probes_module.h"
@@ -59,7 +60,6 @@
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_SYSCALLS)
   context_.clock_tracker.reset(new ClockTracker(&context_));
   context_.heap_profile_tracker.reset(new HeapProfileTracker(&context_));
-  context_.heap_graph_tracker.reset(new HeapGraphTracker(&context_));
 #if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
   context_.sched_tracker.reset(new SchedEventTracker(&context_));
   context_.systrace_parser.reset(new SystraceParser(&context_));
@@ -76,6 +76,8 @@
       new ProtoImporterModule<SystemProbesModule>(&context_));
   context_.android_probes_module.reset(
       new ProtoImporterModule<AndroidProbesModule>(&context_));
+  context_.heap_graph_module.reset(
+      new ProtoImporterModule<HeapGraphModule>(&context_));
   context_.graphics_event_module.reset(
       new ProtoImporterModule<GraphicsEventModule>(&context_));
 }