TrackEvent: Add parent uuid field and move track descriptor extension points

This patch adds the parent_uuid field to the track descriptor so that
tracks can be grouped in a hierarchy and moves the extension points
(e.g., Chrome-specific track descriptor fields) to their own top-level
messages to make it easier to add custom descriptor extensions in the
future.

Bug: 132678367
Change-Id: I448df34a7acff5809cd768b25f3d22d2ac27cf73
diff --git a/Android.bp b/Android.bp
index 3d8cdc7..d8b4f9a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -4718,6 +4718,8 @@
     "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
     "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
     "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+    "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
+    "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
     "protos/perfetto/trace/track_event/chrome_user_event.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
@@ -4738,6 +4740,8 @@
     "external/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.gen.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.gen.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_thread_descriptor.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.gen.cc",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.gen.cc",
@@ -4758,6 +4762,8 @@
     "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
     "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
     "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+    "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
+    "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
     "protos/perfetto/trace/track_event/chrome_user_event.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
@@ -4778,6 +4784,8 @@
     "external/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.gen.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.gen.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_thread_descriptor.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.gen.h",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.gen.h",
@@ -4802,6 +4810,8 @@
     "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
     "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
     "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+    "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
+    "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
     "protos/perfetto/trace/track_event/chrome_user_event.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
@@ -4821,6 +4831,8 @@
     "external/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pb.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.pb.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_thread_descriptor.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pb.cc",
@@ -4841,6 +4853,8 @@
     "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
     "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
     "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+    "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
+    "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
     "protos/perfetto/trace/track_event/chrome_user_event.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
@@ -4860,6 +4874,8 @@
     "external/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pb.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.pb.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_thread_descriptor.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pb.h",
@@ -4884,6 +4900,8 @@
     "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
     "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
     "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+    "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
+    "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
     "protos/perfetto/trace/track_event/chrome_user_event.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
@@ -4904,6 +4922,8 @@
     "external/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_thread_descriptor.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.cc",
@@ -4924,6 +4944,8 @@
     "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
     "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
     "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+    "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
+    "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
     "protos/perfetto/trace/track_event/chrome_user_event.proto",
     "protos/perfetto/trace/track_event/debug_annotation.proto",
     "protos/perfetto/trace/track_event/log_message.proto",
@@ -4944,6 +4966,8 @@
     "external/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_keyed_service.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_thread_descriptor.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/chrome_user_event.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.h",
diff --git a/BUILD b/BUILD
index 85d887b..0242d73 100644
--- a/BUILD
+++ b/BUILD
@@ -2347,6 +2347,8 @@
         "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
         "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
         "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+        "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
+        "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
         "protos/perfetto/trace/track_event/chrome_user_event.proto",
         "protos/perfetto/trace/track_event/debug_annotation.proto",
         "protos/perfetto/trace/track_event/log_message.proto",
diff --git a/protos/perfetto/trace/track_event/BUILD.gn b/protos/perfetto/trace/track_event/BUILD.gn
index 0db8974..2cb38d0 100644
--- a/protos/perfetto/trace/track_event/BUILD.gn
+++ b/protos/perfetto/trace/track_event/BUILD.gn
@@ -20,6 +20,8 @@
     "chrome_histogram_sample.proto",
     "chrome_keyed_service.proto",
     "chrome_legacy_ipc.proto",
+    "chrome_process_descriptor.proto",
+    "chrome_thread_descriptor.proto",
     "chrome_user_event.proto",
     "debug_annotation.proto",
     "log_message.proto",
