[tp] Add range of interest feature for track events

- Introduces a new TracePacket type for specifying the "range of interest"
- Introduces a new trace processor flag for enabling track events cropping based on this new packet, disabled by default
- Updates the chrome_reliable_range.sql metric to rely on this packet when it's present in the trace (computing the reliable range on an already cropped trace may produce incorrect results)

Bug: b/239830951
Change-Id: Ieea9c2bb3c90dde4325033864153093afe3a300c
diff --git a/Android.bp b/Android.bp
index 14c0e12..920be0f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -4887,6 +4887,7 @@
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
         "protos/perfetto/trace/track_event/process_descriptor.proto",
+        "protos/perfetto/trace/track_event/range_of_interest.proto",
         "protos/perfetto/trace/track_event/source_location.proto",
         "protos/perfetto/trace/track_event/task_execution.proto",
         "protos/perfetto/trace/track_event/thread_descriptor.proto",
@@ -7379,6 +7380,7 @@
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
         "protos/perfetto/trace/track_event/process_descriptor.proto",
+        "protos/perfetto/trace/track_event/range_of_interest.proto",
         "protos/perfetto/trace/track_event/source_location.proto",
         "protos/perfetto/trace/track_event/task_execution.proto",
         "protos/perfetto/trace/track_event/thread_descriptor.proto",
@@ -7411,6 +7413,7 @@
         "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.gen.cc",
         "external/perfetto/protos/perfetto/trace/track_event/log_message.gen.cc",
         "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.gen.cc",
+        "external/perfetto/protos/perfetto/trace/track_event/range_of_interest.gen.cc",
         "external/perfetto/protos/perfetto/trace/track_event/source_location.gen.cc",
         "external/perfetto/protos/perfetto/trace/track_event/task_execution.gen.cc",
         "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.gen.cc",
@@ -7443,6 +7446,7 @@
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
         "protos/perfetto/trace/track_event/process_descriptor.proto",
+        "protos/perfetto/trace/track_event/range_of_interest.proto",
         "protos/perfetto/trace/track_event/source_location.proto",
         "protos/perfetto/trace/track_event/task_execution.proto",
         "protos/perfetto/trace/track_event/thread_descriptor.proto",
@@ -7475,6 +7479,7 @@
         "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.gen.h",
         "external/perfetto/protos/perfetto/trace/track_event/log_message.gen.h",
         "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.gen.h",
+        "external/perfetto/protos/perfetto/trace/track_event/range_of_interest.gen.h",
         "external/perfetto/protos/perfetto/trace/track_event/source_location.gen.h",
         "external/perfetto/protos/perfetto/trace/track_event/task_execution.gen.h",
         "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.gen.h",
@@ -7511,6 +7516,7 @@
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
         "protos/perfetto/trace/track_event/process_descriptor.proto",
+        "protos/perfetto/trace/track_event/range_of_interest.proto",
         "protos/perfetto/trace/track_event/source_location.proto",
         "protos/perfetto/trace/track_event/task_execution.proto",
         "protos/perfetto/trace/track_event/thread_descriptor.proto",
@@ -7550,6 +7556,7 @@
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
         "protos/perfetto/trace/track_event/process_descriptor.proto",
+        "protos/perfetto/trace/track_event/range_of_interest.proto",
         "protos/perfetto/trace/track_event/source_location.proto",
         "protos/perfetto/trace/track_event/task_execution.proto",
         "protos/perfetto/trace/track_event/thread_descriptor.proto",
@@ -7581,6 +7588,7 @@
         "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pb.cc",
         "external/perfetto/protos/perfetto/trace/track_event/log_message.pb.cc",
         "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pb.cc",
+        "external/perfetto/protos/perfetto/trace/track_event/range_of_interest.pb.cc",
         "external/perfetto/protos/perfetto/trace/track_event/source_location.pb.cc",
         "external/perfetto/protos/perfetto/trace/track_event/task_execution.pb.cc",
         "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pb.cc",
@@ -7613,6 +7621,7 @@
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
         "protos/perfetto/trace/track_event/process_descriptor.proto",
+        "protos/perfetto/trace/track_event/range_of_interest.proto",
         "protos/perfetto/trace/track_event/source_location.proto",
         "protos/perfetto/trace/track_event/task_execution.proto",
         "protos/perfetto/trace/track_event/thread_descriptor.proto",
@@ -7644,6 +7653,7 @@
         "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pb.h",
         "external/perfetto/protos/perfetto/trace/track_event/log_message.pb.h",
         "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pb.h",
+        "external/perfetto/protos/perfetto/trace/track_event/range_of_interest.pb.h",
         "external/perfetto/protos/perfetto/trace/track_event/source_location.pb.h",
         "external/perfetto/protos/perfetto/trace/track_event/task_execution.pb.h",
         "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pb.h",
