Merge "Detect heapprofd with untrustworth self_max_count."
diff --git a/src/trace_processor/importers/proto/heap_profile_tracker.cc b/src/trace_processor/importers/proto/heap_profile_tracker.cc
index 951bb8c..968da7d 100644
--- a/src/trace_processor/importers/proto/heap_profile_tracker.cc
+++ b/src/trace_processor/importers/proto/heap_profile_tracker.cc
@@ -177,9 +177,10 @@
     uint32_t merged_idx =
         callsite_to_merged_callsite[*callsites_tbl.id().IndexOf(
             CallsiteId(static_cast<uint32_t>(callsite_id)))];
-    // On Android R, the count field is incorrectly set. As such, we cannot
-    // depend on count == 0 to imply size == 0, so we check for both of them
-    // separately. TODO(fmayer): Hide count on R builds.
+    // On old heapprofd producers, the count field is incorrectly set and we
+    // zero it in proto_trace_parser.cc.
+    // As such, we cannot depend on count == 0 to imply size == 0, so we check
+    // for both of them separately.
     if (size > 0) {
       tbl->mutable_alloc_size()->Set(merged_idx,
                                      tbl->alloc_size()[merged_idx] + size);
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index 4a2e0b9..f35618c 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -336,6 +336,11 @@
         stats::heapprofd_unwind_samples, static_cast<int>(entry.pid()),
         static_cast<int64_t>(stats.heap_samples()));
 