diff --git a/protos/perfetto/trace/track_event/chrome_process_descriptor.proto b/protos/perfetto/trace/track_event/chrome_process_descriptor.proto
new file mode 100644
index 0000000..25e5d6f
--- /dev/null
+++ b/protos/perfetto/trace/track_event/chrome_process_descriptor.proto
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+// Describes the attributes for a Chrome process. Must be paired with a
+// ProcessDescriptor in the same TrackDescriptor.
+//
+// Next id: 4.
+message ChromeProcessDescriptor {
+  // See chromium's content::ProcessType.
+  enum ChromeProcessType {
+    PROCESS_UNSPECIFIED = 0;
+    PROCESS_BROWSER = 1;
+    PROCESS_RENDERER = 2;
+    PROCESS_UTILITY = 3;
+    PROCESS_ZYGOTE = 4;
+    PROCESS_SANDBOX_HELPER = 5;
+    PROCESS_GPU = 6;
+    PROCESS_PPAPI_PLUGIN = 7;
+    PROCESS_PPAPI_BROKER = 8;
+  }
+  optional ChromeProcessType process_type = 1;
+  optional int32 process_priority = 2;
+
+  // To support old UI. New UI should determine default sorting by process_type.
+  optional int32 legacy_sort_index = 3;
+}
diff --git a/protos/perfetto/trace/track_event/chrome_thread_descriptor.proto b/protos/perfetto/trace/track_event/chrome_thread_descriptor.proto
new file mode 100644
index 0000000..0f23e7b
--- /dev/null
+++ b/protos/perfetto/trace/track_event/chrome_thread_descriptor.proto
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 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";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+// Describes a Chrome thread's attributes. Emitted as part of a TrackDescriptor,
+// usually by the thread's trace writer. Must be paired with a ThreadDescriptor
+// in the same TrackDescriptor.
+//
+// Next id: 3.
+message ChromeThreadDescriptor {
+  enum ThreadType {
+    THREAD_UNSPECIFIED = 0;
+
+    THREAD_MAIN = 1;
+    THREAD_IO = 2;
+
+    // Scheduler:
+    THREAD_POOL_BG_WORKER = 3;
+    THREAD_POOL_FG_WORKER = 4;
+    THREAD_POOL_FB_BLOCKING = 5;
+    THREAD_POOL_BG_BLOCKING = 6;
+    THREAD_POOL_SERVICE = 7;
+
+    // Compositor:
+    THREAD_COMPOSITOR = 8;
+    THREAD_VIZ_COMPOSITOR = 9;
+    THREAD_COMPOSITOR_WORKER = 10;
+
+    // Renderer:
+    THREAD_SERVICE_WORKER = 11;
+
+    // Tracing related threads:
+    THREAD_MEMORY_INFRA = 50;
+    THREAD_SAMPLING_PROFILER = 51;
+  };
+  optional ThreadType thread_type = 1;
+
+  // To support old UI. New UI should determine default sorting by thread_type.
+  optional int32 legacy_sort_index = 2;
+}
diff --git a/protos/perfetto/trace/track_event/process_descriptor.proto b/protos/perfetto/trace/track_event/process_descriptor.proto
index cc60936..fceb5ba 100644
--- a/protos/perfetto/trace/track_event/process_descriptor.proto
+++ b/protos/perfetto/trace/track_event/process_descriptor.proto
@@ -22,11 +22,17 @@
 // Describes a process's attributes. Emitted as part of a TrackDescriptor,
 // usually by the process's main thread.
 //
