Merge changes If73657de,I2602fe22

* changes:
  Support perfetto::DynamicString in legacy macro
  Support perfetto::DynamicString event name
diff --git a/docs/instrumentation/track-events.md b/docs/instrumentation/track-events.md
index 9837d6c..931a2a6 100644
--- a/docs/instrumentation/track-events.md
+++ b/docs/instrumentation/track-events.md
@@ -302,6 +302,51 @@
 );
 ```
 
+## Dynamic event names
+
+Ideally all event name should be compile time string constants. For example:
+
+```C+++
+TRACE_EVENT_BEGIN("rendering", "DrawGame");
+```
+
+Here `"DrawGame"` is a compile time string. If we pass a dynamic string here,
+we will get compile time static_assert failure. For example :
+
+```C++
+const char* name = "DrawGame";
+TRACE_EVENT_BEGIN("rendering", name);  // Error. Event name is not static.
+```
+
+There are two ways to use dynamic event name:
+
+1) If the event name is actually dynamic (e.g., std::string), write it using
+   `perfetto::DynamicName`:
+
+```C++
+  TRACE_EVENT("category", perfetto::DynamicName{dynamic_name});
+```
+
+Note: Below is the old way of using dynamic event names. It's not recommended
+      anymore.
+
+```C++
+TRACE_EVENT("category", nullptr, [&](perfetto::EventContext ctx) {
+  ctx.event()->set_name(dynamic_name);
+});
+```
+
+2) If the name is static, but the pointer is computed at runtime, wrap it
+   with perfetto::StaticString:
+
+```C++
+TRACE_EVENT("category", perfetto::StaticString{name});
+TRACE_EVENT("category", perfetto::StaticString{i % 2 == 0 ? "A" : "B"});
+```
+
+DANGER: Using perfetto::StaticString with strings whose contents change
+        dynamically can cause silent trace data corruption.
+
 ## Performance
 
 Perfetto's trace points are designed to have minimal overhead when tracing is
diff --git a/include/perfetto/tracing/internal/track_event_data_source.h b/include/perfetto/tracing/internal/track_event_data_source.h
index 757157f..4d51114 100644
--- a/include/perfetto/tracing/internal/track_event_data_source.h
+++ b/include/perfetto/tracing/internal/track_event_data_source.h
@@ -97,6 +97,29 @@
   return true;
 }
 
+// Taken from C++17
+template <typename...>
+using void_t = void;
+
+// Returns true iff `GetStaticString(T)` is defined OR T == DynamicString.
+template <typename T, typename = void>
+struct IsValidEventNameType
+    : std::is_same<perfetto::DynamicString, typename std::decay<T>::type> {};
+
+template <typename T>
+struct IsValidEventNameType<
+    T,
+    void_t<decltype(GetStaticString(std::declval<T>()))>> : std::true_type {};
+
+template <typename T>
+inline void ValidateEventNameType() {
+  static_assert(
+      IsValidEventNameType<T>::value,
+      "Event names must be static strings. To use dynamic event names, see "
+      "https://perfetto.dev/docs/instrumentation/"
+      "track-events#dynamic-event-names");
+}
+
 }  // namespace
 
 // Traits for dynamic categories.
@@ -234,10 +257,12 @@
   // - Zero or one lambda.
 
   // Trace point which does not take a track or timestamp.
-  template <typename CategoryType, typename... Arguments>
+  template <typename CategoryType,
+            typename EventNameType,
+            typename... Arguments>
   static void TraceForCategory(uint32_t instances,
                                const CategoryType& category,
-                               const char* event_name,
+                               const EventNameType& event_name,
                                perfetto::protos::pbzero::TrackEvent::Type type,
                                Arguments&&... args) PERFETTO_NO_INLINE {
     TraceForCategoryImpl(instances, category, event_name, type,
@@ -253,12 +278,13 @@
   // parsing track as a part of Arguments...).
   template <typename TrackType,
             typename CategoryType,
+            typename EventNameType,
             typename... Arguments,
             typename TrackTypeCheck = typename std::enable_if<
                 std::is_convertible<TrackType, Track>::value>::type>
   static void TraceForCategory(uint32_t instances,
                                const CategoryType& category,
-                               const char* event_name,
+                               const EventNameType& event_name,
                                perfetto::protos::pbzero::TrackEvent::Type type,
                                TrackType&& track,
                                Arguments&&... args) PERFETTO_NO_INLINE {
@@ -269,13 +295,14 @@
 
   // Trace point which takes a timestamp, but not track.
   template <typename CategoryType,
+            typename EventNameType,
             typename TimestampType = uint64_t,
             typename... Arguments,
             typename TimestampTypeCheck = typename std::enable_if<
                 IsValidTimestamp<TimestampType>()>::type>
   static void TraceForCategory(uint32_t instances,
                                const CategoryType& category,
-                               const char* event_name,
+                               const EventNameType& event_name,
                                perfetto::protos::pbzero::TrackEvent::Type type,
                                TimestampType&& timestamp,
                                Arguments&&... args) PERFETTO_NO_INLINE {
@@ -288,6 +315,7 @@
   // Trace point which takes a timestamp and a track.
   template <typename TrackType,
             typename CategoryType,
+            typename EventNameType,
             typename TimestampType = uint64_t,
             typename... Arguments,
             typename TrackTypeCheck = typename std::enable_if<
@@ -296,7 +324,7 @@
                 IsValidTimestamp<TimestampType>()>::type>
   static void TraceForCategory(uint32_t instances,
                                const CategoryType& category,
-                               const char* event_name,
+                               const EventNameType& event_name,
                                perfetto::protos::pbzero::TrackEvent::Type type,
                                TrackType&& track,
                                TimestampType&& timestamp,
@@ -308,10 +336,10 @@
   }
 
   // Trace point with with a counter sample.
-  template <typename CategoryType, typename ValueType>
+  template <typename CategoryType, typename EventNameType, typename ValueType>
   static void TraceForCategory(uint32_t instances,
                                const CategoryType& category,
-                               const char*,
+                               const EventNameType&,
                                perfetto::protos::pbzero::TrackEvent::Type type,
                                CounterTrack track,
                                ValueType value) PERFETTO_ALWAYS_INLINE {
@@ -322,13 +350,14 @@
 
   // Trace point with with a timestamp and a counter sample.
   template <typename CategoryType,
+            typename EventNameType,
             typename TimestampType = uint64_t,
             typename TimestampTypeCheck = typename std::enable_if<
                 IsValidTimestamp<TimestampType>()>::type,
             typename ValueType>
   static void TraceForCategory(uint32_t instances,
                                const CategoryType& category,
-                               const char*,
+                               const EventNameType&,
                                perfetto::protos::pbzero::TrackEvent::Type type,
                                CounterTrack track,
                                TimestampType timestamp,
@@ -435,6 +464,7 @@
   };
 
   template <typename CategoryType,
+            typename EventNameType,
             typename TrackType = Track,
             typename TimestampType = uint64_t,
             typename TimestampTypeCheck = typename std::enable_if<
@@ -445,7 +475,7 @@
   static void TraceForCategoryImpl(
       uint32_t instances,
       const CategoryType& category,
-      const char* event_name,
+      const EventNameType& event_name,
       perfetto::protos::pbzero::TrackEvent::Type type,
       const TrackType& track,
       const TimestampType& timestamp,
@@ -483,8 +513,9 @@
             bool on_current_thread_track =
                 (&track == &TrackEventInternal::kDefaultTrack);
             auto event_ctx = TrackEventInternal::WriteEvent(
-                trace_writer, incr_state, tls_state, static_category,
-                event_name, type, trace_timestamp, on_current_thread_track);
+                trace_writer, incr_state, tls_state, static_category, type,
+                trace_timestamp, on_current_thread_track);
+            TrackEventInternal::WriteEventName(event_name, event_ctx, type);
             // Write dynamic categories (except for events that don't require
             // categories). For counter events, the counter name (and optional
             // category) is stored as part of the track descriptor instead being
diff --git a/include/perfetto/tracing/internal/track_event_internal.h b/include/perfetto/tracing/internal/track_event_internal.h
index af67b7c..0e0bfe7 100644
--- a/include/perfetto/tracing/internal/track_event_internal.h
+++ b/include/perfetto/tracing/internal/track_event_internal.h
@@ -182,12 +182,31 @@
                                 const protos::gen::TrackEventConfig& config,
                                 const Category& category);
 
+  static void WriteEventName(const perfetto::DynamicString& event_name,
+                             perfetto::EventContext& event_ctx,
+                             perfetto::protos::pbzero::TrackEvent::Type);
+
+  static void WriteStaticEventName(const char* static_event_name,
+                                   perfetto::EventContext& event_ctx);
+
+  template <typename EventNameType,
+            typename Checker =
+                decltype(GetStaticString(std::declval<const EventNameType&>()))>
+  static void WriteEventName(const EventNameType& event_name,
+                             perfetto::EventContext& event_ctx,
+                             perfetto::protos::pbzero::TrackEvent::Type type) {
+    auto static_name = GetStaticString(event_name);
+    if (static_name != nullptr &&
+        type != protos::pbzero::TrackEvent::TYPE_SLICE_END) {
+      WriteStaticEventName(static_name, event_ctx);
+    }
+  }
+
   static perfetto::EventContext WriteEvent(
       TraceWriterBase*,
       TrackEventIncrementalState*,
       const TrackEventTlsState& tls_state,
       const Category* category,
-      const char* name,
       perfetto::protos::pbzero::TrackEvent::Type,
       const TraceTimestamp& timestamp,
       bool on_current_thread_track);
diff --git a/include/perfetto/tracing/internal/track_event_macros.h b/include/perfetto/tracing/internal/track_event_macros.h
index da22586..a9a3c7a 100644
--- a/include/perfetto/tracing/internal/track_event_macros.h
+++ b/include/perfetto/tracing/internal/track_event_macros.h
@@ -23,6 +23,7 @@
 
 #include "perfetto/base/compiler.h"
 #include "perfetto/tracing/internal/track_event_data_source.h"
+#include "perfetto/tracing/string_helpers.h"
 #include "perfetto/tracing/track_event_category_registry.h"
 
 // Ignore GCC warning about a missing argument for a variadic macro parameter.
@@ -115,8 +116,9 @@
 
 // Efficiently determines whether tracing is enabled for the given category, and
 // if so, emits one trace event with the given arguments.
-#define PERFETTO_INTERNAL_TRACK_EVENT(category, ...)                           \
+#define PERFETTO_INTERNAL_TRACK_EVENT(category, name, ...)                     \
   do {                                                                         \
+    perfetto::internal::ValidateEventNameType<decltype(name)>();               \
     namespace tns = ::PERFETTO_TRACK_EVENT_NAMESPACE;                          \
     /* Compute the category index outside the lambda to work around a */       \
     /* GCC 7 bug */                                                            \
@@ -126,7 +128,7 @@
     if (tns::internal::IsDynamicCategory(category)) {                          \
       tns::TrackEvent::CallIfEnabled(                                          \
           [&](uint32_t instances) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {         \
-            tns::TrackEvent::TraceForCategory(instances, category,             \
+            tns::TrackEvent::TraceForCategory(instances, category, name,       \
                                               ##__VA_ARGS__);                  \
           });                                                                  \
     } else {                                                                   \
@@ -137,7 +139,7 @@
                 instances,                                                     \
                 PERFETTO_UID(                                                  \
                     kCatIndex_ADD_TO_PERFETTO_DEFINE_CATEGORIES_IF_FAILS_),    \
-                ##__VA_ARGS__);                                                \
+                name, ##__VA_ARGS__);                                          \
           });                                                                  \
     }                                                                          \
   } while (false)
diff --git a/include/perfetto/tracing/string_helpers.h b/include/perfetto/tracing/string_helpers.h
index c5d239f..7d0bd6b 100644
--- a/include/perfetto/tracing/string_helpers.h
+++ b/include/perfetto/tracing/string_helpers.h
@@ -40,34 +40,6 @@
   const char* value;
 };
 
-namespace internal {
-
-// Ensure that |string| is a static constant string.
-//
-// If you get a compiler failure here, you are most likely trying to use
-// TRACE_EVENT with a dynamic event name. There are two ways to fix this:
-//
-// 1) If the event name is actually dynamic (e.g., std::string), write it into
-//    the event manually:
-//
-//      TRACE_EVENT("category", nullptr, [&](perfetto::EventContext ctx) {
-//        ctx.event()->set_name(dynamic_name);
-//      });
-//
-// 2) If the name is static, but the pointer is computed at runtime, wrap it
-//    with perfetto::StaticString:
-//
-//      TRACE_EVENT("category", perfetto::StaticString{name});
-//
-//    DANGER: Using perfetto::StaticString with strings whose contents change
-//            dynamically can cause silent trace data corruption.
-//
-constexpr const char* GetStaticString(StaticString string) {
-  return string.value;
-}
-
-}  // namespace internal
-
 // A explicit wrapper for marking strings as dynamic to ensure that perfetto
 // doesn't try to cache the pointer value.
 class PERFETTO_EXPORT_COMPONENT DynamicString {
@@ -81,6 +53,22 @@
   size_t length;
 };
 
+namespace internal {
+
+template <size_t N>
+constexpr const char* GetStaticString(const char (&string)[N]) {
+  return string;
+}
+
+constexpr std::nullptr_t GetStaticString(std::nullptr_t) {
+  return nullptr;
+}
+
+constexpr const char* GetStaticString(perfetto::StaticString string) {
+  return string.value;
+}
+
+}  // namespace internal
 }  // namespace perfetto
 
 #endif  // INCLUDE_PERFETTO_TRACING_STRING_HELPERS_H_
diff --git a/include/perfetto/tracing/track_event.h b/include/perfetto/tracing/track_event.h
index 45499eb..c3e86d3 100644
--- a/include/perfetto/tracing/track_event.h
+++ b/include/perfetto/tracing/track_event.h
@@ -291,9 +291,9 @@
 //   TRACE_EVENT("category", "Name", perfetto::Track(1234),
 //               "arg", value, "arg2", value2);
 //
-#define TRACE_EVENT_BEGIN(category, name, ...)               \
-  PERFETTO_INTERNAL_TRACK_EVENT(                             \
-      category, ::perfetto::internal::GetStaticString(name), \
+#define TRACE_EVENT_BEGIN(category, name, ...) \
+  PERFETTO_INTERNAL_TRACK_EVENT(               \
+      category, name,                          \
       ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN, ##__VA_ARGS__)
 
 // End a slice under |category|.
@@ -307,10 +307,10 @@
   PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(category, name, ##__VA_ARGS__)
 
 // Emit a slice which has zero duration.
-#define TRACE_EVENT_INSTANT(category, name, ...)             \
-  PERFETTO_INTERNAL_TRACK_EVENT(                             \
-      category, ::perfetto::internal::GetStaticString(name), \
-      ::perfetto::protos::pbzero::TrackEvent::TYPE_INSTANT, ##__VA_ARGS__)
+#define TRACE_EVENT_INSTANT(category, name, ...)                            \
+  PERFETTO_INTERNAL_TRACK_EVENT(                                            \
+      category, name, ::perfetto::protos::pbzero::TrackEvent::TYPE_INSTANT, \
+      ##__VA_ARGS__)
 
 // Efficiently determine if the given static or dynamic trace category or
 // category group is enabled for tracing.
diff --git a/include/perfetto/tracing/track_event_legacy.h b/include/perfetto/tracing/track_event_legacy.h
index 0ec0ddd..f99d093 100644
--- a/include/perfetto/tracing/track_event_legacy.h
+++ b/include/perfetto/tracing/track_event_legacy.h
@@ -434,6 +434,23 @@
   }
 };
 
+// In legacy macro, `const char*` is considered static by default, unless it's
+// wrapped in `TRACE_STR_COPY`.
+// Given a `nullptr`, `const char (&)[N]`, `const char*` or `StaticString`,
+// convert it to `perfetto::StaticString`.
+template <typename T>
+inline ::perfetto::StaticString ConvertToStaticStringByDefault(const T& name);
+
+inline ::perfetto::DynamicString ConvertToStaticStringByDefault(
+    ::perfetto::DynamicString name) {
+  return name;
+}
+
+template <typename T>
+inline ::perfetto::StaticString ConvertToStaticStringByDefault(const T& name) {
+  return ::perfetto::StaticString{name};
+}
+
 }  // namespace internal
 }  // namespace perfetto
 
@@ -442,8 +459,7 @@
 #define PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK(phase, category, name, track, \
                                                 ...)                          \
   PERFETTO_INTERNAL_TRACK_EVENT(                                              \
-      category,                                                               \
-      ::perfetto::internal::GetStaticString(::perfetto::StaticString{name}),  \
+      category, ::perfetto::internal::ConvertToStaticStringByDefault(name),   \
       ::perfetto::internal::TrackEventLegacy::PhaseToType(phase), track,      \
       ##__VA_ARGS__);
 
@@ -503,12 +519,12 @@
 
 // PERFETTO_INTERNAL_SCOPED_TRACK_EVENT does not require GetStaticString, as it
 // uses TRACE_EVENT_BEGIN/END internally, which already have this call.
-#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...)               \
-  PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(                                    \
-      category, ::perfetto::StaticString{name},                            \
-      [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
-        using ::perfetto::internal::TrackEventLegacy;                      \
-        TrackEventLegacy::AddDebugAnnotations(&ctx, ##__VA_ARGS__);        \
+#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...)                \
+  PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(                                     \
+      category, ::perfetto::internal::ConvertToStaticStringByDefault(name), \
+      [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {  \
+        using ::perfetto::internal::TrackEventLegacy;                       \
+        TrackEventLegacy::AddDebugAnnotations(&ctx, ##__VA_ARGS__);         \
       })
 
 // PERFETTO_INTERNAL_SCOPED_TRACK_EVENT does not require GetStaticString, as it
@@ -516,7 +532,7 @@
 #define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category, name, bind_id,   \
                                                   flags, ...)                \
   PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(                                      \
-      category, ::perfetto::StaticString{name},                              \
+      category, ::perfetto::internal::ConvertToStaticStringByDefault(name),  \
       [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {   \
         using ::perfetto::internal::TrackEventLegacy;                        \
         ::perfetto::internal::LegacyTraceId PERFETTO_UID(trace_id){bind_id}; \
@@ -1230,7 +1246,7 @@
 // involvement from the embedder. APIs such as TRACE_EVENT_API_ADD_TRACE_EVENT
 // are still up to the embedder to define.
 
-#define TRACE_STR_COPY(str) (str)
+#define TRACE_STR_COPY(str) (perfetto::DynamicString{str})
 
 #define TRACE_ID_WITH_SCOPE(scope, ...) \
   ::perfetto::internal::LegacyTraceId::WithScope(scope, ##__VA_ARGS__)
diff --git a/src/tracing/internal/track_event_internal.cc b/src/tracing/internal/track_event_internal.cc
index dbc87ab..fbcb023 100644
--- a/src/tracing/internal/track_event_internal.cc
+++ b/src/tracing/internal/track_event_internal.cc
@@ -438,12 +438,27 @@
 }
 
 // static
+void TrackEventInternal::WriteStaticEventName(
+    const char* static_event_name,
+    perfetto::EventContext& event_ctx) {
+  size_t name_iid = InternedEventName::Get(&event_ctx, static_event_name);
+  event_ctx.event()->set_name_iid(name_iid);
+}
+
+// static
+void TrackEventInternal::WriteEventName(
+    const perfetto::DynamicString& event_name,
+    perfetto::EventContext& event_ctx,
+    perfetto::protos::pbzero::TrackEvent::Type) {
+  event_ctx.event()->set_name(event_name.value, event_name.length);
+}
+
+// static
 EventContext TrackEventInternal::WriteEvent(
     TraceWriterBase* trace_writer,
     TrackEventIncrementalState* incr_state,
     const TrackEventTlsState& tls_state,
     const Category* category,
-    const char* name,
     perfetto::protos::pbzero::TrackEvent::Type type,
     const TraceTimestamp& timestamp,
     bool on_current_thread_track) {
@@ -466,7 +481,7 @@
         static_cast<int64_t>(tls_state.timestamp_unit_multiplier));
   }
 
-  // We assume that |category| and |name| point to strings with static lifetime.
+  // We assume that |category| points to the string with static lifetime.
   // This means we can use their addresses as interning keys.
   // TODO(skyostil): Intern categories at compile time.
   if (category && type != protos::pbzero::TrackEvent::TYPE_SLICE_END &&
@@ -479,10 +494,6 @@
           return true;
         });
   }
-  if (name && type != protos::pbzero::TrackEvent::TYPE_SLICE_END) {
-    size_t name_iid = InternedEventName::Get(&ctx, name);
-    track_event->set_name_iid(name_iid);
-  }
   return ctx;
 }
 
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index 2293a73..0c4f52c 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -3226,6 +3226,23 @@
                                   "B:test.Even", "B:test.Odd", "B:test.Even"));
 }
 
+TEST_P(PerfettoApiTest, TrackEventEventNameDynamicString) {
+  // Create a new trace session.
+  auto* tracing_session = NewTraceWithCategories({"foo"});
+  tracing_session->get()->StartBlocking();
+  TRACE_EVENT_BEGIN("foo", perfetto::DynamicString{std::string("Event1")});
+  TRACE_EVENT_BEGIN("foo", perfetto::DynamicString{std::string("Event2")});
+  TRACE_EVENT0("foo", TRACE_STR_COPY(std::string("Event3")));
+  const char* event4 = "Event4";
+  TRACE_EVENT0("foo", event4);
+  auto slices = StopSessionAndReadSlicesFromTrace(tracing_session);
+  ASSERT_EQ(4u, slices.size());
+  EXPECT_EQ("B:foo.Event1", slices[0]);
+  EXPECT_EQ("B:foo.Event2", slices[1]);
+  EXPECT_EQ("B:foo.Event3", slices[2]);
+  EXPECT_EQ("B:foo.Event4", slices[3]);
+}
+
 TEST_P(PerfettoApiTest, TrackEventArgumentsNotEvaluatedWhenDisabled) {
   // Create a new trace session.
   auto* tracing_session = NewTraceWithCategories({"foo"});