Revert "perfetto: Split COMPLETE events into BEGIN/END pairs"

This reverts commit 4da1652655a4cc8038e2c7fe60fad09cb27e006c.

Reason for revert: crbug.com/1026658

Original change's description:
> perfetto: Split COMPLETE events into BEGIN/END pairs
> 
> There are a few reasons why this is desirable:
> (1) Reduces need for complete event stack in ThreadLocalEventSinks,
>     which was brittle before (e.g. crbug.com/983307).
> (2) Makes it possible to flush event sinks while tracing in the future
>     without losing not-yet-completed COMPLETE events from the stack
>     (streamed tracing use case). Events that didn't end before the
>     flush will still be present in the trace as BEGIN only.
> (3) Prevents reordering of nested COMPLETE events - something which
>     could confuse TraceProcessor in the past (events with identical
>     begin timestamps would be imported incorrectly).
> 
> To achieve this, this patch also plumbs the EXPLICIT_TIMESTAMP flag
> and thread id through to TraceLog::UpdateTraceEventDurationExplicit,
> because it seems that android can add COMPLETE events with explicit
> timestamps / threads [1].
> 
> [1] https://cs.chromium.org/chromium/src/base/android/early_trace_event_binding.cc?q=INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMPS&ss=chromium&l=31
> 
> Bug: 983307, 928738, 1006770
> Change-Id: I66e685c04c068646d550f182185d3c45febcbfa8
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1899852
> Commit-Queue: Eric Seckler <eseckler@chromium.org>
> Reviewed-by: oysteine <oysteine@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#716871}

TBR=oysteine@chromium.org,eseckler@chromium.org

Change-Id: I8056e483b439796eed90feaaa09434f7f63d1124
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 983307, 928738, 1006770, 1026658
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1927034
Reviewed-by: Eric Seckler <eseckler@chromium.org>
Commit-Queue: Eric Seckler <eseckler@chromium.org>
Cr-Commit-Position: refs/heads/master@{#717158}
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
index df910294..08f8ea80 100644
--- a/base/trace_event/trace_event.h
+++ b/base/trace_event/trace_event.h
@@ -174,11 +174,8 @@
 //     const unsigned char* category_group_enabled,
 //     const char* name,
 //     base::trace_event::TraceEventHandle id,
-//     int thread_id,
-//     bool explicit_timestamps,
-//     const base::TimeTicks& now,
-//     const base::ThreadTicks& thread_now,
-//     base::trace_event::ThreadInstructionCount thread_instruction_now)
+//     const TimeTicks& now,
+//     const ThreadTicks* thread_now)
 #define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION_EXPLICIT \
   trace_event_internal::UpdateTraceEventDurationExplicit
 
@@ -382,29 +379,28 @@
 
 // Implementation detail: internal macro to create static category and add
 // event if the category is enabled.
-#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMPS(                 \
-    category_group, name, id, thread_id, begin_timestamp, end_timestamp,     \
-    thread_end_timestamp, flags, ...)                                        \
-  do {                                                                       \
-    INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group);                  \
-    if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) {                     \
-      trace_event_internal::TraceID trace_event_trace_id((id));              \
-      unsigned int trace_event_flags =                                       \
-          flags | trace_event_trace_id.id_flags();                           \
-      const unsigned char* uid_category_group_enabled =                      \
-          INTERNAL_TRACE_EVENT_UID(category_group_enabled);                  \
-      auto handle =                                                          \
-          trace_event_internal::AddTraceEventWithThreadIdAndTimestamp(       \
-              TRACE_EVENT_PHASE_COMPLETE, uid_category_group_enabled, name,  \
-              trace_event_trace_id.scope(), trace_event_trace_id.raw_id(),   \
-              thread_id, begin_timestamp,                                    \
-              trace_event_flags | TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP,       \
-              trace_event_internal::kNoId, ##__VA_ARGS__);                   \
-      TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION_EXPLICIT(                  \
-          uid_category_group_enabled, name, handle, thread_id,               \
-          /*explicit_timestamps=*/true, end_timestamp, thread_end_timestamp, \
-          base::trace_event::ThreadInstructionCount());                      \
-    }                                                                        \
+#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMPS(                  \
+    category_group, name, id, thread_id, begin_timestamp, end_timestamp,      \
+    thread_end_timestamp, flags, ...)                                         \
+  do {                                                                        \
+    INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group);                   \
+    if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) {                      \
+      trace_event_internal::TraceID trace_event_trace_id((id));               \
+      unsigned int trace_event_flags =                                        \
+          flags | trace_event_trace_id.id_flags();                            \
+      const unsigned char* uid_category_group_enabled =                       \
+          INTERNAL_TRACE_EVENT_UID(category_group_enabled);                   \
+      auto handle =                                                           \
+          trace_event_internal::AddTraceEventWithThreadIdAndTimestamp(        \
+              TRACE_EVENT_PHASE_COMPLETE, uid_category_group_enabled, name,   \
+              trace_event_trace_id.scope(), trace_event_trace_id.raw_id(),    \
+              thread_id, begin_timestamp,                                     \
+              trace_event_flags | TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP,        \
+              trace_event_internal::kNoId, ##__VA_ARGS__);                    \
+      TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION_EXPLICIT(                   \
+          uid_category_group_enabled, name, handle, end_timestamp,            \
+          thread_end_timestamp, base::trace_event::ThreadInstructionCount()); \
+    }                                                                         \
   } while (0)
 
 // The linked ID will not be mangled.