@@ -7680,6 +7690,7 @@
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
         "protos/perfetto/trace/track_event/process_descriptor.proto",
+        "protos/perfetto/trace/track_event/range_of_interest.proto",
         "protos/perfetto/trace/track_event/source_location.proto",
         "protos/perfetto/trace/track_event/task_execution.proto",
         "protos/perfetto/trace/track_event/thread_descriptor.proto",
@@ -7712,6 +7723,7 @@
         "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.cc",
         "external/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.cc",
         "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pbzero.cc",
+        "external/perfetto/protos/perfetto/trace/track_event/range_of_interest.pbzero.cc",
         "external/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.cc",
         "external/perfetto/protos/perfetto/trace/track_event/task_execution.pbzero.cc",
         "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pbzero.cc",
@@ -7744,6 +7756,7 @@
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
         "protos/perfetto/trace/track_event/process_descriptor.proto",
+        "protos/perfetto/trace/track_event/range_of_interest.proto",
         "protos/perfetto/trace/track_event/source_location.proto",
         "protos/perfetto/trace/track_event/task_execution.proto",
         "protos/perfetto/trace/track_event/thread_descriptor.proto",
@@ -7776,6 +7789,7 @@
         "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.h",
         "external/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.h",
         "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pbzero.h",
+        "external/perfetto/protos/perfetto/trace/track_event/range_of_interest.pbzero.h",
         "external/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.h",
         "external/perfetto/protos/perfetto/trace/track_event/task_execution.pbzero.h",
         "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pbzero.h",
@@ -7918,6 +7932,7 @@
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
         "protos/perfetto/trace/track_event/process_descriptor.proto",
+        "protos/perfetto/trace/track_event/range_of_interest.proto",
         "protos/perfetto/trace/track_event/source_location.proto",
         "protos/perfetto/trace/track_event/task_execution.proto",
         "protos/perfetto/trace/track_event/thread_descriptor.proto",
@@ -9770,6 +9785,7 @@
     name: "perfetto_src_trace_processor_stdlib_gen_amalgamated_stdlib",
     srcs: [
         "src/trace_processor/stdlib/android/binder.sql",
+        "src/trace_processor/stdlib/common/metadata.sql",
         "src/trace_processor/stdlib/experimental/android_broadcast.sql",
     ],
     cmd: "$(location tools/gen_amalgamated_sql.py) --namespace=stdlib --root-dir=src/trace_processor/stdlib --cpp-out=$(out) $(in)",
@@ -10920,6 +10936,7 @@
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
         "protos/perfetto/trace/track_event/process_descriptor.proto",
+        "protos/perfetto/trace/track_event/range_of_interest.proto",
         "protos/perfetto/trace/track_event/source_location.proto",
         "protos/perfetto/trace/track_event/task_execution.proto",
         "protos/perfetto/trace/track_event/thread_descriptor.proto",
diff --git a/BUILD b/BUILD
index ad4a35b..401bde9 100644
--- a/BUILD
+++ b/BUILD
@@ -1760,6 +1760,14 @@
     ],
 )
 
