Merge "Change LMK metric implementation"
diff --git a/src/trace_processor/proto_trace_tokenizer.cc b/src/trace_processor/proto_trace_tokenizer.cc
index 2e54577..41e175e 100644
--- a/src/trace_processor/proto_trace_tokenizer.cc
+++ b/src/trace_processor/proto_trace_tokenizer.cc
@@ -157,17 +157,24 @@
       size -= size_missing;
       partial_buf_.clear();
       uint8_t* buf_start = &buf[0];  // Note that buf is std::moved below.
-      ParseInternal(std::move(buf), buf_start, size_incl_header);
+      bool success = ParseInternal(std::move(buf), buf_start, size_incl_header);
+      if (PERFETTO_UNLIKELY(!success)) {
+        PERFETTO_ELOG(
+            "Failed to parse trace.  Check if the trace is corrupted.");
+        return false;
+      }
     } else {
       partial_buf_.insert(partial_buf_.end(), data, &data[size]);
       return true;
     }
   }
-  ParseInternal(std::move(owned_buf), data, size);
-  return true;
+  bool success = ParseInternal(std::move(owned_buf), data, size);
+  if (!success)
+    PERFETTO_ELOG("Failed to parse trace. Check if the trace is corrupted.");
+  return success;
 }
 
-void ProtoTraceTokenizer::ParseInternal(std::unique_ptr<uint8_t[]> owned_buf,
+bool ProtoTraceTokenizer::ParseInternal(std::unique_ptr<uint8_t[]> owned_buf,
                                         uint8_t* data,
                                         size_t size) {
   PERFETTO_DCHECK(data >= &owned_buf[0]);
@@ -178,7 +185,9 @@
   protos::pbzero::Trace::Decoder decoder(data, size);
   for (auto it = decoder.packet(); it; ++it) {
     size_t field_offset = whole_buf.offset_of(it->data());
-    ParsePacket(whole_buf.slice(field_offset, it->size()));
+    bool success = ParsePacket(whole_buf.slice(field_offset, it->size()));
+    if (PERFETTO_UNLIKELY(!success))
+      return false;
   }
 
   const size_t bytes_left = decoder.bytes_left();
@@ -187,11 +196,13 @@
     partial_buf_.insert(partial_buf_.end(), &data[decoder.read_offset()],
                         &data[decoder.read_offset() + bytes_left]);
   }
+  return true;
 }
 
-void ProtoTraceTokenizer::ParsePacket(TraceBlobView packet) {
+bool ProtoTraceTokenizer::ParsePacket(TraceBlobView packet) {
   protos::pbzero::TracePacket::Decoder decoder(packet.data(), packet.length());
-  PERFETTO_DCHECK(!decoder.bytes_left());
+  if (PERFETTO_UNLIKELY(decoder.bytes_left()))
+    return false;
 
   auto timestamp = decoder.has_timestamp()
                        ? static_cast<int64_t>(decoder.timestamp())
@@ -214,22 +225,24 @@
     auto ftrace_field = decoder.ftrace_events();
     const size_t fld_off = packet.offset_of(ftrace_field.data);
     ParseFtraceBundle(packet.slice(fld_off, ftrace_field.size));
-    return;
+    return true;
   }
 
   if (decoder.has_track_event()) {
     ParseTrackEventPacket(decoder, std::move(packet));
-    return;
+    return true;
   }
 
   if (decoder.has_thread_descriptor()) {
     ParseThreadDescriptorPacket(decoder);
-    return;
+    return true;
   }
 
   // Use parent data and length because we want to parse this again
   // later to get the exact type of the packet.
   context_->sorter->PushTracePacket(timestamp, std::move(packet));
+
+  return true;
 }
 
 void ProtoTraceTokenizer::HandleIncrementalStateCleared(
diff --git a/src/trace_processor/proto_trace_tokenizer.h b/src/trace_processor/proto_trace_tokenizer.h
index 95b1a22..3b68575 100644
--- a/src/trace_processor/proto_trace_tokenizer.h
+++ b/src/trace_processor/proto_trace_tokenizer.h
@@ -58,10 +58,10 @@
   bool Parse(std::unique_ptr<uint8_t[]>, size_t size) override;
 
  private:
-  void ParseInternal(std::unique_ptr<uint8_t[]> owned_buf,
+  bool ParseInternal(std::unique_ptr<uint8_t[]> owned_buf,
                      uint8_t* data,
                      size_t size);
-  void ParsePacket(TraceBlobView);
+  bool ParsePacket(TraceBlobView);
   void HandleIncrementalStateCleared(
       const protos::pbzero::TracePacket::Decoder& packet_decoder);
   void HandlePreviousPacketDropped(
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index 7a97020..91b132d 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -617,7 +617,9 @@
     PERFETTO_CHECK(aio_read(&cb) == 0);
 
     // Parse the completed buffer while the async read is in-flight.
-    tp->Parse(std::move(buf), static_cast<size_t>(rsize));
+    bool success = tp->Parse(std::move(buf), static_cast<size_t>(rsize));
+    if (PERFETTO_UNLIKELY(!success))
+      return 1;
   }
   tp->NotifyEndOfFile();
 
diff --git a/tools/heap_profile b/tools/heap_profile
index c96c1ce..cda8a5e 100755
--- a/tools/heap_profile
+++ b/tools/heap_profile
@@ -141,7 +141,7 @@
                       "multiple of 4096, at least 8192.", type=int,
                       default=8 * 1048576)
   parser.add_argument("--block-client", help="When buffer is full, block the "
-                      "client o wait for buffer space. Use with caution as "
+                      "client to wait for buffer space. Use with caution as "
                       "this can significantly slow down the client",
                       action="store_true")
   parser.add_argument("--simpleperf", action="store_true",