-// Next id: 5.
+// Next id: 6.
 message ProcessDescriptor {
   optional int32 pid = 1;
   repeated string cmdline = 2;
 
+  optional int32 process_priority = 5;
+
+  // ---------------------------------------------------------------------------
+  // Deprecated / legacy fields, which will be removed in the future:
+  // ---------------------------------------------------------------------------
+
   // See chromium's content::ProcessType.
   enum ChromeProcessType {
     PROCESS_UNSPECIFIED = 0;
@@ -40,7 +46,6 @@
     PROCESS_PPAPI_BROKER = 8;
   }
   optional ChromeProcessType chrome_process_type = 4;
-  optional int32 process_priority = 5;
 
   // To support old UI. New UI should determine default sorting by process_type.
   optional int32 legacy_sort_index = 3;
diff --git a/protos/perfetto/trace/track_event/thread_descriptor.proto b/protos/perfetto/trace/track_event/thread_descriptor.proto
index b2d2cb6..1c14e21 100644
--- a/protos/perfetto/trace/track_event/thread_descriptor.proto
+++ b/protos/perfetto/trace/track_event/thread_descriptor.proto
@@ -29,6 +29,10 @@
 
   optional string thread_name = 5;
 
+  // ---------------------------------------------------------------------------
+  // Deprecated / legacy fields, which will be removed in the future:
+  // ---------------------------------------------------------------------------
+
   enum ChromeThreadType {
     CHROME_THREAD_UNSPECIFIED = 0;
 
@@ -56,10 +60,6 @@
   };
   optional ChromeThreadType chrome_thread_type = 4;
 
-  // ---------------------------------------------------------------------------
-  // Deprecated / legacy fields, which will be removed in the future:
-  // ---------------------------------------------------------------------------
-
   // Deprecated. Use ClockSnapshot in combination with TracePacket's timestamp
   // and timestamp_clock_id fields instead.
   optional int64 reference_timestamp_us = 6;
diff --git a/protos/perfetto/trace/track_event/track_descriptor.proto b/protos/perfetto/trace/track_event/track_descriptor.proto
index a9ba7be..35b1ce2 100644
--- a/protos/perfetto/trace/track_event/track_descriptor.proto
+++ b/protos/perfetto/trace/track_event/track_descriptor.proto
@@ -17,13 +17,17 @@
 syntax = "proto2";
 option optimize_for = LITE_RUNTIME;
 
+import "protos/perfetto/trace/track_event/chrome_process_descriptor.proto";
+import "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto";
 import "protos/perfetto/trace/track_event/process_descriptor.proto";
 import "protos/perfetto/trace/track_event/thread_descriptor.proto";
 
 package perfetto.protos;
 
 // Defines a track for TrackEvents. Slices and instant events on the same track
-// will be nested based on their timestamps, see TrackEvent::Type.
+// will be nested based on their timestamps, see TrackEvent::Type. Additionally
+// events on tracks which represent the same thread (i.e., matching pid and tid
+// in ThreadDescriptor) will be merged onto one sequential timeline.
 //
 // A TrackDescriptor only needs to be emitted by one trace writer / producer and
 // is valid for the entirety of the trace. To ensure the descriptor isn't lost
@@ -35,7 +39,7 @@
 // |TrackEvent::track_uuid|. It is possible but not necessary to emit a
 // TrackDescriptor for this implicit track.
 //
-// Next id: 1.
+// Next id: 8.
 message TrackDescriptor {
   // Unique ID that identifies this track. This ID is global to the whole trace.
   // Producers should ensure that it is unlikely to clash with IDs emitted by
@@ -45,14 +49,18 @@
   // event id + id_scope, pid, and/or tid to compute this ID.
   optional uint64 uuid = 1;
 
-  // TODO(eseckler): Support track hierarchies.
-  // uint64 parent_uuid = X;
+  // A parent track reference can be used to describe relationships between
+  // tracks. For example, to define an asynchronous track which is scoped to a
+  // specific process, specify the uuid for that process's process track here.
+  optional uint64 parent_uuid = 5;
 
   // Name of the track.
   optional string name = 2;
 
-  // Associate the track with a process or thread - the UI will draw this track
-  // in the context of the process/thread.
+  // Associate the track with a process or thread - the UI will merge all tracks
+  // for the same process / thread into a single timeline view.
   optional ProcessDescriptor process = 3;
+  optional ChromeProcessDescriptor chrome_process = 6;
   optional ThreadDescriptor thread = 4;
+  optional ChromeThreadDescriptor chrome_thread = 7;
 }
diff --git a/src/trace_processor/importers/proto/track_event_tokenizer.cc b/src/trace_processor/importers/proto/track_event_tokenizer.cc
index 9d17b77..44f0750 100644
--- a/src/trace_processor/importers/proto/track_event_tokenizer.cc
+++ b/src/trace_processor/importers/proto/track_event_tokenizer.cc
@@ -30,6 +30,8 @@
 
 #include "protos/perfetto/trace/clock_snapshot.pbzero.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h"
+#include "protos/perfetto/trace/track_event/chrome_thread_descriptor.pbzero.h"
 #include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
 #include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
 #include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
@@ -74,6 +76,28 @@
 
     upid = context_->process_tracker->GetOrCreateProcess(
         static_cast<uint32_t>(process_descriptor_decoder.pid()));
+
+    if (track_descriptor_decoder.has_chrome_process()) {
+      auto chrome_process_descriptor_field =
+          track_descriptor_decoder.chrome_process();
+      protos::pbzero::ChromeProcessDescriptor::Decoder
+          chrome_process_descriptor_decoder(
+              chrome_process_descriptor_field.data,
+              chrome_process_descriptor_field.size);
+
+      auto process_type = chrome_process_descriptor_decoder.process_type();
+      size_t name_index =
+          static_cast<size_t>(process_type) < process_name_ids_.size()
+              ? static_cast<size_t>(process_type)
+              : 0u;
+      StringId name = process_name_ids_[name_index];
+
+      // Don't override system-provided names.
+      context_->process_tracker->SetProcessNameIfUnset(
+          context_->process_tracker->GetOrCreateProcess(
+              static_cast<uint32_t>(process_descriptor_decoder.pid())),
+          name);
+    }
   }
 
   if (track_descriptor_decoder.has_thread()) {
@@ -86,6 +110,18 @@
         static_cast<uint32_t>(thread_descriptor_decoder.tid()),
         static_cast<uint32_t>(thread_descriptor_decoder.pid()));
     upid = *context_->storage->GetThread(*utid).upid;