@@ -721,8 +717,6 @@
     const unsigned char* category_group_enabled,
     const char* name,
     base::trace_event::TraceEventHandle handle,
-    int thread_id,
-    bool explicit_timestamps,
     const base::TimeTicks& now,
     const base::ThreadTicks& thread_now,
     base::trace_event::ThreadInstructionCount thread_instruction_now);
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc
index f785ef3..1e0cd14 100644
--- a/base/trace_event/trace_log.cc
+++ b/base/trace_event/trace_log.cc
@@ -1405,19 +1405,15 @@
   if (!category_group_enabled_local)
     return;
 
-  UpdateTraceEventDurationExplicit(
-      category_group_enabled, name, handle,
-      static_cast<int>(base::PlatformThread::CurrentId()),
-      /*explicit_timestamps=*/false, OffsetNow(), ThreadNow(),
-      ThreadInstructionNow());
+  UpdateTraceEventDurationExplicit(category_group_enabled, name, handle,
+                                   OffsetNow(), ThreadNow(),
+                                   ThreadInstructionNow());
 }
 
 void TraceLog::UpdateTraceEventDurationExplicit(
     const unsigned char* category_group_enabled,
     const char* name,
     TraceEventHandle handle,
-    int thread_id,
-    bool explicit_timestamps,
     const TimeTicks& now,
     const ThreadTicks& thread_now,
     ThreadInstructionCount thread_instruction_now) {
@@ -1442,9 +1438,7 @@
     auto update_duration_override =
         update_duration_override_.load(std::memory_order_relaxed);
     if (update_duration_override) {
-      update_duration_override(category_group_enabled, name, handle, thread_id,
-                               explicit_timestamps, now, thread_now,
-                               thread_instruction_now);
+      update_duration_override(handle, now, thread_now, thread_instruction_now);
       return;
     }
   }
@@ -1822,15 +1816,13 @@
     const unsigned char* category_group_enabled,
     const char* name,
     base::trace_event::TraceEventHandle handle,
-    int thread_id,
-    bool explicit_timestamps,
     const base::TimeTicks& now,
     const base::ThreadTicks& thread_now,
     base::trace_event::ThreadInstructionCount thread_instruction_now) {
   return base::trace_event::TraceLog::GetInstance()
       ->UpdateTraceEventDurationExplicit(category_group_enabled, name, handle,
-                                         thread_id, explicit_timestamps, now,
-                                         thread_now, thread_instruction_now);
+                                         now, thread_now,
+                                         thread_instruction_now);
 }
 
 ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient(
diff --git a/base/trace_event/trace_log.h b/base/trace_event/trace_log.h
index 6b877179..e0c850ca 100644
--- a/base/trace_event/trace_log.h
+++ b/base/trace_event/trace_log.h
@@ -201,11 +201,7 @@
                                                  TraceEventHandle* handle);
   using OnFlushFunction = void (*)();
   using UpdateDurationFunction =
