Merge "TrackEvent: Add entry point for track+timestamp+lambda"
diff --git a/include/perfetto/tracing/internal/track_event_data_source.h b/include/perfetto/tracing/internal/track_event_data_source.h
index e6310a5..1bdffec 100644
--- a/include/perfetto/tracing/internal/track_event_data_source.h
+++ b/include/perfetto/tracing/internal/track_event_data_source.h
@@ -150,6 +150,7 @@
   // - Two debug annotations
   // - Track
   // - Track + Lambda
+  // - Track + Lambda + timestamp
   // - Track + one debug annotation
   // - Track + two debug annotations
 
@@ -237,6 +238,27 @@
         TrackEventInternal::GetTimeNs(), std::move(arg_function));
   }
 
+  // Trace point with a track, a lambda function and an overridden timestamp.
+  // |timestamp| must be in nanoseconds in the trace clock timebase.
+  template <size_t CategoryIndex,
+            typename TrackType,
+            typename CategoryType,
+            typename ArgumentFunction = void (*)(EventContext),
+            typename ArgumentFunctionCheck = typename std::enable_if<
+                IsValidTraceLambda<ArgumentFunction>()>::type>
+  static void TraceForCategory(uint32_t instances,
+                               const CategoryType& dynamic_category,
+                               const char* event_name,
+                               perfetto::protos::pbzero::TrackEvent::Type type,
+                               const TrackType& track,
+                               uint64_t timestamp,
+                               ArgumentFunction arg_function)
+      PERFETTO_NO_INLINE {
+    TraceForCategoryImpl<CategoryIndex>(instances, dynamic_category, event_name,
+                                        type, track, timestamp,
+                                        std::move(arg_function));
+  }
+
   // Trace point with one debug annotation.
   //
   // This type of trace point is implemented with an inner helper function which
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index 773965a..b398d52 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -1215,6 +1215,55 @@
   perfetto::TrackEvent::EraseTrackDescriptor(track);
 }
 
+TEST_F(PerfettoApiTest, TrackEventCustomTrackAndTimestamp) {
+  // Create a new trace session.
+  auto* tracing_session = NewTraceWithCategories({"bar"});
+  tracing_session->get()->StartBlocking();
+
+  // Custom track.
+  perfetto::Track track(789);
+
+  auto empty_lambda = [](perfetto::EventContext) {};
+  constexpr uint64_t kBeginEventTime = 10;
+  constexpr uint64_t kEndEventTime = 15;
+  TRACE_EVENT_BEGIN("bar", "Event", track, kBeginEventTime, empty_lambda);
+  TRACE_EVENT_END("bar", track, kEndEventTime, empty_lambda);
+
+  constexpr uint64_t kInstantEventTime = 1;
+  TRACE_EVENT_INSTANT("bar", "InstantEvent", track, kInstantEventTime,
+                      empty_lambda);
+
+  perfetto::TrackEvent::Flush();
+  tracing_session->get()->StopBlocking();
+
+  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+  perfetto::protos::gen::Trace trace;
+  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+
+  int event_count = 0;
+  for (const auto& packet : trace.packet()) {
+    if (!packet.has_track_event())
+      continue;
+    event_count++;
+    switch (packet.track_event().type()) {
+      case perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN:
+        EXPECT_EQ(packet.timestamp(), kBeginEventTime);
+        break;
+      case perfetto::protos::gen::TrackEvent::TYPE_SLICE_END:
+        EXPECT_EQ(packet.timestamp(), kEndEventTime);
+        break;
+      case perfetto::protos::gen::TrackEvent::TYPE_INSTANT:
+        EXPECT_EQ(packet.timestamp(), kInstantEventTime);
+        break;
+      case perfetto::protos::gen::TrackEvent::TYPE_COUNTER:
+      case perfetto::protos::gen::TrackEvent::TYPE_UNSPECIFIED:
+        ADD_FAILURE();
+    }
+  }
+  EXPECT_EQ(event_count, 3);
+  perfetto::TrackEvent::EraseTrackDescriptor(track);
+}
+
 TEST_F(PerfettoApiTest, TrackEventAnonymousCustomTrack) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"bar"});