+
+    if (track_descriptor_decoder.has_chrome_thread()) {
+      auto chrome_thread_descriptor_field =
+          track_descriptor_decoder.chrome_thread();
+      protos::pbzero::ChromeThreadDescriptor::Decoder
+          chrome_thread_descriptor_decoder(chrome_thread_descriptor_field.data,
+                                           chrome_thread_descriptor_field.size);
+
+      TokenizeChromeThreadDescriptor(thread_descriptor_decoder.pid(),
+                                     thread_descriptor_decoder.tid(),
+                                     chrome_thread_descriptor_decoder);
+    }
   }
 
   StringId name_id =
@@ -99,6 +135,7 @@
     const protos::pbzero::TracePacket::Decoder& packet_decoder) {
   protos::pbzero::ProcessDescriptor::Decoder process_descriptor_decoder(
       packet_decoder.process_descriptor());
+  // TODO(skyostil): Remove parsing for legacy chrome_process_type field.
   if (!process_descriptor_decoder.has_chrome_process_type())
     return;
 
@@ -155,6 +192,7 @@
   if (thread_descriptor_decoder.has_thread_name()) {
     name = thread_descriptor_decoder.thread_name();
   } else if (thread_descriptor_decoder.has_chrome_thread_type()) {
+    // TODO(skyostil): Remove parsing for legacy chrome_thread_type field.
     using protos::pbzero::ThreadDescriptor;
     switch (thread_descriptor_decoder.chrome_thread_type()) {
       case ThreadDescriptor::CHROME_THREAD_MAIN:
@@ -214,6 +252,74 @@
   }
 }
 
+void TrackEventTokenizer::TokenizeChromeThreadDescriptor(
+    int32_t pid,
+    int32_t tid,
+    const protos::pbzero::ChromeThreadDescriptor::Decoder&
+        thread_descriptor_decoder) {
+  if (!thread_descriptor_decoder.has_thread_type())
+    return;
+
+  base::StringView name;
+  using protos::pbzero::ChromeThreadDescriptor;
+  // Thread names that end in an ampersand indicate multiple thread instances
+  // (e.g., CompositorTileWorker{1,2,...}) that have been collapsed into a
+  // single thread name.
+  switch (thread_descriptor_decoder.thread_type()) {
+    case ChromeThreadDescriptor::THREAD_MAIN:
+      name = "CrProcessMain";
+      break;
+    case ChromeThreadDescriptor::THREAD_IO:
+      name = "ChromeIOThread";
+      break;
+    case ChromeThreadDescriptor::THREAD_POOL_FG_WORKER:
+      name = "ThreadPoolForegroundWorker&";
+      break;
+    case ChromeThreadDescriptor::THREAD_POOL_BG_WORKER:
+      name = "ThreadPoolBackgroundWorker&";
+      break;
+    case ChromeThreadDescriptor::THREAD_POOL_FB_BLOCKING:
+      name = "ThreadPoolSingleThreadForegroundBlocking&";
+      break;
+    case ChromeThreadDescriptor::THREAD_POOL_BG_BLOCKING:
+      name = "ThreadPoolSingleThreadBackgroundBlocking&";
+      break;
+    case ChromeThreadDescriptor::THREAD_POOL_SERVICE:
+      name = "ThreadPoolService";
+      break;
+    case ChromeThreadDescriptor::THREAD_COMPOSITOR_WORKER:
+      name = "CompositorTileWorker&";
+      break;
+    case ChromeThreadDescriptor::THREAD_COMPOSITOR:
+      name = "Compositor";
+      break;
+    case ChromeThreadDescriptor::THREAD_VIZ_COMPOSITOR:
+      name = "VizCompositorThread";
+      break;
+    case ChromeThreadDescriptor::THREAD_SERVICE_WORKER:
+      name = "ServiceWorkerThread&";
+      break;
+    case ChromeThreadDescriptor::THREAD_MEMORY_INFRA:
+      name = "MemoryInfra";
+      break;
+    case ChromeThreadDescriptor::THREAD_SAMPLING_PROFILER:
+      name = "StackSamplingProfiler";
+      break;
+    case ChromeThreadDescriptor::THREAD_UNSPECIFIED:
+      name = "ChromeUnspecified";
+      break;
+  }
+
+  if (!name.empty()) {
+    auto thread_name_id = context_->storage->InternString(name);
+    ProcessTracker* procs = context_->process_tracker.get();
+    // Don't override system-provided names.
+    procs->SetThreadNameIfUnset(procs->UpdateThread(static_cast<uint32_t>(tid),
+                                                    static_cast<uint32_t>(pid)),
+                                thread_name_id);
+  }
+}
+
 void TrackEventTokenizer::TokenizeTrackEventPacket(
     PacketSequenceState* state,
     const protos::pbzero::TracePacket::Decoder& packet_decoder,
diff --git a/src/trace_processor/importers/proto/track_event_tokenizer.h b/src/trace_processor/importers/proto/track_event_tokenizer.h
index 13a7425..4c848f7 100644
--- a/src/trace_processor/importers/proto/track_event_tokenizer.h
+++ b/src/trace_processor/importers/proto/track_event_tokenizer.h
@@ -25,6 +25,7 @@
 
 namespace protos {
 namespace pbzero {
+class ChromeThreadDescriptor_Decoder;
 class ThreadDescriptor_Decoder;
 class TracePacket_Decoder;
 }  // namespace pbzero
@@ -49,6 +50,10 @@
       const protos::pbzero::TracePacket_Decoder&);
   void TokenizeThreadDescriptor(
       const protos::pbzero::ThreadDescriptor_Decoder&);
+  void TokenizeChromeThreadDescriptor(
+      int32_t pid,
+      int32_t tid,
+      const protos::pbzero::ChromeThreadDescriptor_Decoder&);
   void TokenizeTrackEventPacket(PacketSequenceState* state,
                                 const protos::pbzero::TracePacket_Decoder&,
                                 TraceBlobView* packet,