+# GN target: //src/trace_processor/stdlib/common:common
+perfetto_filegroup(
+    name = "src_trace_processor_stdlib_common_common",
+    srcs = [
+        "src/trace_processor/stdlib/common/metadata.sql",
+    ],
+)
+
 # GN target: //src/trace_processor/stdlib/experimental:experimental
 perfetto_filegroup(
     name = "src_trace_processor_stdlib_experimental_experimental",
@@ -1773,6 +1781,7 @@
     name = "src_trace_processor_stdlib_gen_amalgamated_stdlib",
     deps = [
         ":src_trace_processor_stdlib_android_android",
+        ":src_trace_processor_stdlib_common_common",
         ":src_trace_processor_stdlib_experimental_experimental",
     ],
     outs = [
@@ -4084,6 +4093,7 @@
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
         "protos/perfetto/trace/track_event/process_descriptor.proto",
+        "protos/perfetto/trace/track_event/range_of_interest.proto",
         "protos/perfetto/trace/track_event/source_location.proto",
         "protos/perfetto/trace/track_event/task_execution.proto",
         "protos/perfetto/trace/track_event/thread_descriptor.proto",
diff --git a/include/perfetto/trace_processor/basic_types.h b/include/perfetto/trace_processor/basic_types.h
index fd5539b..1aaac47 100644
--- a/include/perfetto/trace_processor/basic_types.h
+++ b/include/perfetto/trace_processor/basic_types.h
@@ -95,6 +95,18 @@
   kAllDataSourcesStarted = 2,
 };
 
+// Enum which encodes which timestamp source (if any) should be used to drop
+// track event data before this timestamp.
+enum class DropTrackEventDataBefore {
+  // Retain all track events. This is the default approach.
+  kNoDrop = 0,
+
+  // Drops track events before the timestamp specified by the
+  // TrackEventRangeOfInterest trace packet. No data is dropped if this packet
+  // is not present in the trace.
+  kTrackEventRangeOfInterest = 1,
+};
+
 // Struct for configuring a TraceProcessor instance (see trace_processor.h).
 struct PERFETTO_EXPORT_COMPONENT Config {
   // Indicates the sortinng mode that trace processor should use on the passed
@@ -116,6 +128,11 @@
   DropFtraceDataBefore drop_ftrace_data_before =
       DropFtraceDataBefore::kTracingStarted;
 
+  // Indicates the source of timestamp before which track events should be
+  // dropped. See the enum documentation for more details.
+  DropTrackEventDataBefore drop_track_event_data_before =
+      DropTrackEventDataBefore::kNoDrop;
+
   // Any built-in metric proto or sql files matching these paths are skipped
   // during trace processor metric initialization.
   std::vector<std::string> skip_builtin_metric_paths;
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 17d545b..ac61e36 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -11098,6 +11098,16 @@
 
 // End of protos/perfetto/trace/track_event/process_descriptor.proto
 
+// Begin of protos/perfetto/trace/track_event/range_of_interest.proto
+
+// This message specifies the "range of interest" for track events. With the
+// `drop_track_event_data_before` option set to `kTrackEventRangeOfInterest`,
+// Trace Processor drops track events outside of this range.
+message TrackEventRangeOfInterest {
+  optional int64 start_us = 1;
+}
+// End of protos/perfetto/trace/track_event/range_of_interest.proto
+
 // Begin of protos/perfetto/trace/track_event/thread_descriptor.proto
 
 // Describes a thread's attributes. Emitted as part of a TrackDescriptor,
@@ -11566,7 +11576,7 @@
 // See the [Buffers and Dataflow](/docs/concepts/buffers.md) doc for details.
 //
 // Next reserved id: 14 (up to 15).
-// Next id: 90.
+// Next id: 91.
 message TracePacket {
   // The timestamp of the TracePacket.
   // By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
@@ -11674,6 +11684,10 @@
     // Represents a single packet sent or received by the network.
     NetworkPacketEvent network_packet = 88;
 
+    // The "range of interest" for track events. See the message definition
+    // comments for more details.
+    TrackEventRangeOfInterest track_event_range_of_interest = 90;
+
     // This field is only used for testing.
     // In previous versions of this proto this field had the id 268435455
     // This caused many problems:
diff --git a/protos/perfetto/trace/trace_packet.proto b/protos/perfetto/trace/trace_packet.proto
index 50499d4..1df67bd 100644
--- a/protos/perfetto/trace/trace_packet.proto
+++ b/protos/perfetto/trace/trace_packet.proto
@@ -61,6 +61,7 @@
 import "protos/perfetto/trace/system_info/cpu_info.proto";
 import "protos/perfetto/trace/trace_packet_defaults.proto";
 import "protos/perfetto/trace/track_event/process_descriptor.proto";
+import "protos/perfetto/trace/track_event/range_of_interest.proto";
 import "protos/perfetto/trace/track_event/thread_descriptor.proto";
 import "protos/perfetto/trace/track_event/track_descriptor.proto";
 import "protos/perfetto/trace/track_event/track_event.proto";
@@ -92,7 +93,7 @@
 // See the [Buffers and Dataflow](/docs/concepts/buffers.md) doc for details.
 //
 // Next reserved id: 14 (up to 15).
-// Next id: 90.
+// Next id: 91.
 message TracePacket {
   // The timestamp of the TracePacket.
   // By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
@@ -200,6 +201,10 @@
     // Represents a single packet sent or received by the network.
     NetworkPacketEvent network_packet = 88;
 
+    // The "range of interest" for track events. See the message definition
+    // comments for more details.
+    TrackEventRangeOfInterest track_event_range_of_interest = 90;
+
     // This field is only used for testing.
     // In previous versions of this proto this field had the id 268435455
     // This caused many problems:
diff --git a/protos/perfetto/trace/track_event/BUILD.gn b/protos/perfetto/trace/track_event/BUILD.gn
index 5f53bf9..7dc1aad 100644
--- a/protos/perfetto/trace/track_event/BUILD.gn
+++ b/protos/perfetto/trace/track_event/BUILD.gn
@@ -36,6 +36,7 @@
     "debug_annotation.proto",
     "log_message.proto",
     "process_descriptor.proto",
+    "range_of_interest.proto",
     "source_location.proto",
     "task_execution.proto",
     "thread_descriptor.proto",
diff --git a/protos/perfetto/trace/track_event/range_of_interest.proto b/protos/perfetto/trace/track_event/range_of_interest.proto
new file mode 100644
index 0000000..2955f97
--- /dev/null
+++ b/protos/perfetto/trace/track_event/range_of_interest.proto
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+syntax = "proto2";
+
+package perfetto.protos;
+
+// This message specifies the "range of interest" for track events. With the
+// `drop_track_event_data_before` option set to `kTrackEventRangeOfInterest`,
+// Trace Processor drops track events outside of this range.
+message TrackEventRangeOfInterest {
+  optional int64 start_us = 1;
+}
\ No newline at end of file
diff --git a/src/trace_processor/importers/proto/track_event_module.cc b/src/trace_processor/importers/proto/track_event_module.cc
index 547bf3b..7197046 100644
--- a/src/trace_processor/importers/proto/track_event_module.cc
+++ b/src/trace_processor/importers/proto/track_event_module.cc
@@ -35,6 +35,7 @@
     : track_event_tracker_(new TrackEventTracker(context)),
       tokenizer_(context, track_event_tracker_.get()),
       parser_(context, track_event_tracker_.get()) {
+  RegisterForField(TracePacket::kTrackEventRangeOfInterestFieldNumber, context);
   RegisterForField(TracePacket::kTrackEventFieldNumber, context);
   RegisterForField(TracePacket::kTrackDescriptorFieldNumber, context);
   RegisterForField(TracePacket::kThreadDescriptorFieldNumber, context);
@@ -50,6 +51,9 @@
     PacketSequenceState* state,
     uint32_t field_id) {
   switch (field_id) {
+    case TracePacket::kTrackEventRangeOfInterestFieldNumber:
+      return tokenizer_.TokenizeRangeOfInterestPacket(state, decoder,
+                                                      packet_timestamp);
     case TracePacket::kTrackDescriptorFieldNumber:
       return tokenizer_.TokenizeTrackDescriptorPacket(state, decoder,
                                                       packet_timestamp);
diff --git a/src/trace_processor/importers/proto/track_event_parser.cc b/src/trace_processor/importers/proto/track_event_parser.cc
index c52e69b..c961057 100644
--- a/src/trace_processor/importers/proto/track_event_parser.cc
+++ b/src/trace_processor/importers/proto/track_event_parser.cc
@@ -1715,6 +1715,17 @@
                                        const TrackEventData* event_data,
                                        ConstBytes blob,
                                        uint32_t packet_sequence_id) {
+  const auto range_of_interest_start_us =
+      track_event_tracker_->range_of_interest_start_us();
+  if (context_->config.drop_track_event_data_before ==
+          DropTrackEventDataBefore::kTrackEventRangeOfInterest &&
+      range_of_interest_start_us && ts < *range_of_interest_start_us) {
+    // The event is outside of the range of interest, and dropping is enabled.
+    // So we drop the event.
+    context_->storage->IncrementStats(
+        stats::track_event_dropped_packets_outside_of_range_of_interest);
+    return;
+  }
   util::Status status =
       EventImporter(this, ts, event_data, std::move(blob), packet_sequence_id)
           .Import();
diff --git a/src/trace_processor/importers/proto/track_event_tokenizer.cc b/src/trace_processor/importers/proto/track_event_tokenizer.cc
index 331696d..1f6218f 100644
--- a/src/trace_processor/importers/proto/track_event_tokenizer.cc
+++ b/src/trace_processor/importers/proto/track_event_tokenizer.cc
@@ -21,6 +21,7 @@
 #include "src/trace_processor/importers/common/clock_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/track_tracker.h"
+#include "src/trace_processor/importers/proto/metadata_tracker.h"
 #include "src/trace_processor/importers/proto/packet_sequence_state.h"
 #include "src/trace_processor/importers/proto/proto_trace_reader.h"
 #include "src/trace_processor/importers/proto/track_event_tracker.h"
@@ -34,6 +35,7 @@
 #include "protos/perfetto/trace/track_event/chrome_thread_descriptor.pbzero.h"
 #include "protos/perfetto/trace/track_event/counter_descriptor.pbzero.h"
 #include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
+#include "protos/perfetto/trace/track_event/range_of_interest.pbzero.h"
 #include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
 #include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
 #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
@@ -54,6 +56,23 @@
       counter_name_thread_instruction_count_id_(
           context_->storage->InternString("thread_instruction_count")) {}
 
+ModuleResult TrackEventTokenizer::TokenizeRangeOfInterestPacket(
+    PacketSequenceState* /*state*/,
+    const protos::pbzero::TracePacket::Decoder& packet,
+    int64_t /*packet_timestamp*/) {
+  protos::pbzero::TrackEventRangeOfInterest::Decoder range_of_interest(
+      packet.track_event_range_of_interest());
+  if (!range_of_interest.has_start_us()) {
+    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+    return ModuleResult::Handled();
+  }
+  track_event_tracker_->SetRangeOfInterestStartUs(range_of_interest.start_us());
+  context_->metadata_tracker->SetMetadata(
+      metadata::range_of_interest_start_us,
+      Variadic::Integer(range_of_interest.start_us()));
+  return ModuleResult::Handled();
+}
+
 ModuleResult TrackEventTokenizer::TokenizeTrackDescriptorPacket(
     PacketSequenceState* state,
     const protos::pbzero::TracePacket::Decoder& packet,
diff --git a/src/trace_processor/importers/proto/track_event_tokenizer.h b/src/trace_processor/importers/proto/track_event_tokenizer.h
index 0dc41f8..010bc87 100644
--- a/src/trace_processor/importers/proto/track_event_tokenizer.h
+++ b/src/trace_processor/importers/proto/track_event_tokenizer.h
@@ -46,6 +46,10 @@
  public:
   explicit TrackEventTokenizer(TraceProcessorContext*, TrackEventTracker*);
 
+  ModuleResult TokenizeRangeOfInterestPacket(
+      PacketSequenceState* state,
+      const protos::pbzero::TracePacket_Decoder&,
+      int64_t packet_timestamp);
   ModuleResult TokenizeTrackDescriptorPacket(
       PacketSequenceState* state,
       const protos::pbzero::TracePacket_Decoder&,
diff --git a/src/trace_processor/importers/proto/track_event_tracker.h b/src/trace_processor/importers/proto/track_event_tracker.h
index c0307d6..6664599 100644
--- a/src/trace_processor/importers/proto/track_event_tracker.h
+++ b/src/trace_processor/importers/proto/track_event_tracker.h
@@ -132,6 +132,14 @@
 
   void OnFirstPacketOnSequence(uint32_t packet_sequence_id);
 
+  void SetRangeOfInterestStartUs(int64_t range_of_interest_start_us) {
+    range_of_interest_start_us_ = range_of_interest_start_us;
+  }
+
+  base::Optional<int64_t> range_of_interest_start_us() const {
+    return range_of_interest_start_us_;
+  }
+
  private:
   struct DescriptorTrackReservation {
     uint64_t parent_uuid = 0;
@@ -240,6 +248,8 @@
 
   const StringId default_descriptor_track_name_ = kNullStringId;
 
+  base::Optional<int64_t> range_of_interest_start_us_;
+
   TraceProcessorContext* const context_;
 };
 
diff --git a/src/trace_processor/metrics/sql/chrome/chrome_reliable_range.sql b/src/trace_processor/metrics/sql/chrome/chrome_reliable_range.sql
index de1c510..81c31dd 100644
--- a/src/trace_processor/metrics/sql/chrome/chrome_reliable_range.sql
+++ b/src/trace_processor/metrics/sql/chrome/chrome_reliable_range.sql
@@ -19,6 +19,7 @@
 -- 3. The "reliable range" is an intersection of reliable thread ranges for all threads such that:
 --   a. The number of events on the thread is at or above 25p.
 --   b. The event rate for the thread is at or above 75p.
+SELECT IMPORT('common.metadata');
 
 DROP VIEW IF EXISTS chrome_event_stats_per_thread;
 
@@ -113,10 +114,15 @@
 CREATE VIEW chrome_reliable_range
 AS
 SELECT
-  MAX(thread_start, data_loss_free_start) AS start,
-  IIF(thread_start >= data_loss_free_start,
-      'First slice for utid=' || limiting_utid,
-      'Missing process data for upid=' || limiting_upid) AS reason,
+  -- If the trace has a cropping packet, we don't want to recompute the reliable
+  -- based on cropped track events - the result might be incorrect.g
+  IFNULL(EXTRACT_INT_METADATA('range_of_interest_start_us'),
+         MAX(thread_start, data_loss_free_start)) AS start,
+  IIF(EXTRACT_INT_METADATA('range_of_interest_start_us') IS NOT NULL,
+      'Range of interest packet',
+      IIF(thread_start >= data_loss_free_start,
+          'First slice for utid=' || limiting_utid,
+          'Missing process data for upid=' || limiting_upid)) AS reason,
   limiting_upid AS debug_limiting_upid,
   limiting_utid AS debug_limiting_utid
 FROM
diff --git a/src/trace_processor/stdlib/BUILD.gn b/src/trace_processor/stdlib/BUILD.gn
index 9b9d470..970605b 100644
--- a/src/trace_processor/stdlib/BUILD.gn
+++ b/src/trace_processor/stdlib/BUILD.gn
@@ -20,6 +20,7 @@
 perfetto_amalgamated_sql_header("gen_amalgamated_stdlib") {
   deps = [
     "android",
+    "common",
     "experimental",
   ]
   generated_header = "amalgamated_stdlib.h"
diff --git a/src/trace_processor/stdlib/common/BUILD.gn b/src/trace_processor/stdlib/common/BUILD.gn
new file mode 100644
index 0000000..adebbd4
--- /dev/null
+++ b/src/trace_processor/stdlib/common/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright (C) 2022 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.
+
+import("../../../../gn/perfetto_sql.gni")
+
+perfetto_sql_source_set("common") {
+  sources = [ "metadata.sql" ]
+}
diff --git a/src/trace_processor/stdlib/common/metadata.sql b/src/trace_processor/stdlib/common/metadata.sql
new file mode 100644
index 0000000..82312da
--- /dev/null
+++ b/src/trace_processor/stdlib/common/metadata.sql
@@ -0,0 +1,24 @@
+--
+-- Copyright 2022 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
+--
+--     https://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.
+--
+
+-- Extracts an int value with the given name from the metadata table.
+--
+-- @arg name STRING The name of the metadata entry.
+-- @res LONG int_value for the given name. NULL if there's no such entry.
+SELECT CREATE_FUNCTION(
+    'EXTRACT_INT_METADATA(name STRING)',
+    'LONG',
+    'SELECT int_value FROM metadata WHERE name = ($name)');
diff --git a/src/trace_processor/storage/metadata.h b/src/trace_processor/storage/metadata.h
index 7040f68..de2e651 100644
--- a/src/trace_processor/storage/metadata.h
+++ b/src/trace_processor/storage/metadata.h
@@ -42,6 +42,7 @@
   F(benchmark_story_run_time_us,       KeyType::kSingle,  Variadic::kInt),    \
   F(benchmark_story_tags,              KeyType::kMulti,   Variadic::kString), \
   F(ftrace_setup_errors,               KeyType::kMulti,   Variadic::kString), \
+  F(range_of_interest_start_us,        KeyType::kSingle,  Variadic::kInt),    \
   F(statsd_triggering_subscription_id, KeyType::kSingle,  Variadic::kInt),    \
   F(system_machine,                    KeyType::kSingle,  Variadic::kString), \
   F(system_name,                       KeyType::kSingle,  Variadic::kString), \
diff --git a/src/trace_processor/storage/stats.h b/src/trace_processor/storage/stats.h
index 78605df..430b1ab 100644
--- a/src/trace_processor/storage/stats.h
+++ b/src/trace_processor/storage/stats.h
@@ -134,6 +134,12 @@
   F(traced_total_buffers,               kSingle,  kInfo,     kTrace,    ""),   \
   F(traced_tracing_sessions,            kSingle,  kInfo,     kTrace,    ""),   \
   F(track_event_parser_errors,          kSingle,  kInfo,     kAnalysis, ""),   \
+  F(track_event_dropped_packets_outside_of_range_of_interest,                  \
+                                        kSingle,  kInfo,     kAnalysis,        \
+      "The number of TrackEvent packets dropped by trace processor due to "    \
+      "being outside of the range of interest. This happens if a trace has a " \
+      "TrackEventRangeOfInterest packet, and track event dropping is "         \
+      "enabled."),                                                             \
   F(track_event_tokenizer_errors,       kSingle,  kInfo,     kAnalysis, ""),   \
   F(track_event_thread_invalid_end,     kSingle,  kError,    kTrace,           \
       "The end event for a thread track does not match a track event "         \
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index 67b211c..97e548a 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -704,6 +704,7 @@
   bool dev = false;
   bool no_ftrace_raw = false;
   bool analyze_trace_proto_content = false;
+  bool crop_track_events = false;
 };
 
 void PrintUsage(char** argv) {
@@ -775,7 +776,9 @@
                                       processor when loading traces containing
                                       ftrace events.
 --analyze-trace-proto-content         Enables trace proto content analysis in
-                                      trace processor.)",
+                                      trace processor.
+--crop-track-events                   Ignores track event outside of the
+                                      range of interest in trace processor.)",
                 argv[0]);
 }
 
@@ -794,6 +797,7 @@
     OPT_METATRACE_BUFFER_CAPACITY,
     OPT_METATRACE_CATEGORIES,
     OPT_ANALYZE_TRACE_PROTO_CONTENT,
+    OPT_CROP_TRACK_EVENTS,
   };
 
   static const option long_options[] = {
@@ -822,6 +826,7 @@
       {"no-ftrace-raw", no_argument, nullptr, OPT_NO_FTRACE_RAW},
       {"analyze-trace-proto-content", no_argument, nullptr,
        OPT_ANALYZE_TRACE_PROTO_CONTENT},
+      {"crop-track-events", no_argument, nullptr, OPT_CROP_TRACK_EVENTS},
       {nullptr, 0, nullptr, 0}};
 
   bool explicit_interactive = false;
@@ -945,6 +950,11 @@
       continue;
     }
 
+    if (option == OPT_CROP_TRACK_EVENTS) {
+      command_line_options.crop_track_events = true;
+      continue;
+    }
+
     PrintUsage(argv);
     exit(option == 'h' ? 0 : 1);
   }
@@ -1433,6 +1443,10 @@
                             : SortingMode::kDefaultHeuristics;
   config.ingest_ftrace_in_raw_table = !options.no_ftrace_raw;
   config.analyze_trace_proto_content = options.analyze_trace_proto_content;
+  config.drop_track_event_data_before =
+      options.crop_track_events
+          ? DropTrackEventDataBefore::kTrackEventRangeOfInterest
+          : DropTrackEventDataBefore::kNoDrop;
 
   std::vector<MetricExtension> metric_extensions;
   RETURN_IF_ERROR(ParseMetricExtensionPaths(
diff --git a/test/trace_processor/chrome/chrome_reliable_range_cropping.out b/test/trace_processor/chrome/chrome_reliable_range_cropping.out
new file mode 100644
index 0000000..2b3eafe
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_reliable_range_cropping.out
@@ -0,0 +1,3 @@
+
+"start","reason","debug_limiting_upid","debug_limiting_utid"
+10,"Range of interest packet","[NULL]",2
diff --git a/test/trace_processor/chrome/chrome_reliable_range_cropping.textproto b/test/trace_processor/chrome/chrome_reliable_range_cropping.textproto
new file mode 100644
index 0000000..f681217
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_reliable_range_cropping.textproto
@@ -0,0 +1,113 @@
+# This test is similar to chrome_reliable_range.textproto, but it has a cropping
+# packet, which takes precedence.
+
+packet {
+  timestamp: 0
+  trusted_packet_sequence_id: 1
+  incremental_state_cleared: true
+  track_event_range_of_interest {
+    start_us: 10
+  }
+}
+
+# Track descriptors for each thread.
+packet {
+  timestamp: 1
+  trusted_packet_sequence_id: 1
+  track_descriptor {
+    uuid: 1
+    thread {
+      pid: 1
+      tid: 1
+    }
+    parent_uuid: 0
+  }
+}
+packet {
+  timestamp: 2
+  incremental_state_cleared: true
+  trusted_packet_sequence_id: 2
+  track_descriptor {
+    uuid: 2
+    thread {
+      pid: 2
+      tid: 2
+    }
+    parent_uuid: 0
+  }
+}
+packet {
+  timestamp: 3
+  incremental_state_cleared: true
+  first_packet_on_sequence: true
+  trusted_packet_sequence_id: 3
+  track_descriptor {
+    uuid: 3
+    thread {
+      pid: 3
+      tid: 3
+    }
+    parent_uuid: 0
+  }
+}
+
+# Slice begin events
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 11
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    type: 1
+    name: "slice1"
+  }
+}
+packet {
+  trusted_packet_sequence_id: 2
+  timestamp: 12
+  track_event {
+    track_uuid: 2
+    categories: "cat"
+    type: 1
+    name: "slice1"
+  }
+}
+packet {
+  trusted_packet_sequence_id: 3
+  timestamp: 13
+  track_event {
+    track_uuid: 3
+    categories: "cat"
+    type: 1
+    name: "slice3"
+  }
+}
+
+# Slice end events
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 1011
+  track_event {
+    track_uuid: 1
+    categories: "cat"
+    type: 2
+  }
+}
+packet {
+  trusted_packet_sequence_id: 2
+  timestamp: 1012
+  track_event {
+    track_uuid: 2
+    categories: "cat"
+    type: 2
+  }
+}
+packet {
+  trusted_packet_sequence_id: 3
+  timestamp: 1013
+  track_event {
+    track_uuid: 3
+    categories: "cat"
+    type: 2
+  }
+}
\ No newline at end of file
diff --git a/test/trace_processor/chrome/index b/test/trace_processor/chrome/index
index fef528c..dce31ec 100644
--- a/test/trace_processor/chrome/index
+++ b/test/trace_processor/chrome/index
@@ -76,6 +76,7 @@
 
 # Chrome reliable range
 chrome_reliable_range.textproto chrome_reliable_range_test.sql chrome_reliable_range.out
+chrome_reliable_range_cropping.textproto chrome_reliable_range_test.sql chrome_reliable_range_cropping.out
 chrome_reliable_range_missing_processes.textproto chrome_reliable_range_test.sql chrome_reliable_range_missing_processes.out
 
 # Chrome slices
diff --git a/test/trace_processor/track_event/index b/test/trace_processor/track_event/index
index 24b6703..9c5cdba 100644
--- a/test/trace_processor/track_event/index
+++ b/test/trace_processor/track_event/index
@@ -45,3 +45,6 @@
 
 # Descriptor merging regression test (bug: b/197203390)
 ../../data/trace_with_descriptor.pftrace merging_regression_test.sql merging_regression.out
+
+# Range of interest
+range_of_interest.textproto range_of_interest_test.sql range_of_interest.out
diff --git a/test/trace_processor/track_event/range_of_interest.out b/test/trace_processor/track_event/range_of_interest.out
new file mode 100644
index 0000000..6ec06ed
--- /dev/null
+++ b/test/trace_processor/track_event/range_of_interest.out
@@ -0,0 +1,3 @@
+"ts","name"
+12,"slice3"
+13,"slice4"
diff --git a/test/trace_processor/track_event/range_of_interest.textproto b/test/trace_processor/track_event/range_of_interest.textproto
new file mode 100644
index 0000000..f02c773
--- /dev/null
+++ b/test/trace_processor/track_event/range_of_interest.textproto
@@ -0,0 +1,117 @@
+packet {
+  timestamp: 0
+  trusted_packet_sequence_id: 1
+  incremental_state_cleared: true
+  track_event_range_of_interest {
+    start_us: 12
+  }
+}
+
+# Track for slice begin/end events.
+packet {
+  timestamp: 0
+  trusted_packet_sequence_id: 1
+  track_descriptor {
+    uuid: 12345
+    thread {
+      pid: 123
+      tid: 345
+    }
+    parent_uuid: 0
+    chrome_thread {
+      thread_type: THREAD_POOL_FG_WORKER
+    }
+  }
+}
+
+# Slice begins. The first two slices starts before the range of interest, the
+
+# rest are in the range.
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 10
+  track_event {
+    track_uuid: 12345
+    categories: "cat1"
+    type: 1
+    name: "slice1"
+  }
+}
+
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 11
+  track_event {
+    track_uuid: 12345
+    categories: "cat1"
+    type: 1
+    name: "slice2"
+  }
+}
+
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 12
+  track_event {
+    track_uuid: 12345
+    categories: "cat1"
+    type: 1
+    name: "slice3"
+  }
+}
+
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 13
+  track_event {
+    track_uuid: 12345
+    categories: "cat1"
+    type: 1
+    name: "slice4"
+  }
+}
+
+# Slice ends
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 6000
+  track_event {
+    track_uuid: 12345
+    categories: "cat1"
+    name: "slice4"
+    type: 2
+  }
+}
+
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 6001
+  track_event {
+    track_uuid: 12345
+    categories: "cat1"
+    name: "slice2"
+    type: 2
+  }
+}
+
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 6002
+  track_event {
+    track_uuid: 12345
+    categories: "cat1"
+    name: "slice2"
+    type: 2
+  }
+}
+
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 6003
+  track_event {
+    track_uuid: 12345
+    categories: "cat1"
+    name: "slice1"
+    type: 2
+  }
+}
diff --git a/test/trace_processor/track_event/range_of_interest_test.sql b/test/trace_processor/track_event/range_of_interest_test.sql
new file mode 100644
index 0000000..8e761c2
--- /dev/null
+++ b/test/trace_processor/track_event/range_of_interest_test.sql
@@ -0,0 +1,18 @@
+--
+-- Copyright 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
+--
+--     https://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.
+
+SELECT ts, name
+FROM slice
+ORDER BY ts;
\ No newline at end of file
diff --git a/tools/diff_test_trace_processor.py b/tools/diff_test_trace_processor.py
index cb13573..3f49af1 100755
--- a/tools/diff_test_trace_processor.py
+++ b/tools/diff_test_trace_processor.py
@@ -124,6 +124,7 @@
   cmd = [
       trace_processor_path,
       '--analyze-trace-proto-content',
+      '--crop-track-events',
       '--run-metrics',
       metric,
       '--metrics-output=%s' % ('json' if json_output else 'binary'),
@@ -165,6 +166,7 @@
   cmd = [
       trace_processor_path,
       '--analyze-trace-proto-content',
+      '--crop-track-events',
       '-q',
       query_path,
       '--perf-file',