+    // orig_sampling_interval_bytes was introduced slightly after a bug with
+    // self_max_count was fixed in the producer. We use this as a proxy
+    // whether or not we are getting this data from a fixed producer or not.
+    bool trustworthy_max_count = entry.orig_sampling_interval_bytes() > 0;
+
     for (auto sample_it = entry.samples(); sample_it; ++sample_it) {
       protos::pbzero::ProfilePacket::HeapSample::Decoder sample(*sample_it);
 
@@ -351,7 +356,8 @@
       src_allocation.callstack_id = sample.callstack_id();
       if (sample.has_self_max()) {
         src_allocation.self_allocated = sample.self_max();
-        src_allocation.alloc_count = sample.self_max_count();
+        if (trustworthy_max_count)
+          src_allocation.alloc_count = sample.self_max_count();
       } else {
         src_allocation.self_allocated = sample.self_allocated();
         src_allocation.self_freed = sample.self_freed();
diff --git a/test/trace_processor/profiling/heap_profile_dump_max.out b/test/trace_processor/profiling/heap_profile_dump_max.out
new file mode 100644
index 0000000..1ef5076
--- /dev/null
+++ b/test/trace_processor/profiling/heap_profile_dump_max.out
@@ -0,0 +1,3 @@
+"id","type","ts","upid","heap_name","callsite_id","count","size"
+0,"heap_profile_allocation",-10,2,"malloc",2,6,1000
+1,"heap_profile_allocation",-10,2,"malloc",3,1,90
diff --git a/test/trace_processor/profiling/heap_profile_dump_max.textproto b/test/trace_processor/profiling/heap_profile_dump_max.textproto
new file mode 100644
index 0000000..6efbfe1
--- /dev/null
+++ b/test/trace_processor/profiling/heap_profile_dump_max.textproto
@@ -0,0 +1,149 @@
+packet {
+  process_tree {
+    processes {
+      pid: 1
+      ppid: 0
+      cmdline: "init"
+      uid: 0
+    }
+    processes {
+      pid: 2
+      ppid: 1
+      cmdline: "system_server"
+      uid: 1000
+    }
+  }
+}
+
+packet {
+  clock_snapshot {
+    clocks: {
+      clock_id: 6 # BOOTTIME
+      timestamp: 0
+    }
+    clocks: {
+      clock_id: 4 # MONOTONIC_COARSE
+      timestamp: 10
+    }
+  }
+}
+
+packet {
+  trusted_packet_sequence_id: 999
+  previous_packet_dropped: true
+  incremental_state_cleared: true
+  timestamp: 10
+  profile_packet {
+    strings {
+      iid: 1
+      str: "f1"
+    }
+    strings {
+      iid: 2
+      str: "f2"
+    }
+    strings {
+      iid: 3
+      str: "f3"
+    }
+    strings {
+      iid: 4
+      str: "liblib.so"
+    }
+    strings {
+      iid: 5
+      str: "build-id"
+    }
+    frames {
+      iid: 1
+      function_name_id: 1
+      mapping_id: 1
+      rel_pc: 0x1000
+    }
+    frames {
+      iid: 2
+      function_name_id: 2
+      mapping_id: 1
+      rel_pc: 0x2000
+    }
+    frames {
+      iid: 3
+      function_name_id: 3
+      mapping_id: 1
+      rel_pc: 0x3000
+    }
+    frames {
+      iid: 4
+      function_name_id: 2
+      mapping_id: 2
+      rel_pc: 0x4000
+    }
+    callstacks {
+      iid: 1
+      frame_ids: 1
+      frame_ids: 2
+      frame_ids: 3
+    }
+    callstacks {
+      iid: 2
+      frame_ids: 1
+      frame_ids: 4
+    }
+    mappings {
+      iid: 1
+      path_string_ids: 4
+      build_id: 5
+    }
+    mappings {
+      iid: 2
+      path_string_ids: 4
+      build_id: 5
+    }
+    process_dumps {
+      pid: 2
+      orig_sampling_interval_bytes: 1024
+      sampling_interval_bytes: 1024
+      samples {
+        callstack_id: 1
+        self_max: 1000
+        self_max_count: 6
+      }
+      samples {
+        callstack_id: 2
+        self_max: 90
+        self_max_count: 1
+      }
+    }
+  }
+}
+# Add some symbolization packets
+packet {
+  module_symbols {
+    path: "/liblib.so"
+    build_id: "build-id"
+    address_symbols {
+      address: 0x3000
+      lines {
+        function_name: "symbolized f3"
+        source_file_name: "f3.cc"
+        line_number: 33
+      }
+    }
+    address_symbols {
+      address: 0x2000
+      lines {
+        function_name: "symbolized f2"
+        source_file_name: "f2.cc"
+        line_number: 22
+      }
+    }
+    address_symbols {
+      address: 0x4000
+      lines {
+        function_name: "symbolized f2"
+        source_file_name: "f2.cc"
+        line_number: 23
+      }
+    }
+  }
+}
diff --git a/test/trace_processor/profiling/heap_profile_dump_max_legacy.out b/test/trace_processor/profiling/heap_profile_dump_max_legacy.out
new file mode 100644
index 0000000..a5e6319
--- /dev/null
+++ b/test/trace_processor/profiling/heap_profile_dump_max_legacy.out
@@ -0,0 +1,3 @@
+"id","type","ts","upid","heap_name","callsite_id","count","size"
+0,"heap_profile_allocation",-10,2,"malloc",2,0,1000
+1,"heap_profile_allocation",-10,2,"malloc",3,0,90
diff --git a/test/trace_processor/profiling/heap_profile_dump_max_legacy.textproto b/test/trace_processor/profiling/heap_profile_dump_max_legacy.textproto
new file mode 100644
index 0000000..86cadb4
--- /dev/null
+++ b/test/trace_processor/profiling/heap_profile_dump_max_legacy.textproto
@@ -0,0 +1,147 @@
+packet {
+  process_tree {
+    processes {
+      pid: 1
+      ppid: 0
+      cmdline: "init"
+      uid: 0
+    }
+    processes {
+      pid: 2
+      ppid: 1
+      cmdline: "system_server"
+      uid: 1000
+    }
+  }
+}
+
+packet {
+  clock_snapshot {
+    clocks: {
+      clock_id: 6 # BOOTTIME
+      timestamp: 0
+    }
+    clocks: {
+      clock_id: 4 # MONOTONIC_COARSE
+      timestamp: 10
+    }
+  }
+}
+
+packet {
+  trusted_packet_sequence_id: 999
+  previous_packet_dropped: true
+  incremental_state_cleared: true
+  timestamp: 10
+  profile_packet {
+    strings {
+      iid: 1
+      str: "f1"
+    }
+    strings {
+      iid: 2
+      str: "f2"
+    }
+    strings {
+      iid: 3
+      str: "f3"
+    }
+    strings {
+      iid: 4
+      str: "liblib.so"
+    }
+    strings {
+      iid: 5
+      str: "build-id"
+    }
+    frames {
+      iid: 1
+      function_name_id: 1
+      mapping_id: 1
+      rel_pc: 0x1000
+    }
+    frames {
+      iid: 2
+      function_name_id: 2
+      mapping_id: 1
+      rel_pc: 0x2000
+    }
+    frames {
+      iid: 3
+      function_name_id: 3
+      mapping_id: 1
+      rel_pc: 0x3000
+    }
+    frames {
+      iid: 4
+      function_name_id: 2
+      mapping_id: 2
+      rel_pc: 0x4000
+    }
+    callstacks {
+      iid: 1
+      frame_ids: 1
+      frame_ids: 2
+      frame_ids: 3
+    }
+    callstacks {
+      iid: 2
+      frame_ids: 1
+      frame_ids: 4
+    }
+    mappings {
+      iid: 1
+      path_string_ids: 4
+      build_id: 5
+    }
+    mappings {
+      iid: 2
+      path_string_ids: 4
+      build_id: 5
+    }
+    process_dumps {
+      pid: 2
+      samples {
+        callstack_id: 1
+        self_max: 1000
+        self_max_count: 6
+      }
+      samples {
+        callstack_id: 2
+        self_max: 90
+        self_max_count: 1
+      }
+    }
+  }
+}
+# Add some symbolization packets
+packet {
+  module_symbols {
+    path: "/liblib.so"
+    build_id: "build-id"
+    address_symbols {
+      address: 0x3000
+      lines {
+        function_name: "symbolized f3"
+        source_file_name: "f3.cc"
+        line_number: 33
+      }
+    }
+    address_symbols {
+      address: 0x2000
+      lines {
+        function_name: "symbolized f2"
+        source_file_name: "f2.cc"
+        line_number: 22
+      }
+    }
+    address_symbols {
+      address: 0x4000
+      lines {
+        function_name: "symbolized f2"
+        source_file_name: "f2.cc"
+        line_number: 23
+      }
+    }
+  }
+}
diff --git a/test/trace_processor/profiling/index b/test/trace_processor/profiling/index
index ab299b5..60166f5 100644
--- a/test/trace_processor/profiling/index
+++ b/test/trace_processor/profiling/index
@@ -3,6 +3,8 @@
 heap_profile_jit.textproto heap_profile_frames.sql heap_profile_jit.out
 heap_profile_deobfuscate.textproto heap_profile_deobfuscate.sql heap_profile_deobfuscate.out
 heap_profile_deobfuscate_memfd.textproto heap_profile_deobfuscate.sql heap_profile_deobfuscate.out
+heap_profile_dump_max_legacy.textproto heap_profile_tracker_new_stack.sql heap_profile_dump_max_legacy.out
+heap_profile_dump_max.textproto heap_profile_tracker_new_stack.sql heap_profile_dump_max.out
 
 
 profiler_smaps.textproto profiler_smaps.sql profiler_smaps.out