-      void (*)(const unsigned char* category_group_enabled,
-               const char* name,
-               TraceEventHandle handle,
-               int thread_id,
-               bool explicit_timestamps,
+      void (*)(TraceEventHandle handle,
                const TimeTicks& now,
                const ThreadTicks& thread_now,
                ThreadInstructionCount thread_instruction_now);
@@ -296,8 +292,6 @@
       const unsigned char* category_group_enabled,
       const char* name,
       TraceEventHandle handle,
-      int thread_id,
-      bool explicit_timestamps,
       const TimeTicks& now,
       const ThreadTicks& thread_now,
       ThreadInstructionCount thread_instruction_now);
diff --git a/services/tracing/public/cpp/perfetto/thread_local_event_sink.h b/services/tracing/public/cpp/perfetto/thread_local_event_sink.h
index c4f32dd9..8435060 100644
--- a/services/tracing/public/cpp/perfetto/thread_local_event_sink.h
+++ b/services/tracing/public/cpp/perfetto/thread_local_event_sink.h
@@ -39,11 +39,7 @@
                              base::trace_event::TraceEventHandle* handle) = 0;
 
   virtual void UpdateDuration(
-      const unsigned char* category_group_enabled,
-      const char* name,
       base::trace_event::TraceEventHandle handle,
-      int thread_id,
-      bool explicit_timestamps,
       const base::TimeTicks& now,
       const base::ThreadTicks& thread_now,
       base::trace_event::ThreadInstructionCount thread_instruction_now) = 0;
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
index 34d20da9..24b29aa 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
@@ -884,11 +884,7 @@
 
 // static
 void TraceEventDataSource::OnUpdateDuration(
-    const unsigned char* category_group_enabled,
-    const char* name,
     base::trace_event::TraceEventHandle handle,
-    int thread_id,
-    bool explicit_timestamps,
     const base::TimeTicks& now,
     const base::ThreadTicks& thread_now,
     base::trace_event::ThreadInstructionCount thread_instruction_now) {
@@ -901,9 +897,8 @@
   auto* thread_local_event_sink =
       static_cast<ThreadLocalEventSink*>(ThreadLocalEventSinkSlot()->Get());
   if (thread_local_event_sink) {
-    thread_local_event_sink->UpdateDuration(
-        category_group_enabled, name, handle, thread_id, explicit_timestamps,
-        now, thread_now, thread_instruction_now);
+    thread_local_event_sink->UpdateDuration(handle, now, thread_now,
+                                            thread_instruction_now);
   }
 }
 
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.h b/services/tracing/public/cpp/perfetto/trace_event_data_source.h
index 6df3f78d..b5d22bf3 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source.h
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.h
@@ -210,11 +210,7 @@
                               bool thread_will_flush,
                               base::trace_event::TraceEventHandle* handle);
   static void OnUpdateDuration(
-      const unsigned char* category_group_enabled,
-      const char* name,
       base::trace_event::TraceEventHandle handle,
-      int thread_id,
-      bool explicit_timestamps,
       const base::TimeTicks& now,
       const base::ThreadTicks& thread_now,
       base::trace_event::ThreadInstructionCount thread_instruction_now);
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
index e28efaaa..99d4f19 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
@@ -335,13 +335,8 @@
       last_thread_time_ += packet->track_event().thread_time_delta_us();
     }
 
-    if (category_iid > 0) {
-      EXPECT_EQ(packet->track_event().category_iids_size(), 1);
-      EXPECT_EQ(packet->track_event().category_iids(0), category_iid);
-    } else {
-      EXPECT_EQ(packet->track_event().category_iids_size(), 0);
-    }
-
+    EXPECT_EQ(packet->track_event().category_iids_size(), 1);
+    EXPECT_EQ(packet->track_event().category_iids(0), category_iid);
     EXPECT_TRUE(packet->track_event().has_legacy_event());
 
     const auto& legacy_event = packet->track_event().legacy_event();
