Allow to exclude objects from heap graph.

Test: Profile system_server with ignored_types.
Bug: 143874090
Change-Id: Ibdc4c68831214b6d5717788be201a3067e1e7693
diff --git a/perfetto_hprof/perfetto_hprof.cc b/perfetto_hprof/perfetto_hprof.cc
index a960824..7fa1c33 100644
--- a/perfetto_hprof/perfetto_hprof.cc
+++ b/perfetto_hprof/perfetto_hprof.cc
@@ -181,6 +181,10 @@
     }
 
     dump_smaps_ = cfg->dump_smaps();
+    for (auto it = cfg->ignored_types(); it; ++it) {
+      std::string name = (*it).ToStdString();
+      ignored_types_.emplace_back(std::move(name));
+    }
 
     uint64_t self_pid = static_cast<uint64_t>(getpid());
     for (auto pid_it = cfg->pid(); pid_it; ++pid_it) {
@@ -255,9 +259,12 @@
     return nullptr;
   }
 
+  std::vector<std::string> ignored_types() { return ignored_types_; }
+
  private:
   bool enabled_ = false;
   bool dump_smaps_ = false;
+  std::vector<std::string> ignored_types_;
   static art::Thread* self_;
 };
 
@@ -506,6 +513,16 @@
   }
 }
 
+bool IsIgnored(const std::vector<std::string>& ignored_types,
+               art::mirror::Object* obj) NO_THREAD_SAFETY_ANALYSIS {
+  if (obj->IsClass()) {
+    return false;
+  }
+  art::mirror::Class* klass = obj->GetClass();
+  return std::find(ignored_types.begin(), ignored_types.end(), PrettyType(klass)) !=
+         ignored_types.end();
+}
+
 void DumpPerfetto(art::Thread* self) {
   pid_t parent_pid = getpid();
   LOG(INFO) << "preparing to dump heap for " << parent_pid;
@@ -564,6 +581,7 @@
       [parent_pid, timestamp](JavaHprofDataSource::TraceContext ctx)
           NO_THREAD_SAFETY_ANALYSIS {
             bool dump_smaps;
+            std::vector<std::string> ignored_types;
             {
               auto ds = ctx.GetDataSourceLocked();
               if (!ds || !ds->enabled()) {
@@ -571,6 +589,7 @@
                 return;
               }
               dump_smaps = ds->dump_smaps();
+              ignored_types = ds->ignored_types();
             }
             LOG(INFO) << "dumping heap for " << parent_pid;
             if (dump_smaps) {
@@ -613,8 +632,8 @@
                 new protozero::PackedVarInt);
 
             art::Runtime::Current()->GetHeap()->VisitObjectsPaused(
-                [&writer, &interned_fields, &interned_locations,
-                &reference_field_ids, &reference_object_ids, &interned_classes](
+                [&writer, &interned_fields, &interned_locations, &reference_field_ids,
+                 &reference_object_ids, &interned_classes, &ignored_types](
                     art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
                   if (obj->IsClass()) {
                     art::mirror::Class* klass = obj->AsClass().Ptr();
@@ -663,6 +682,10 @@
                           obj->AsClass()->GetLocation()));
                   }
 
+                  if (IsIgnored(ignored_types, obj)) {
+                    return;
+                  }
+
                   auto class_id = FindOrAppend(&interned_classes, class_ptr);
 
                   perfetto::protos::pbzero::HeapGraphObject* object_proto =
@@ -693,11 +716,16 @@
                           });
                     }
                   }
-                  for (const auto& p : referred_objects) {
-                    if (emit_field_ids) {
-                      reference_field_ids->Append(FindOrAppend(&interned_fields, p.first));
+                  for (auto& p : referred_objects) {
+                    const std::string& field_name = p.first;
+                    art::mirror::Object* referred_obj = p.second;
+                    if (referred_obj && IsIgnored(ignored_types, referred_obj)) {
+                      referred_obj = nullptr;
                     }
-                    reference_object_ids->Append(GetObjectId(p.second));
+                    if (emit_field_ids) {
+                      reference_field_ids->Append(FindOrAppend(&interned_fields, field_name));
+                    }
+                    reference_object_ids->Append(GetObjectId(referred_obj));
                   }
                   if (emit_field_ids) {
                     object_proto->set_reference_field_id(*reference_field_ids);