@@ -935,56 +930,44 @@
   trace_event_internal::TraceID trace_event_trace_id =
       trace_event_internal::kNoId;
 
-  // COMPLETE events are split into a BEGIN/END event pair. Adding the event
-  // writes the BEGIN event immediately.
   auto handle = trace_event_internal::AddTraceEventWithThreadIdAndTimestamp(
       TRACE_EVENT_PHASE_COMPLETE, category_group_enabled, kEventName,
       trace_event_trace_id.scope(), trace_event_trace_id.raw_id(),
-      /*thread_id=*/1,
+      1 /* thread_id */,
       base::TimeTicks() + base::TimeDelta::FromMicroseconds(10),
       trace_event_trace_id.id_flags() | TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP,
       trace_event_internal::kNoId);
 
-  EXPECT_EQ(producer_client()->GetFinalizedPacketCount(), 2u);
-  auto* b_packet = producer_client()->GetFinalizedPacket(1);
-  ExpectTraceEvent(
-      b_packet, /*category_iid=*/1u, /*name_iid=*/1u, TRACE_EVENT_PHASE_BEGIN,
-      TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP | TRACE_EVENT_FLAG_HAS_ID, /*id=*/0u,
-      /*absolute_timestamp=*/10, /*tid_override=*/1, /*pid_override=*/0);
-
-  // Updating the duration of the event as it goes out of scope results in the
-  // corresponding END event being written. These END events don't contain any
-  // event names or categories in the proto format.
   base::trace_event::TraceLog::GetInstance()->UpdateTraceEventDurationExplicit(
-      category_group_enabled, kEventName, handle, /*thread_id=*/1,
-      /*explicit_timestamps=*/true,
+      category_group_enabled, kEventName, handle,
       base::TimeTicks() + base::TimeDelta::FromMicroseconds(30),
       base::ThreadTicks() + base::TimeDelta::FromMicroseconds(50),
       base::trace_event::ThreadInstructionCount());
 
-  EXPECT_EQ(producer_client()->GetFinalizedPacketCount(), 3u);
-  auto* e_packet = producer_client()->GetFinalizedPacket(2);
+  // The call to UpdateTraceEventDurationExplicit should have successfully
+  // updated the duration of the event which was added in the
+  // AddTraceEventWithThreadIdAndTimestamp call.
+  EXPECT_EQ(producer_client()->GetFinalizedPacketCount(), 2u);
+  auto* e_packet = producer_client()->GetFinalizedPacket(1);
   ExpectTraceEvent(
-      e_packet, /*category_iid=*/0u, /*name_iid=*/0u, TRACE_EVENT_PHASE_END,
-      TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP, /*id=*/0u,
-      /*absolute_timestamp=*/30, /*tid_override=*/1, /*pid_override=*/0);
+      e_packet, /*category_iid=*/1u, /*name_iid=*/1u,
+      TRACE_EVENT_PHASE_COMPLETE,
+      TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP | TRACE_EVENT_FLAG_HAS_ID, /*id=*/0u,
+      /*absolute_timestamp=*/10, /*tid_override=*/1, /*pid_override=*/0,
+      /*duration=*/20);
 
-  // Updating the duration of an event that wasn't added before tracing begun
-  // will only emit an END event, again without category or name.
+  // Updating the duration of an invalid event should cause no further events to
+  // be emitted.
   handle.event_index = 0;
+
   base::trace_event::TraceLog::GetInstance()->UpdateTraceEventDurationExplicit(
-      category_group_enabled, "other_event_name", handle, /*thread_id=*/1,
-      /*explicit_timestamps=*/true,
-      base::TimeTicks() + base::TimeDelta::FromMicroseconds(40),
-      base::ThreadTicks() + base::TimeDelta::FromMicroseconds(60),
+      category_group_enabled, kEventName, handle,
+      base::TimeTicks() + base::TimeDelta::FromMicroseconds(30),
+      base::ThreadTicks() + base::TimeDelta::FromMicroseconds(50),
       base::trace_event::ThreadInstructionCount());
 
-  EXPECT_EQ(producer_client()->GetFinalizedPacketCount(), 4u);
-  auto* e2_packet = producer_client()->GetFinalizedPacket(3);
-  ExpectTraceEvent(
-      e2_packet, /*category_iid=*/0u, /*name_iid=*/0u, TRACE_EVENT_PHASE_END,
-      TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP, /*id=*/0u,
-      /*absolute_timestamp=*/40, /*tid_override=*/1, /*pid_override=*/0);
+  // No further packets should have been emitted.
+  EXPECT_EQ(producer_client()->GetFinalizedPacketCount(), 2u);
 }
 
 // TODO(eseckler): Add a test with multiple events + same strings (cat, name,
diff --git a/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc b/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc
index 2809fec8..2ca0914 100644
--- a/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc
+++ b/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc
@@ -38,6 +38,12 @@
 
 namespace {
 
+// To mark TraceEvent handles that have been added by Perfetto,
+// we use the chunk index so high that TraceLog would've asserted
+// at this point anyway.
+constexpr uint32_t kMagicChunkIndex =
+    base::trace_event::TraceBufferChunk::kMaxChunkIndex;
+
 // Replacement string for names of events with TRACE_EVENT_FLAG_COPY.
 const char* const kPrivacyFiltered = "PRIVACY_FILTERED";
 
@@ -181,12 +187,28 @@
 void TrackEventThreadLocalEventSink::AddTraceEvent(
     base::trace_event::TraceEvent* trace_event,
     base::trace_event::TraceEventHandle* handle) {
-  char phase = trace_event->phase();
+  // TODO(eseckler): Support splitting COMPLETE events into BEGIN/END pairs.
+  // For now, we emit them as legacy events so that the generated JSON trace
+  // size remains small.
+  if (handle && trace_event->phase() == TRACE_EVENT_PHASE_COMPLETE) {
+    // 'X' phase events are added through a scoped object and
+    // will have its duration updated when said object drops off
+    // the stack; keep a copy of the event around instead of
+    // writing it into SHM, until we have the duration.
+    // We can't keep the TraceEvent around in the scoped object
+    // itself as that causes a lot more codegen in the callsites
+    // and bloats the binary size too much (due to the increased
+    // sizeof() of the scoped object itself).
+    DCHECK_LT(current_stack_depth_, kMaxCompleteEventDepth);
+    if (current_stack_depth_ >= kMaxCompleteEventDepth) {
+      return;
+    }
 
-  // Split COMPLETE events into BEGIN/END pairs. We write the BEGIN here, and
-  // the END in UpdateDuration().
-  if (phase == TRACE_EVENT_PHASE_COMPLETE) {
-    phase = TRACE_EVENT_PHASE_BEGIN;
+    complete_event_stack_[current_stack_depth_] = std::move(*trace_event);
+    handle->event_index = ++current_stack_depth_;
+    handle->chunk_index = kMagicChunkIndex;
+    handle->chunk_seq = sink_id_;
+    return;
   }
 
   uint32_t flags = trace_event->flags();
@@ -209,14 +231,10 @@
 
   const char* category_name =
       TraceLog::GetCategoryGroupName(trace_event->category_group_enabled());
-  InterningIndexEntry interned_category{};
-  // Don't write the category for END events that were split from a COMPLETE
-  // event to save trace size.
-  if (handle || phase != TRACE_EVENT_PHASE_END) {
-    interned_category = interned_event_categories_.LookupOrAdd(category_name);
-  }
+  InterningIndexEntry interned_category =
+      interned_event_categories_.LookupOrAdd(category_name);
 
-  InterningIndexEntry interned_name{};
+  InterningIndexEntry interned_name;
   const size_t kMaxSize = base::trace_event::TraceArguments::kMaxSize;
   InterningIndexEntry interned_annotation_names[kMaxSize] = {
       InterningIndexEntry{}};
@@ -228,74 +246,69 @@
   const char* log_message_body = nullptr;
   int line_number = 0;
 
-  // Don't write the name or arguments for END events that were split from a
-  // COMPLETE event to save trace size.
-  if (handle || phase != TRACE_EVENT_PHASE_END) {
-    if (copy_strings) {
-      if (!is_java_event && privacy_filtering_enabled_) {
-        interned_name = interned_event_names_.LookupOrAdd(kPrivacyFiltered);
-      } else {
-        interned_name =
-            interned_event_names_.LookupOrAdd(std::string(trace_event->name()));
-        for (size_t i = 0;
-             i < trace_event->arg_size() && trace_event->arg_name(i); ++i) {
-          interned_annotation_names[i] = interned_annotation_names_.LookupOrAdd(
-              std::string(trace_event->arg_name(i)));
-        }
-      }
+  if (copy_strings) {
+    if (!is_java_event && privacy_filtering_enabled_) {
+      interned_name = interned_event_names_.LookupOrAdd(kPrivacyFiltered);
     } else {
-      interned_name = interned_event_names_.LookupOrAdd(trace_event->name());
+      interned_name =
+          interned_event_names_.LookupOrAdd(std::string(trace_event->name()));
+      for (size_t i = 0;
+           i < trace_event->arg_size() && trace_event->arg_name(i); ++i) {
+        interned_annotation_names[i] = interned_annotation_names_.LookupOrAdd(
+            std::string(trace_event->arg_name(i)));
+      }
+    }
+  } else {
+    interned_name = interned_event_names_.LookupOrAdd(trace_event->name());
 
-      // TODO(eseckler): Remove special handling of typed events here once we
-      // support them in TRACE_EVENT macros.
+    // TODO(eseckler): Remove special handling of typed events here once we
+    // support them in TRACE_EVENT macros.
 
-      if (flags & TRACE_EVENT_FLAG_TYPED_PROTO_ARGS) {
-        if (trace_event->arg_size() == 2u) {
+    if (flags & TRACE_EVENT_FLAG_TYPED_PROTO_ARGS) {
+      if (trace_event->arg_size() == 2u) {
+        DCHECK_EQ(strcmp(category_name, kTaskExecutionEventCategory), 0);
+        DCHECK(strcmp(trace_event->name(), kTaskExecutionEventNames[0]) == 0 ||
+               strcmp(trace_event->name(), kTaskExecutionEventNames[1]) == 0 ||
+               strcmp(trace_event->name(), kTaskExecutionEventNames[2]) == 0);
+        // Double argument task execution event (src_file, src_func).
+        DCHECK_EQ(trace_event->arg_type(0), TRACE_VALUE_TYPE_STRING);
+        DCHECK_EQ(trace_event->arg_type(1), TRACE_VALUE_TYPE_STRING);
+        src_file = trace_event->arg_value(0).as_string;
+        src_func = trace_event->arg_value(1).as_string;
+      } else {
+        // arg_size == 1 enforced by the maximum number of parameter == 2.
+        DCHECK_EQ(trace_event->arg_size(), 1u);
+
+        if (trace_event->arg_type(0) == TRACE_VALUE_TYPE_STRING) {
+          // Single argument task execution event (src_file).
           DCHECK_EQ(strcmp(category_name, kTaskExecutionEventCategory), 0);
           DCHECK(
               strcmp(trace_event->name(), kTaskExecutionEventNames[0]) == 0 ||
               strcmp(trace_event->name(), kTaskExecutionEventNames[1]) == 0 ||
               strcmp(trace_event->name(), kTaskExecutionEventNames[2]) == 0);
-          // Double argument task execution event (src_file, src_func).
-          DCHECK_EQ(trace_event->arg_type(0), TRACE_VALUE_TYPE_STRING);
-          DCHECK_EQ(trace_event->arg_type(1), TRACE_VALUE_TYPE_STRING);
           src_file = trace_event->arg_value(0).as_string;
-          src_func = trace_event->arg_value(1).as_string;
         } else {
-          // arg_size == 1 enforced by the maximum number of parameter == 2.
-          DCHECK_EQ(trace_event->arg_size(), 1u);
+          DCHECK(trace_event->arg_type(0) == TRACE_VALUE_TYPE_CONVERTABLE);
+          DCHECK(strcmp(category_name, "log") == 0);
+          DCHECK(strcmp(trace_event->name(), "LogMessage") == 0);
+          const base::trace_event::LogMessage* value =
+              static_cast<base::trace_event::LogMessage*>(
+                  trace_event->arg_value(0).as_convertable);
+          src_file = value->file();
+          line_number = value->line_number();
+          log_message_body = value->message().c_str();
 
-          if (trace_event->arg_type(0) == TRACE_VALUE_TYPE_STRING) {
-            // Single argument task execution event (src_file).
-            DCHECK_EQ(strcmp(category_name, kTaskExecutionEventCategory), 0);
-            DCHECK(
-                strcmp(trace_event->name(), kTaskExecutionEventNames[0]) == 0 ||
-                strcmp(trace_event->name(), kTaskExecutionEventNames[1]) == 0 ||
-                strcmp(trace_event->name(), kTaskExecutionEventNames[2]) == 0);
-            src_file = trace_event->arg_value(0).as_string;
-          } else {
-            DCHECK_EQ(trace_event->arg_type(0), TRACE_VALUE_TYPE_CONVERTABLE);
-            DCHECK(strcmp(category_name, "log") == 0);
-            DCHECK(strcmp(trace_event->name(), "LogMessage") == 0);
-            const base::trace_event::LogMessage* value =
-                static_cast<base::trace_event::LogMessage*>(
-                    trace_event->arg_value(0).as_convertable);
-            src_file = value->file();
-            line_number = value->line_number();
-            log_message_body = value->message().c_str();
-
-            interned_log_message_body =
-                interned_log_message_bodies_.LookupOrAdd(value->message());
-          }  // else
-        }    // else
-        interned_source_location = interned_source_locations_.LookupOrAdd(
-            std::make_tuple(src_file, src_func, line_number));
-      } else if (!privacy_filtering_enabled_) {
-        for (size_t i = 0;
-             i < trace_event->arg_size() && trace_event->arg_name(i); ++i) {
-          interned_annotation_names[i] =
-              interned_annotation_names_.LookupOrAdd(trace_event->arg_name(i));
-        }
+          interned_log_message_body =
+              interned_log_message_bodies_.LookupOrAdd(value->message());
+        }  // else
+      }    // else
+      interned_source_location = interned_source_locations_.LookupOrAdd(
+          std::make_tuple(src_file, src_func, line_number));
+    } else if (!privacy_filtering_enabled_) {
+      for (size_t i = 0;
+           i < trace_event->arg_size() && trace_event->arg_name(i); ++i) {
+        interned_annotation_names[i] =
+            interned_annotation_names_.LookupOrAdd(trace_event->arg_name(i));
       }
     }
   }
@@ -354,9 +367,7 @@
   }
 
   // TODO(eseckler): Split comma-separated category strings.
-  if (interned_category.id) {
-    track_event->add_category_iids(interned_category.id);
-  }
+  track_event->add_category_iids(interned_category.id);
 
   if (interned_log_message_body.id) {
     auto* log_message = track_event->set_log_message();
@@ -371,11 +382,9 @@
 
   auto* legacy_event = track_event->set_legacy_event();
 
-  // TODO(eseckler): Set name on |track_event| instead.
-  if (interned_name.id) {
-    legacy_event->set_name_iid(interned_name.id);
-  }
+  legacy_event->set_name_iid(interned_name.id);
 
+  char phase = trace_event->phase();
   legacy_event->set_phase(phase);
 
   if (phase == TRACE_EVENT_PHASE_COMPLETE) {
@@ -476,8 +485,7 @@
 
   // Emit any new interned data entries into the packet.
   perfetto::protos::pbzero::InternedData* interned_data = nullptr;
-
-  if (interned_category.id && !interned_category.was_emitted) {
+  if (!interned_category.was_emitted) {
     if (!interned_data) {
       interned_data = trace_packet->set_interned_data();
     }
@@ -486,7 +494,7 @@
     category_entry->set_name(category_name);
   }
 
-  if (interned_name.id && !interned_name.was_emitted) {
+  if (!interned_name.was_emitted) {
     if (!interned_data) {
       interned_data = trace_packet->set_interned_data();
     }
@@ -546,29 +554,41 @@
     interned_source_locations_.Clear();
     interned_log_message_bodies_.Clear();
   }
-
-#if defined(OS_ANDROID)
-  trace_event->SendToATrace();
-#endif
 }
 
 void TrackEventThreadLocalEventSink::UpdateDuration(
-    const unsigned char* category_group_enabled,
-    const char* name,
     base::trace_event::TraceEventHandle handle,
-    int thread_id,
-    bool explicit_timestamps,
     const base::TimeTicks& now,
     const base::ThreadTicks& thread_now,
     base::trace_event::ThreadInstructionCount thread_instruction_now) {
-  base::trace_event::TraceEvent new_trace_event(
-      thread_id, now, thread_now, thread_instruction_now, TRACE_EVENT_PHASE_END,
-      category_group_enabled, name, trace_event_internal::kGlobalScope,
-      trace_event_internal::kNoId /* id */,
-      trace_event_internal::kNoId /* bind_id */, nullptr,
-      explicit_timestamps ? TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP
-                          : TRACE_EVENT_FLAG_NONE);
-  AddTraceEvent(&new_trace_event, nullptr);
+  if (!handle.event_index || handle.chunk_index != kMagicChunkIndex ||
+      handle.chunk_seq != sink_id_) {
+    return;
+  }
+
+  DCHECK_GE(current_stack_depth_, 1u);
+  // During trace shutdown, as the list of enabled categories are
+  // non-monotonically shut down, there's the possibility that events higher in
+  // the stack will have their category disabled prior to events lower in the
+  // stack, hence we get misaligned here. In this case, as we know we're
+  // shutting down, we leave the events unfinished.
+  if (handle.event_index != current_stack_depth_) {
+    DCHECK(handle.event_index > 0 &&
+           handle.event_index < current_stack_depth_ &&
+           !base::trace_event::TraceLog::GetInstance()->IsEnabled());
+    current_stack_depth_ = std::min(
+        current_stack_depth_, static_cast<uint32_t>(handle.event_index - 1));
+    return;
+  }
+
+  current_stack_depth_--;
+  complete_event_stack_[current_stack_depth_].UpdateDuration(
+      now, thread_now, thread_instruction_now);
+  AddTraceEvent(&complete_event_stack_[current_stack_depth_], nullptr);
+
+#if defined(OS_ANDROID)
+  complete_event_stack_[current_stack_depth_].SendToATrace();
+#endif
 }
 
 void TrackEventThreadLocalEventSink::Flush() {
diff --git a/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h b/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h
index 97cb808..b20860b 100644
--- a/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h
+++ b/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h
@@ -45,11 +45,7 @@
   // ThreadLocalEventSink implementation:
   void AddTraceEvent(base::trace_event::TraceEvent* trace_event,
                      base::trace_event::TraceEventHandle* handle) override;
-  void UpdateDuration(const unsigned char* category_group_enabled,
-                      const char* name,
-                      base::trace_event::TraceEventHandle handle,
-                      int thread_id,
-                      bool explicit_timestamps,
+  void UpdateDuration(base::trace_event::TraceEventHandle handle,
                       const base::TimeTicks& now,
                       const base::ThreadTicks& thread_now,
                       base::trace_event::ThreadInstructionCount
@@ -98,6 +94,9 @@
   perfetto::protos::pbzero::ThreadDescriptor::ChromeThreadType thread_type_ =
       perfetto::protos::pbzero::ThreadDescriptor::CHROME_THREAD_UNSPECIFIED;
 
+  base::trace_event::TraceEvent complete_event_stack_[kMaxCompleteEventDepth];
+  uint32_t current_stack_depth_ = 0;
+
   const bool privacy_filtering_enabled_;
 };