Merge "perfetto-ui: Show CPU slice aggregation"
diff --git a/Android.bp b/Android.bp
index ee8abe0..2b5c886 100644
--- a/Android.bp
+++ b/Android.bp
@@ -83,7 +83,6 @@
     ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
     ":perfetto_protos_perfetto_config_process_stats_zero_gen",
     ":perfetto_protos_perfetto_config_profiling_cpp_gen",
-    ":perfetto_protos_perfetto_config_profiling_lite_gen",
     ":perfetto_protos_perfetto_config_profiling_zero_gen",
     ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
     ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
@@ -123,7 +122,6 @@
     "libbase",
     "liblog",
     "libprocinfo",
-    "libprotobuf-cpp-lite",
     "libunwindstack",
   ],
   init_rc: [
@@ -146,7 +144,6 @@
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
     "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
     "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
     "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
@@ -686,6 +683,227 @@
   ],
 }
 
+// GN: //test/cts:perfetto_cts_deps
+cc_library_static {
+  name: "perfetto_cts_deps",
+  srcs: [
+    ":perfetto_include_perfetto_base_base",
+    ":perfetto_include_perfetto_ext_base_base",
+    ":perfetto_include_perfetto_ext_ipc_ipc",
+    ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
+    ":perfetto_include_perfetto_ext_traced_traced",
+    ":perfetto_include_perfetto_ext_tracing_core_core",
+    ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
+    ":perfetto_include_perfetto_protozero_protozero",
+    ":perfetto_include_perfetto_tracing_core_core",
+    ":perfetto_include_perfetto_tracing_core_forward_decls",
+    ":perfetto_include_perfetto_tracing_tracing",
+    ":perfetto_protos_perfetto_common_cpp_gen",
+    ":perfetto_protos_perfetto_common_zero_gen",
+    ":perfetto_protos_perfetto_config_android_cpp_gen",
+    ":perfetto_protos_perfetto_config_android_zero_gen",
+    ":perfetto_protos_perfetto_config_cpp_gen",
+    ":perfetto_protos_perfetto_config_ftrace_cpp_gen",
+    ":perfetto_protos_perfetto_config_ftrace_zero_gen",
+    ":perfetto_protos_perfetto_config_gpu_cpp_gen",
+    ":perfetto_protos_perfetto_config_gpu_zero_gen",
+    ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
+    ":perfetto_protos_perfetto_config_inode_file_zero_gen",
+    ":perfetto_protos_perfetto_config_power_cpp_gen",
+    ":perfetto_protos_perfetto_config_power_zero_gen",
+    ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
+    ":perfetto_protos_perfetto_config_process_stats_zero_gen",
+    ":perfetto_protos_perfetto_config_profiling_cpp_gen",
+    ":perfetto_protos_perfetto_config_profiling_zero_gen",
+    ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
+    ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
+    ":perfetto_protos_perfetto_config_zero_gen",
+    ":perfetto_protos_perfetto_ipc_cpp_gen",
+    ":perfetto_protos_perfetto_ipc_ipc_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
+    ":perfetto_protos_perfetto_trace_android_cpp_gen",
+    ":perfetto_protos_perfetto_trace_android_zero_gen",
+    ":perfetto_protos_perfetto_trace_chrome_cpp_gen",
+    ":perfetto_protos_perfetto_trace_chrome_zero_gen",
+    ":perfetto_protos_perfetto_trace_filesystem_cpp_gen",
+    ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
+    ":perfetto_protos_perfetto_trace_ftrace_cpp_gen",
+    ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
+    ":perfetto_protos_perfetto_trace_gpu_cpp_gen",
+    ":perfetto_protos_perfetto_trace_gpu_zero_gen",
+    ":perfetto_protos_perfetto_trace_interned_data_cpp_gen",
+    ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
+    ":perfetto_protos_perfetto_trace_minimal_cpp_gen",
+    ":perfetto_protos_perfetto_trace_minimal_zero_gen",
+    ":perfetto_protos_perfetto_trace_non_minimal_cpp_gen",
+    ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
+    ":perfetto_protos_perfetto_trace_perfetto_cpp_gen",
+    ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
+    ":perfetto_protos_perfetto_trace_power_cpp_gen",
+    ":perfetto_protos_perfetto_trace_power_zero_gen",
+    ":perfetto_protos_perfetto_trace_profiling_cpp_gen",
+    ":perfetto_protos_perfetto_trace_profiling_zero_gen",
+    ":perfetto_protos_perfetto_trace_ps_cpp_gen",
+    ":perfetto_protos_perfetto_trace_ps_zero_gen",
+    ":perfetto_protos_perfetto_trace_sys_stats_cpp_gen",
+    ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
+    ":perfetto_protos_perfetto_trace_track_event_cpp_gen",
+    ":perfetto_protos_perfetto_trace_track_event_zero_gen",
+    ":perfetto_src_android_internal_headers",
+    ":perfetto_src_android_internal_lazy_library_loader",
+    ":perfetto_src_base_base",
+    ":perfetto_src_base_test_support",
+    ":perfetto_src_base_unix_socket",
+    ":perfetto_src_ipc_ipc",
+    ":perfetto_src_perfetto_cmd_perfetto_atoms",
+    ":perfetto_src_protozero_protozero",
+    ":perfetto_src_traced_probes_android_log_android_log",
+    ":perfetto_src_traced_probes_data_source",
+    ":perfetto_src_traced_probes_filesystem_filesystem",
+    ":perfetto_src_traced_probes_ftrace_format_parser",
+    ":perfetto_src_traced_probes_ftrace_ftrace",
+    ":perfetto_src_traced_probes_metatrace_metatrace",
+    ":perfetto_src_traced_probes_packages_list_packages_list",
+    ":perfetto_src_traced_probes_power_power",
+    ":perfetto_src_traced_probes_probes_src",
+    ":perfetto_src_traced_probes_ps_ps",
+    ":perfetto_src_traced_probes_sys_stats_sys_stats",
+    ":perfetto_src_tracing_common",
+    ":perfetto_src_tracing_ipc",
+    ":perfetto_src_tracing_tracing",
+    ":perfetto_test_task_runner_thread",
+    ":perfetto_test_task_runner_thread_delegates",
+    ":perfetto_test_test_helper",
+    "test/cts/device_feature_test_cts.cc",
+    "test/cts/end_to_end_integrationtest_cts.cc",
+    "test/cts/heapprofd_java_test_cts.cc",
+    "test/cts/heapprofd_test_cts.cc",
+    "test/cts/utils.cc",
+  ],
+  static_libs: [
+    "libgmock",
+    "libgtest",
+    "libperfetto_client_experimental",
+  ],
+  export_include_dirs: [
+    "include",
+    "include/perfetto/base/build_configs/android_tree",
+  ],
+  generated_headers: [
+    "perfetto_protos_perfetto_common_cpp_gen_headers",
+    "perfetto_protos_perfetto_common_zero_gen_headers",
+    "perfetto_protos_perfetto_config_android_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_android_zero_gen_headers",
+    "perfetto_protos_perfetto_config_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
+    "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
+    "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
+    "perfetto_protos_perfetto_config_power_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_power_zero_gen_headers",
+    "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
+    "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
+    "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
+    "perfetto_protos_perfetto_config_zero_gen_headers",
+    "perfetto_protos_perfetto_ipc_cpp_gen_headers",
+    "perfetto_protos_perfetto_ipc_ipc_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_android_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_android_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_gpu_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_interned_data_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_minimal_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_non_minimal_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_power_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_power_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_profiling_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_ps_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_sys_stats_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
+  ],
+  export_generated_headers: [
+    "perfetto_protos_perfetto_common_cpp_gen_headers",
+    "perfetto_protos_perfetto_common_zero_gen_headers",
+    "perfetto_protos_perfetto_config_android_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_android_zero_gen_headers",
+    "perfetto_protos_perfetto_config_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
+    "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
+    "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
+    "perfetto_protos_perfetto_config_power_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_power_zero_gen_headers",
+    "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
+    "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
+    "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
+    "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
+    "perfetto_protos_perfetto_config_zero_gen_headers",
+    "perfetto_protos_perfetto_ipc_cpp_gen_headers",
+    "perfetto_protos_perfetto_ipc_ipc_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_android_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_android_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_gpu_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_interned_data_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_minimal_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_non_minimal_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_power_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_power_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_profiling_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_ps_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_sys_stats_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
+    "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
+  ],
+  defaults: [
+    "perfetto_defaults",
+  ],
+  cflags: [
+    "-DGOOGLE_PROTOBUF_NO_RTTI",
+    "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+  ],
+}
+
 // GN: //gn:default_deps
 cc_defaults {
   name: "perfetto_defaults",
@@ -823,65 +1041,55 @@
     ":perfetto_include_perfetto_tracing_core_forward_decls",
     ":perfetto_include_perfetto_tracing_tracing",
     ":perfetto_protos_perfetto_common_cpp_gen",
-    ":perfetto_protos_perfetto_common_lite_gen",
     ":perfetto_protos_perfetto_common_zero_gen",
     ":perfetto_protos_perfetto_config_android_cpp_gen",
-    ":perfetto_protos_perfetto_config_android_lite_gen",
     ":perfetto_protos_perfetto_config_android_zero_gen",
     ":perfetto_protos_perfetto_config_cpp_gen",
     ":perfetto_protos_perfetto_config_ftrace_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_lite_gen",
     ":perfetto_protos_perfetto_config_ftrace_zero_gen",
     ":perfetto_protos_perfetto_config_gpu_cpp_gen",
-    ":perfetto_protos_perfetto_config_gpu_lite_gen",
     ":perfetto_protos_perfetto_config_gpu_zero_gen",
     ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
-    ":perfetto_protos_perfetto_config_inode_file_lite_gen",
     ":perfetto_protos_perfetto_config_inode_file_zero_gen",
-    ":perfetto_protos_perfetto_config_lite_gen",
     ":perfetto_protos_perfetto_config_power_cpp_gen",
-    ":perfetto_protos_perfetto_config_power_lite_gen",
     ":perfetto_protos_perfetto_config_power_zero_gen",
     ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_process_stats_lite_gen",
     ":perfetto_protos_perfetto_config_process_stats_zero_gen",
     ":perfetto_protos_perfetto_config_profiling_cpp_gen",
-    ":perfetto_protos_perfetto_config_profiling_lite_gen",
     ":perfetto_protos_perfetto_config_profiling_zero_gen",
     ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_lite_gen",
     ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_cpp_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
     ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
-    ":perfetto_protos_perfetto_trace_android_lite_gen",
+    ":perfetto_protos_perfetto_trace_android_cpp_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
-    ":perfetto_protos_perfetto_trace_chrome_lite_gen",
+    ":perfetto_protos_perfetto_trace_chrome_cpp_gen",
     ":perfetto_protos_perfetto_trace_chrome_zero_gen",
-    ":perfetto_protos_perfetto_trace_filesystem_lite_gen",
+    ":perfetto_protos_perfetto_trace_filesystem_cpp_gen",
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
-    ":perfetto_protos_perfetto_trace_ftrace_lite_gen",
+    ":perfetto_protos_perfetto_trace_ftrace_cpp_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_trace_gpu_lite_gen",
+    ":perfetto_protos_perfetto_trace_gpu_cpp_gen",
     ":perfetto_protos_perfetto_trace_gpu_zero_gen",
-    ":perfetto_protos_perfetto_trace_interned_data_lite_gen",
+    ":perfetto_protos_perfetto_trace_interned_data_cpp_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
-    ":perfetto_protos_perfetto_trace_minimal_lite_gen",
+    ":perfetto_protos_perfetto_trace_minimal_cpp_gen",
     ":perfetto_protos_perfetto_trace_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_lite_gen",
+    ":perfetto_protos_perfetto_trace_non_minimal_cpp_gen",
     ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_lite_gen",
+    ":perfetto_protos_perfetto_trace_perfetto_cpp_gen",
     ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
-    ":perfetto_protos_perfetto_trace_power_lite_gen",
+    ":perfetto_protos_perfetto_trace_power_cpp_gen",
     ":perfetto_protos_perfetto_trace_power_zero_gen",
-    ":perfetto_protos_perfetto_trace_profiling_lite_gen",
+    ":perfetto_protos_perfetto_trace_profiling_cpp_gen",
     ":perfetto_protos_perfetto_trace_profiling_zero_gen",
-    ":perfetto_protos_perfetto_trace_ps_lite_gen",
+    ":perfetto_protos_perfetto_trace_ps_cpp_gen",
     ":perfetto_protos_perfetto_trace_ps_zero_gen",
-    ":perfetto_protos_perfetto_trace_sys_stats_lite_gen",
+    ":perfetto_protos_perfetto_trace_sys_stats_cpp_gen",
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
-    ":perfetto_protos_perfetto_trace_track_event_lite_gen",
+    ":perfetto_protos_perfetto_trace_track_event_cpp_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_src_android_internal_headers",
     ":perfetto_src_android_internal_lazy_library_loader",
@@ -927,74 +1135,64 @@
     "libbase",
     "liblog",
     "libprocinfo",
-    "libprotobuf-cpp-lite",
     "libunwindstack",
   ],
   static_libs: [
     "libgmock",
+    "libgtest",
     "libperfetto_client_experimental",
   ],
   generated_headers: [
     "perfetto_protos_perfetto_common_cpp_gen_headers",
-    "perfetto_protos_perfetto_common_lite_gen_headers",
     "perfetto_protos_perfetto_common_zero_gen_headers",
     "perfetto_protos_perfetto_config_android_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_android_lite_gen_headers",
     "perfetto_protos_perfetto_config_android_zero_gen_headers",
     "perfetto_protos_perfetto_config_cpp_gen_headers",
     "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
     "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
     "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
     "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_lite_gen_headers",
     "perfetto_protos_perfetto_config_power_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_power_lite_gen_headers",
     "perfetto_protos_perfetto_config_power_zero_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
     "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
     "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
     "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_cpp_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
     "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
-    "perfetto_protos_perfetto_trace_android_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_android_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_gpu_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_interned_data_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_minimal_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_non_minimal_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_power_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_power_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_power_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_profiling_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_profiling_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_ps_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_ps_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_sys_stats_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_sys_stats_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
   ],
   defaults: [
@@ -2498,6 +2696,50 @@
   ],
 }
 
+// GN: //protos/perfetto/trace/android:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_android_cpp_gen",
+  srcs: [
+    "protos/perfetto/trace/android/android_log.proto",
+    "protos/perfetto/trace/android/graphics_frame_event.proto",
+    "protos/perfetto/trace/android/packages_list.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/android/android_log.gen.cc",
+    "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.gen.cc",
+    "external/perfetto/protos/perfetto/trace/android/packages_list.gen.cc",
+  ],
+}
+
+// GN: //protos/perfetto/trace/android:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_android_cpp_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/android/android_log.proto",
+    "protos/perfetto/trace/android/graphics_frame_event.proto",
+    "protos/perfetto/trace/android/packages_list.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/android/android_log.gen.h",
+    "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.gen.h",
+    "external/perfetto/protos/perfetto/trace/android/packages_list.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //protos/perfetto/trace/android:lite
 genrule {
   name: "perfetto_protos_perfetto_trace_android_lite_gen",
@@ -2584,6 +2826,50 @@
   ],
 }
 
+// GN: //protos/perfetto/trace/chrome:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_chrome_cpp_gen",
+  srcs: [
+    "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
+    "protos/perfetto/trace/chrome/chrome_metadata.proto",
+    "protos/perfetto/trace/chrome/chrome_trace_event.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/chrome/chrome_benchmark_metadata.gen.cc",
+    "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.gen.cc",
+    "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.gen.cc",
+  ],
+}
+
+// GN: //protos/perfetto/trace/chrome:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
+    "protos/perfetto/trace/chrome/chrome_metadata.proto",
+    "protos/perfetto/trace/chrome/chrome_trace_event.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/chrome/chrome_benchmark_metadata.gen.h",
+    "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.gen.h",
+    "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //protos/perfetto/trace/chrome:lite
 genrule {
   name: "perfetto_protos_perfetto_trace_chrome_lite_gen",
@@ -2670,6 +2956,42 @@
   ],
 }
 
+// GN: //protos/perfetto/trace/filesystem:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_filesystem_cpp_gen",
+  srcs: [
+    "protos/perfetto/trace/filesystem/inode_file_map.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/filesystem/inode_file_map.gen.cc",
+  ],
+}
+
+// GN: //protos/perfetto/trace/filesystem:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/filesystem/inode_file_map.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/filesystem/inode_file_map.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //protos/perfetto/trace/filesystem:lite
 genrule {
   name: "perfetto_protos_perfetto_trace_filesystem_lite_gen",
@@ -2740,6 +3062,174 @@
   ],
 }
 
+// GN: //protos/perfetto/trace/ftrace:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_ftrace_cpp_gen",
+  srcs: [
+    "protos/perfetto/trace/ftrace/binder.proto",
+    "protos/perfetto/trace/ftrace/block.proto",
+    "protos/perfetto/trace/ftrace/cgroup.proto",
+    "protos/perfetto/trace/ftrace/clk.proto",
+    "protos/perfetto/trace/ftrace/compaction.proto",
+    "protos/perfetto/trace/ftrace/ext4.proto",
+    "protos/perfetto/trace/ftrace/f2fs.proto",
+    "protos/perfetto/trace/ftrace/fence.proto",
+    "protos/perfetto/trace/ftrace/filemap.proto",
+    "protos/perfetto/trace/ftrace/ftrace.proto",
+    "protos/perfetto/trace/ftrace/ftrace_event.proto",
+    "protos/perfetto/trace/ftrace/ftrace_event_bundle.proto",
+    "protos/perfetto/trace/ftrace/ftrace_stats.proto",
+    "protos/perfetto/trace/ftrace/generic.proto",
+    "protos/perfetto/trace/ftrace/i2c.proto",
+    "protos/perfetto/trace/ftrace/ipi.proto",
+    "protos/perfetto/trace/ftrace/irq.proto",
+    "protos/perfetto/trace/ftrace/kmem.proto",
+    "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
+    "protos/perfetto/trace/ftrace/mdss.proto",
+    "protos/perfetto/trace/ftrace/mm_event.proto",
+    "protos/perfetto/trace/ftrace/oom.proto",
+    "protos/perfetto/trace/ftrace/power.proto",
+    "protos/perfetto/trace/ftrace/raw_syscalls.proto",
+    "protos/perfetto/trace/ftrace/regulator.proto",
+    "protos/perfetto/trace/ftrace/sched.proto",
+    "protos/perfetto/trace/ftrace/sde.proto",
+    "protos/perfetto/trace/ftrace/signal.proto",
+    "protos/perfetto/trace/ftrace/sync.proto",
+    "protos/perfetto/trace/ftrace/systrace.proto",
+    "protos/perfetto/trace/ftrace/task.proto",
+    "protos/perfetto/trace/ftrace/test_bundle_wrapper.proto",
+    "protos/perfetto/trace/ftrace/vmscan.proto",
+    "protos/perfetto/trace/ftrace/workqueue.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/ftrace/binder.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/block.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/cgroup.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/clk.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/compaction.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/ext4.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/f2fs.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/fence.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/filemap.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/ftrace.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/generic.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/i2c.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/ipi.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/irq.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/kmem.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/lowmemorykiller.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/mdss.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/mm_event.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/oom.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/power.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/raw_syscalls.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/regulator.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/sched.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/sde.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/signal.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/sync.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/systrace.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/task.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/test_bundle_wrapper.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/vmscan.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ftrace/workqueue.gen.cc",
+  ],
+}
+
+// GN: //protos/perfetto/trace/ftrace:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/ftrace/binder.proto",
+    "protos/perfetto/trace/ftrace/block.proto",
+    "protos/perfetto/trace/ftrace/cgroup.proto",
+    "protos/perfetto/trace/ftrace/clk.proto",
+    "protos/perfetto/trace/ftrace/compaction.proto",
+    "protos/perfetto/trace/ftrace/ext4.proto",
+    "protos/perfetto/trace/ftrace/f2fs.proto",
+    "protos/perfetto/trace/ftrace/fence.proto",
+    "protos/perfetto/trace/ftrace/filemap.proto",
+    "protos/perfetto/trace/ftrace/ftrace.proto",
+    "protos/perfetto/trace/ftrace/ftrace_event.proto",
+    "protos/perfetto/trace/ftrace/ftrace_event_bundle.proto",
+    "protos/perfetto/trace/ftrace/ftrace_stats.proto",
+    "protos/perfetto/trace/ftrace/generic.proto",
+    "protos/perfetto/trace/ftrace/i2c.proto",
+    "protos/perfetto/trace/ftrace/ipi.proto",
+    "protos/perfetto/trace/ftrace/irq.proto",
+    "protos/perfetto/trace/ftrace/kmem.proto",
+    "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
+    "protos/perfetto/trace/ftrace/mdss.proto",
+    "protos/perfetto/trace/ftrace/mm_event.proto",
+    "protos/perfetto/trace/ftrace/oom.proto",
+    "protos/perfetto/trace/ftrace/power.proto",
+    "protos/perfetto/trace/ftrace/raw_syscalls.proto",
+    "protos/perfetto/trace/ftrace/regulator.proto",
+    "protos/perfetto/trace/ftrace/sched.proto",
+    "protos/perfetto/trace/ftrace/sde.proto",
+    "protos/perfetto/trace/ftrace/signal.proto",
+    "protos/perfetto/trace/ftrace/sync.proto",
+    "protos/perfetto/trace/ftrace/systrace.proto",
+    "protos/perfetto/trace/ftrace/task.proto",
+    "protos/perfetto/trace/ftrace/test_bundle_wrapper.proto",
+    "protos/perfetto/trace/ftrace/vmscan.proto",
+    "protos/perfetto/trace/ftrace/workqueue.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/ftrace/binder.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/block.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/cgroup.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/clk.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/compaction.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/ext4.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/f2fs.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/fence.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/filemap.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/ftrace.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/generic.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/i2c.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/ipi.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/irq.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/kmem.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/lowmemorykiller.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/mdss.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/mm_event.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/oom.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/power.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/raw_syscalls.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/regulator.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/sched.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/sde.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/signal.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/sync.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/systrace.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/task.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/test_bundle_wrapper.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/vmscan.gen.h",
+    "external/perfetto/protos/perfetto/trace/ftrace/workqueue.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //protos/perfetto/trace/ftrace:lite
 genrule {
   name: "perfetto_protos_perfetto_trace_ftrace_lite_gen",
@@ -3074,6 +3564,58 @@
   ],
 }
 
+// GN: //protos/perfetto/trace/gpu:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_gpu_cpp_gen",
+  srcs: [
+    "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+    "protos/perfetto/trace/gpu/gpu_log.proto",
+    "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+    "protos/perfetto/trace/gpu/vulkan_api_event.proto",
+    "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.gen.cc",
+    "external/perfetto/protos/perfetto/trace/gpu/gpu_log.gen.cc",
+    "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.gen.cc",
+    "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.gen.cc",
+    "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.gen.cc",
+  ],
+}
+
+// GN: //protos/perfetto/trace/gpu:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_gpu_cpp_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+    "protos/perfetto/trace/gpu/gpu_log.proto",
+    "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+    "protos/perfetto/trace/gpu/vulkan_api_event.proto",
+    "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.gen.h",
+    "external/perfetto/protos/perfetto/trace/gpu/gpu_log.gen.h",
+    "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.gen.h",
+    "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.gen.h",
+    "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //protos/perfetto/trace/gpu:lite
 genrule {
   name: "perfetto_protos_perfetto_trace_gpu_lite_gen",
@@ -3081,6 +3623,7 @@
     "protos/perfetto/trace/gpu/gpu_counter_event.proto",
     "protos/perfetto/trace/gpu/gpu_log.proto",
     "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+    "protos/perfetto/trace/gpu/vulkan_api_event.proto",
     "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
   ],
   tools: [
@@ -3091,6 +3634,7 @@
     "external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.pb.cc",
     "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pb.cc",
     "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pb.cc",
+    "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.pb.cc",
     "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pb.cc",
   ],
 }
@@ -3102,6 +3646,7 @@
     "protos/perfetto/trace/gpu/gpu_counter_event.proto",
     "protos/perfetto/trace/gpu/gpu_log.proto",
     "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+    "protos/perfetto/trace/gpu/vulkan_api_event.proto",
     "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
   ],
   tools: [
@@ -3112,6 +3657,7 @@
     "external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.pb.h",
     "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pb.h",
     "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pb.h",
+    "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.pb.h",
     "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pb.h",
   ],
   export_include_dirs: [
@@ -3127,6 +3673,7 @@
     "protos/perfetto/trace/gpu/gpu_counter_event.proto",
     "protos/perfetto/trace/gpu/gpu_log.proto",
     "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+    "protos/perfetto/trace/gpu/vulkan_api_event.proto",
     "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
   ],
   tools: [
@@ -3138,6 +3685,7 @@
     "external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.cc",
   ],
 }
@@ -3149,6 +3697,7 @@
     "protos/perfetto/trace/gpu/gpu_counter_event.proto",
     "protos/perfetto/trace/gpu/gpu_log.proto",
     "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+    "protos/perfetto/trace/gpu/vulkan_api_event.proto",
     "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
   ],
   tools: [
@@ -3160,6 +3709,7 @@
     "external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.pbzero.h",
     "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pbzero.h",
     "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/gpu/vulkan_api_event.pbzero.h",
     "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h",
   ],
   export_include_dirs: [
@@ -3168,6 +3718,42 @@
   ],
 }
 
+// GN: //protos/perfetto/trace/interned_data:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_interned_data_cpp_gen",
+  srcs: [
+    "protos/perfetto/trace/interned_data/interned_data.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/interned_data/interned_data.gen.cc",
+  ],
+}
+
+// GN: //protos/perfetto/trace/interned_data:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_interned_data_cpp_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/interned_data/interned_data.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/interned_data/interned_data.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //protos/perfetto/trace/interned_data:lite
 genrule {
   name: "perfetto_protos_perfetto_trace_interned_data_lite_gen",
@@ -3238,6 +3824,50 @@
   ],
 }
 
+// GN: //protos/perfetto/trace:minimal_cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_minimal_cpp_gen",
+  srcs: [
+    "protos/perfetto/trace/clock_snapshot.proto",
+    "protos/perfetto/trace/system_info.proto",
+    "protos/perfetto/trace/trigger.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/clock_snapshot.gen.cc",
+    "external/perfetto/protos/perfetto/trace/system_info.gen.cc",
+    "external/perfetto/protos/perfetto/trace/trigger.gen.cc",
+  ],
+}
+
+// GN: //protos/perfetto/trace:minimal_cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_minimal_cpp_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/clock_snapshot.proto",
+    "protos/perfetto/trace/system_info.proto",
+    "protos/perfetto/trace/trigger.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/clock_snapshot.gen.h",
+    "external/perfetto/protos/perfetto/trace/system_info.gen.h",
+    "external/perfetto/protos/perfetto/trace/trigger.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //protos/perfetto/trace:minimal_lite
 genrule {
   name: "perfetto_protos_perfetto_trace_minimal_lite_gen",
@@ -3324,6 +3954,54 @@
   ],
 }
 
+// GN: //protos/perfetto/trace:non_minimal_cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_non_minimal_cpp_gen",
+  srcs: [
+    "protos/perfetto/trace/test_event.proto",
+    "protos/perfetto/trace/trace.proto",
+    "protos/perfetto/trace/trace_packet.proto",
+    "protos/perfetto/trace/trace_packet_defaults.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/test_event.gen.cc",
+    "external/perfetto/protos/perfetto/trace/trace.gen.cc",
+    "external/perfetto/protos/perfetto/trace/trace_packet.gen.cc",
+    "external/perfetto/protos/perfetto/trace/trace_packet_defaults.gen.cc",
+  ],
+}
+
+// GN: //protos/perfetto/trace:non_minimal_cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_non_minimal_cpp_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/test_event.proto",
+    "protos/perfetto/trace/trace.proto",
+    "protos/perfetto/trace/trace_packet.proto",
+    "protos/perfetto/trace/trace_packet_defaults.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/test_event.gen.h",
+    "external/perfetto/protos/perfetto/trace/trace.gen.h",
+    "external/perfetto/protos/perfetto/trace/trace_packet.gen.h",
+    "external/perfetto/protos/perfetto/trace/trace_packet_defaults.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //protos/perfetto/trace:non_minimal_lite
 genrule {
   name: "perfetto_protos_perfetto_trace_non_minimal_lite_gen",
@@ -3418,6 +4096,42 @@
   ],
 }
 
+// GN: //protos/perfetto/trace/perfetto:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_perfetto_cpp_gen",
+  srcs: [
+    "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/perfetto/perfetto_metatrace.gen.cc",
+  ],
+}
+
+// GN: //protos/perfetto/trace/perfetto:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/perfetto/perfetto_metatrace.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //protos/perfetto/trace/perfetto:lite
 genrule {
   name: "perfetto_protos_perfetto_trace_perfetto_lite_gen",
@@ -3488,6 +4202,46 @@
   ],
 }
 
+// GN: //protos/perfetto/trace/power:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_power_cpp_gen",
+  srcs: [
+    "protos/perfetto/trace/power/battery_counters.proto",
+    "protos/perfetto/trace/power/power_rails.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/power/battery_counters.gen.cc",
+    "external/perfetto/protos/perfetto/trace/power/power_rails.gen.cc",
+  ],
+}
+
+// GN: //protos/perfetto/trace/power:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_power_cpp_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/power/battery_counters.proto",
+    "protos/perfetto/trace/power/power_rails.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/power/battery_counters.gen.h",
+    "external/perfetto/protos/perfetto/trace/power/power_rails.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //protos/perfetto/trace/power:lite
 genrule {
   name: "perfetto_protos_perfetto_trace_power_lite_gen",
@@ -3602,6 +4356,50 @@
   ],
 }
 
+// GN: //protos/perfetto/trace/profiling:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_profiling_cpp_gen",
+  srcs: [
+    "protos/perfetto/trace/profiling/heap_graph.proto",
+    "protos/perfetto/trace/profiling/profile_common.proto",
+    "protos/perfetto/trace/profiling/profile_packet.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/profiling/heap_graph.gen.cc",
+    "external/perfetto/protos/perfetto/trace/profiling/profile_common.gen.cc",
+    "external/perfetto/protos/perfetto/trace/profiling/profile_packet.gen.cc",
+  ],
+}
+
+// GN: //protos/perfetto/trace/profiling:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_profiling_cpp_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/profiling/heap_graph.proto",
+    "protos/perfetto/trace/profiling/profile_common.proto",
+    "protos/perfetto/trace/profiling/profile_packet.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/profiling/heap_graph.gen.h",
+    "external/perfetto/protos/perfetto/trace/profiling/profile_common.gen.h",
+    "external/perfetto/protos/perfetto/trace/profiling/profile_packet.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //protos/perfetto/trace/profiling:lite
 genrule {
   name: "perfetto_protos_perfetto_trace_profiling_lite_gen",
@@ -3688,6 +4486,46 @@
   ],
 }
 
+// GN: //protos/perfetto/trace/ps:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_ps_cpp_gen",
+  srcs: [
+    "protos/perfetto/trace/ps/process_stats.proto",
+    "protos/perfetto/trace/ps/process_tree.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/ps/process_stats.gen.cc",
+    "external/perfetto/protos/perfetto/trace/ps/process_tree.gen.cc",
+  ],
+}
+
+// GN: //protos/perfetto/trace/ps:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_ps_cpp_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/ps/process_stats.proto",
+    "protos/perfetto/trace/ps/process_tree.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/ps/process_stats.gen.h",
+    "external/perfetto/protos/perfetto/trace/ps/process_tree.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //protos/perfetto/trace/ps:lite
 genrule {
   name: "perfetto_protos_perfetto_trace_ps_lite_gen",
@@ -3766,6 +4604,42 @@
   ],
 }
 
+// GN: //protos/perfetto/trace/sys_stats:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_sys_stats_cpp_gen",
+  srcs: [
+    "protos/perfetto/trace/sys_stats/sys_stats.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/sys_stats/sys_stats.gen.cc",
+  ],
+}
+
+// GN: //protos/perfetto/trace/sys_stats:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_sys_stats_cpp_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/sys_stats/sys_stats.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/sys_stats/sys_stats.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //protos/perfetto/trace/sys_stats:lite
 genrule {
   name: "perfetto_protos_perfetto_trace_sys_stats_lite_gen",
@@ -3836,6 +4710,90 @@
   ],
 }
 
+// GN: //protos/perfetto/trace/track_event:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_track_event_cpp_gen",
+  srcs: [
+    "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
+    "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_user_event.proto",
+    "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/source_location.proto",
+    "protos/perfetto/trace/track_event/task_execution.proto",
+    "protos/perfetto/trace/track_event/thread_descriptor.proto",
+    "protos/perfetto/trace/track_event/track_descriptor.proto",
+    "protos/perfetto/trace/track_event/track_event.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.gen.cc",
+    "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_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",
+    "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.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",
+    "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.gen.cc",
+    "external/perfetto/protos/perfetto/trace/track_event/track_event.gen.cc",
+  ],
+}
+
+// GN: //protos/perfetto/trace/track_event:cpp
+genrule {
+  name: "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
+    "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_user_event.proto",
+    "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/source_location.proto",
+    "protos/perfetto/trace/track_event/task_execution.proto",
+    "protos/perfetto/trace/track_event/thread_descriptor.proto",
+    "protos/perfetto/trace/track_event/track_descriptor.proto",
+    "protos/perfetto/trace/track_event/track_event.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.gen.h",
+    "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_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",
+    "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.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",
+    "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.gen.h",
+    "external/perfetto/protos/perfetto/trace/track_event/track_event.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //protos/perfetto/trace/track_event:lite
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_lite_gen",
@@ -4687,6 +5645,7 @@
   name: "perfetto_src_trace_processor_db_unittests",
   srcs: [
     "src/trace_processor/db/bit_vector_unittest.cc",
+    "src/trace_processor/db/compare_unittest.cc",
     "src/trace_processor/db/row_map_unittest.cc",
     "src/trace_processor/db/sparse_vector_unittest.cc",
   ],
@@ -4748,6 +5707,14 @@
   ],
 }
 
+// GN: //src/trace_processor:protozero_to_text
+filegroup {
+  name: "perfetto_src_trace_processor_protozero_to_text",
+  srcs: [
+    "src/trace_processor/protozero_to_text.cc",
+  ],
+}
+
 // GN: //src/trace_processor/sqlite:sqlite
 filegroup {
   name: "perfetto_src_trace_processor_sqlite_sqlite",
@@ -4769,9 +5736,20 @@
   ],
 }
 
-// GN: //src/trace_processor:storage
+// GN: //src/trace_processor:storage_full
 filegroup {
-  name: "perfetto_src_trace_processor_storage",
+  name: "perfetto_src_trace_processor_storage_full",
+  srcs: [
+    "src/trace_processor/importers/proto/graphics_event_module.cc",
+    "src/trace_processor/importers/proto/graphics_event_parser.cc",
+    "src/trace_processor/importers/proto/vulkan_memory_tracker.cc",
+    "src/trace_processor/register_additional_modules.cc",
+  ],
+}
+
+// GN: //src/trace_processor:storage_minimal
+filegroup {
+  name: "perfetto_src_trace_processor_storage_minimal",
   srcs: [
     "src/trace_processor/args_tracker.cc",
     "src/trace_processor/binder_tracker.cc",
@@ -4782,6 +5760,8 @@
     "src/trace_processor/gzip_trace_parser.cc",
     "src/trace_processor/heap_profile_tracker.cc",
     "src/trace_processor/importers/ftrace/ftrace_descriptors.cc",
+    "src/trace_processor/importers/ftrace/ftrace_module.cc",
+    "src/trace_processor/importers/ftrace/ftrace_module_impl.cc",
     "src/trace_processor/importers/ftrace/ftrace_parser.cc",
     "src/trace_processor/importers/ftrace/ftrace_tokenizer.cc",
     "src/trace_processor/importers/ftrace/sched_event_tracker.cc",
@@ -4789,17 +5769,18 @@
     "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc",
     "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc",
     "src/trace_processor/importers/fuchsia/fuchsia_trace_utils.cc",
+    "src/trace_processor/importers/proto/android_probes_module.cc",
     "src/trace_processor/importers/proto/android_probes_parser.cc",
     "src/trace_processor/importers/proto/args_table_utils.cc",
-    "src/trace_processor/importers/proto/graphics_event_module.cc",
-    "src/trace_processor/importers/proto/graphics_event_parser.cc",
     "src/trace_processor/importers/proto/heap_graph_module.cc",
     "src/trace_processor/importers/proto/heap_graph_tracker.cc",
     "src/trace_processor/importers/proto/heap_graph_walker.cc",
     "src/trace_processor/importers/proto/proto_importer_module.cc",
     "src/trace_processor/importers/proto/proto_trace_parser.cc",
     "src/trace_processor/importers/proto/proto_trace_tokenizer.cc",
+    "src/trace_processor/importers/proto/system_probes_module.cc",
     "src/trace_processor/importers/proto/system_probes_parser.cc",
+    "src/trace_processor/importers/proto/track_event_module.cc",
     "src/trace_processor/importers/proto/track_event_parser.cc",
     "src/trace_processor/importers/proto/track_event_tokenizer.cc",
     "src/trace_processor/importers/systrace/systrace_parser.cc",
@@ -4815,7 +5796,6 @@
     "src/trace_processor/trace_storage.cc",
     "src/trace_processor/track_tracker.cc",
     "src/trace_processor/virtual_destructors.cc",
-    "src/trace_processor/vulkan_memory_tracker.cc",
   ],
 }
 
@@ -4837,7 +5817,6 @@
   name: "perfetto_src_trace_processor_unittests",
   srcs: [
     "src/trace_processor/args_table_unittest.cc",
-    "src/trace_processor/basic_types_unittest.cc",
     "src/trace_processor/clock_tracker_unittest.cc",
     "src/trace_processor/event_tracker_unittest.cc",
     "src/trace_processor/filtered_row_index_unittest.cc",
@@ -4853,6 +5832,7 @@
     "src/trace_processor/null_term_string_view_unittest.cc",
     "src/trace_processor/process_table_unittest.cc",
     "src/trace_processor/process_tracker_unittest.cc",
+    "src/trace_processor/protozero_to_text_unittests.cc",
     "src/trace_processor/sched_slice_table_unittest.cc",
     "src/trace_processor/slice_tracker_unittest.cc",
     "src/trace_processor/span_join_operator_table_unittest.cc",
@@ -4950,6 +5930,42 @@
   ],
 }
 
+// GN: //src/traced/probes/ftrace:test_messages_cpp
+genrule {
+  name: "perfetto_src_traced_probes_ftrace_test_messages_cpp_gen",
+  srcs: [
+    "src/traced/probes/ftrace/test/test_messages.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/src/traced/probes/ftrace/test/test_messages.gen.cc",
+  ],
+}
+
+// GN: //src/traced/probes/ftrace:test_messages_cpp
+genrule {
+  name: "perfetto_src_traced_probes_ftrace_test_messages_cpp_gen_headers",
+  srcs: [
+    "src/traced/probes/ftrace/test/test_messages.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=wrapper_namespace=gen:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/src/traced/probes/ftrace/test/test_messages.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
 // GN: //src/traced/probes/ftrace:test_messages_lite
 genrule {
   name: "perfetto_src_traced_probes_ftrace_test_messages_lite_gen",
@@ -5496,33 +6512,23 @@
     ":perfetto_include_perfetto_tracing_core_forward_decls",
     ":perfetto_include_perfetto_tracing_tracing",
     ":perfetto_protos_perfetto_common_cpp_gen",
-    ":perfetto_protos_perfetto_common_lite_gen",
     ":perfetto_protos_perfetto_common_zero_gen",
     ":perfetto_protos_perfetto_config_android_cpp_gen",
-    ":perfetto_protos_perfetto_config_android_lite_gen",
     ":perfetto_protos_perfetto_config_android_zero_gen",
     ":perfetto_protos_perfetto_config_cpp_gen",
     ":perfetto_protos_perfetto_config_ftrace_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_lite_gen",
     ":perfetto_protos_perfetto_config_ftrace_zero_gen",
     ":perfetto_protos_perfetto_config_gpu_cpp_gen",
-    ":perfetto_protos_perfetto_config_gpu_lite_gen",
     ":perfetto_protos_perfetto_config_gpu_zero_gen",
     ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
-    ":perfetto_protos_perfetto_config_inode_file_lite_gen",
     ":perfetto_protos_perfetto_config_inode_file_zero_gen",
-    ":perfetto_protos_perfetto_config_lite_gen",
     ":perfetto_protos_perfetto_config_power_cpp_gen",
-    ":perfetto_protos_perfetto_config_power_lite_gen",
     ":perfetto_protos_perfetto_config_power_zero_gen",
     ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_process_stats_lite_gen",
     ":perfetto_protos_perfetto_config_process_stats_zero_gen",
     ":perfetto_protos_perfetto_config_profiling_cpp_gen",
-    ":perfetto_protos_perfetto_config_profiling_lite_gen",
     ":perfetto_protos_perfetto_config_profiling_zero_gen",
     ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_lite_gen",
     ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_cpp_gen",
@@ -5530,34 +6536,34 @@
     ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
     ":perfetto_protos_perfetto_metrics_android_zero_gen",
     ":perfetto_protos_perfetto_metrics_zero_gen",
-    ":perfetto_protos_perfetto_trace_android_lite_gen",
+    ":perfetto_protos_perfetto_trace_android_cpp_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
-    ":perfetto_protos_perfetto_trace_chrome_lite_gen",
+    ":perfetto_protos_perfetto_trace_chrome_cpp_gen",
     ":perfetto_protos_perfetto_trace_chrome_zero_gen",
-    ":perfetto_protos_perfetto_trace_filesystem_lite_gen",
+    ":perfetto_protos_perfetto_trace_filesystem_cpp_gen",
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
-    ":perfetto_protos_perfetto_trace_ftrace_lite_gen",
+    ":perfetto_protos_perfetto_trace_ftrace_cpp_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_trace_gpu_lite_gen",
+    ":perfetto_protos_perfetto_trace_gpu_cpp_gen",
     ":perfetto_protos_perfetto_trace_gpu_zero_gen",
-    ":perfetto_protos_perfetto_trace_interned_data_lite_gen",
+    ":perfetto_protos_perfetto_trace_interned_data_cpp_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
-    ":perfetto_protos_perfetto_trace_minimal_lite_gen",
+    ":perfetto_protos_perfetto_trace_minimal_cpp_gen",
     ":perfetto_protos_perfetto_trace_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_lite_gen",
+    ":perfetto_protos_perfetto_trace_non_minimal_cpp_gen",
     ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_lite_gen",
+    ":perfetto_protos_perfetto_trace_perfetto_cpp_gen",
     ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
-    ":perfetto_protos_perfetto_trace_power_lite_gen",
+    ":perfetto_protos_perfetto_trace_power_cpp_gen",
     ":perfetto_protos_perfetto_trace_power_zero_gen",
     ":perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen",
-    ":perfetto_protos_perfetto_trace_profiling_lite_gen",
+    ":perfetto_protos_perfetto_trace_profiling_cpp_gen",
     ":perfetto_protos_perfetto_trace_profiling_zero_gen",
-    ":perfetto_protos_perfetto_trace_ps_lite_gen",
+    ":perfetto_protos_perfetto_trace_ps_cpp_gen",
     ":perfetto_protos_perfetto_trace_ps_zero_gen",
-    ":perfetto_protos_perfetto_trace_sys_stats_lite_gen",
+    ":perfetto_protos_perfetto_trace_sys_stats_cpp_gen",
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
-    ":perfetto_protos_perfetto_trace_track_event_lite_gen",
+    ":perfetto_protos_perfetto_trace_track_event_cpp_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_src_android_internal_headers",
     ":perfetto_src_android_internal_lazy_library_loader",
@@ -5598,9 +6604,11 @@
     ":perfetto_src_trace_processor_lib",
     ":perfetto_src_trace_processor_metrics_lib",
     ":perfetto_src_trace_processor_metrics_unittests",
+    ":perfetto_src_trace_processor_protozero_to_text",
     ":perfetto_src_trace_processor_sqlite_sqlite",
     ":perfetto_src_trace_processor_sqlite_unittests",
-    ":perfetto_src_trace_processor_storage",
+    ":perfetto_src_trace_processor_storage_full",
+    ":perfetto_src_trace_processor_storage_minimal",
     ":perfetto_src_trace_processor_tables_tables",
     ":perfetto_src_trace_processor_tables_unittests",
     ":perfetto_src_trace_processor_unittests",
@@ -5611,6 +6619,7 @@
     ":perfetto_src_traced_probes_filesystem_unittests",
     ":perfetto_src_traced_probes_ftrace_format_parser",
     ":perfetto_src_traced_probes_ftrace_ftrace",
+    ":perfetto_src_traced_probes_ftrace_test_messages_cpp_gen",
     ":perfetto_src_traced_probes_ftrace_test_messages_lite_gen",
     ":perfetto_src_traced_probes_ftrace_test_messages_zero_gen",
     ":perfetto_src_traced_probes_ftrace_test_support",
@@ -5645,37 +6654,28 @@
   ],
   static_libs: [
     "libgmock",
+    "libgtest",
   ],
   generated_headers: [
     "gen_merged_sql_metrics",
     "perfetto_protos_perfetto_common_cpp_gen_headers",
-    "perfetto_protos_perfetto_common_lite_gen_headers",
     "perfetto_protos_perfetto_common_zero_gen_headers",
     "perfetto_protos_perfetto_config_android_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_android_lite_gen_headers",
     "perfetto_protos_perfetto_config_android_zero_gen_headers",
     "perfetto_protos_perfetto_config_cpp_gen_headers",
     "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
     "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
     "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
     "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
     "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_lite_gen_headers",
     "perfetto_protos_perfetto_config_power_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_power_lite_gen_headers",
     "perfetto_protos_perfetto_config_power_zero_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
     "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
     "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
     "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
     "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_cpp_gen_headers",
@@ -5683,34 +6683,34 @@
     "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
     "perfetto_protos_perfetto_metrics_android_zero_gen_headers",
     "perfetto_protos_perfetto_metrics_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_android_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_android_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_gpu_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_interned_data_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_minimal_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_non_minimal_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_power_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_power_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_power_zero_gen_headers",
     "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_profiling_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_profiling_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_ps_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_ps_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_sys_stats_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_sys_stats_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
     "perfetto_src_ipc_test_messages_cpp_gen_headers",
     "perfetto_src_ipc_test_messages_ipc_gen_headers",
@@ -5718,6 +6718,7 @@
     "perfetto_src_protozero_testing_messages_cpp_gen_headers",
     "perfetto_src_protozero_testing_messages_lite_gen_headers",
     "perfetto_src_protozero_testing_messages_zero_gen_headers",
+    "perfetto_src_traced_probes_ftrace_test_messages_cpp_gen_headers",
     "perfetto_src_traced_probes_ftrace_test_messages_lite_gen_headers",
     "perfetto_src_traced_probes_ftrace_test_messages_zero_gen_headers",
   ],
@@ -5817,7 +6818,8 @@
     ":perfetto_src_trace_processor_lib",
     ":perfetto_src_trace_processor_metrics_lib",
     ":perfetto_src_trace_processor_sqlite_sqlite",
-    ":perfetto_src_trace_processor_storage",
+    ":perfetto_src_trace_processor_storage_full",
+    ":perfetto_src_trace_processor_storage_minimal",
     ":perfetto_src_trace_processor_tables_tables",
     "src/trace_processor/proto_to_json.cc",
     "src/trace_processor/trace_processor_shell.cc",
@@ -5923,7 +6925,8 @@
     ":perfetto_src_trace_processor_lib",
     ":perfetto_src_trace_processor_metrics_lib",
     ":perfetto_src_trace_processor_sqlite_sqlite",
-    ":perfetto_src_trace_processor_storage",
+    ":perfetto_src_trace_processor_storage_full",
+    ":perfetto_src_trace_processor_storage_minimal",
     ":perfetto_src_trace_processor_tables_tables",
     ":perfetto_tools_trace_to_text_common",
     ":perfetto_tools_trace_to_text_full",
@@ -6249,37 +7252,6 @@
 // These targets are appended to the autogenerated Android.bp by tools/gen_android_bp.
 
 cc_library_static {
-  name: "perfetto_cts_deps",
-  srcs: [
-    "src/base/test/test_task_runner.cc",
-    "src/traced/probes/ftrace/cpu_reader.cc",
-    "src/traced/probes/ftrace/event_info.cc",
-    "src/traced/probes/ftrace/format_parser.cc",
-    "src/traced/probes/ftrace/ftrace_controller.cc",
-    "src/traced/probes/ftrace/ftrace_procfs.cc",
-    "src/traced/probes/ftrace/proto_translation_table.cc",
-    "src/traced/probes/probes_producer.cc",
-    "test/end_to_end_integrationtest.cc",
-    "test/fake_producer.cc",
-    "test/task_runner_thread.cc",
-    "test/task_runner_thread_delegates.cc",
-    "test/test_helper.cc",
-  ],
-  shared_libs: [
-    "libprotobuf-cpp-lite",
-  ],
-  static_libs: [
-    "libgmock",
-    "libgtest",
-    "libperfetto_client_experimental",
-    "perfetto_trace_protos",
-  ],
-  defaults: [
-    "perfetto_defaults",
-  ],
-}
-
-cc_library_static {
   name: "perfetto_cts_jni_deps",
   srcs: [
     "src/base/test/test_task_runner.cc",
diff --git a/Android.bp.extras b/Android.bp.extras
index 6011886..ec61a44 100644
--- a/Android.bp.extras
+++ b/Android.bp.extras
@@ -1,37 +1,6 @@
 // These targets are appended to the autogenerated Android.bp by tools/gen_android_bp.
 
 cc_library_static {
-  name: "perfetto_cts_deps",
-  srcs: [
-    "src/base/test/test_task_runner.cc",
-    "src/traced/probes/ftrace/cpu_reader.cc",
-    "src/traced/probes/ftrace/event_info.cc",
-    "src/traced/probes/ftrace/format_parser.cc",
-    "src/traced/probes/ftrace/ftrace_controller.cc",
-    "src/traced/probes/ftrace/ftrace_procfs.cc",
-    "src/traced/probes/ftrace/proto_translation_table.cc",
-    "src/traced/probes/probes_producer.cc",
-    "test/end_to_end_integrationtest.cc",
-    "test/fake_producer.cc",
-    "test/task_runner_thread.cc",
-    "test/task_runner_thread_delegates.cc",
-    "test/test_helper.cc",
-  ],
-  shared_libs: [
-    "libprotobuf-cpp-lite",
-  ],
-  static_libs: [
-    "libgmock",
-    "libgtest",
-    "libperfetto_client_experimental",
-    "perfetto_trace_protos",
-  ],
-  defaults: [
-    "perfetto_defaults",
-  ],
-}
-
-cc_library_static {
   name: "perfetto_cts_jni_deps",
   srcs: [
     "src/base/test/test_task_runner.cc",
diff --git a/BUILD b/BUILD
index a652d39..1dde88e 100644
--- a/BUILD
+++ b/BUILD
@@ -582,6 +582,7 @@
         "src/trace_processor/db/bit_vector_iterators.h",
         "src/trace_processor/db/column.cc",
         "src/trace_processor/db/column.h",
+        "src/trace_processor/db/compare.h",
         "src/trace_processor/db/row_map.cc",
         "src/trace_processor/db/row_map.h",
         "src/trace_processor/db/sparse_vector.h",
@@ -770,9 +771,24 @@
     ],
 )
 
-# GN target: //src/trace_processor:storage
+# GN target: //src/trace_processor:storage_full
 filegroup(
-    name = "src_trace_processor_storage",
+    name = "src_trace_processor_storage_full",
+    srcs = [
+        "src/trace_processor/importers/proto/graphics_event_module.cc",
+        "src/trace_processor/importers/proto/graphics_event_module.h",
+        "src/trace_processor/importers/proto/graphics_event_parser.cc",
+        "src/trace_processor/importers/proto/graphics_event_parser.h",
+        "src/trace_processor/importers/proto/vulkan_memory_tracker.cc",
+        "src/trace_processor/importers/proto/vulkan_memory_tracker.h",
+        "src/trace_processor/register_additional_modules.cc",
+        "src/trace_processor/register_additional_modules.h",
+    ],
+)
+
+# GN target: //src/trace_processor:storage_minimal
+filegroup(
+    name = "src_trace_processor_storage_minimal",
     srcs = [
         "src/trace_processor/args_tracker.cc",
         "src/trace_processor/args_tracker.h",
@@ -793,7 +809,9 @@
         "src/trace_processor/heap_profile_tracker.h",
         "src/trace_processor/importers/ftrace/ftrace_descriptors.cc",
         "src/trace_processor/importers/ftrace/ftrace_descriptors.h",
+        "src/trace_processor/importers/ftrace/ftrace_module.cc",
         "src/trace_processor/importers/ftrace/ftrace_module.h",
+        "src/trace_processor/importers/ftrace/ftrace_module_impl.cc",
         "src/trace_processor/importers/ftrace/ftrace_parser.cc",
         "src/trace_processor/importers/ftrace/ftrace_parser.h",
         "src/trace_processor/importers/ftrace/ftrace_tokenizer.cc",
@@ -814,16 +832,13 @@
         "src/trace_processor/importers/json/json_trace_tokenizer.h",
         "src/trace_processor/importers/json/json_trace_utils.cc",
         "src/trace_processor/importers/json/json_trace_utils.h",
+        "src/trace_processor/importers/proto/android_probes_module.cc",
         "src/trace_processor/importers/proto/android_probes_module.h",
         "src/trace_processor/importers/proto/android_probes_parser.cc",
         "src/trace_processor/importers/proto/android_probes_parser.h",
         "src/trace_processor/importers/proto/args_table_utils.cc",
         "src/trace_processor/importers/proto/args_table_utils.h",
         "src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h",
-        "src/trace_processor/importers/proto/graphics_event_module.cc",
-        "src/trace_processor/importers/proto/graphics_event_module.h",
-        "src/trace_processor/importers/proto/graphics_event_parser.cc",
-        "src/trace_processor/importers/proto/graphics_event_parser.h",
         "src/trace_processor/importers/proto/heap_graph_module.cc",
         "src/trace_processor/importers/proto/heap_graph_module.h",
         "src/trace_processor/importers/proto/heap_graph_tracker.cc",
@@ -838,9 +853,11 @@
         "src/trace_processor/importers/proto/proto_trace_parser.h",
         "src/trace_processor/importers/proto/proto_trace_tokenizer.cc",
         "src/trace_processor/importers/proto/proto_trace_tokenizer.h",
+        "src/trace_processor/importers/proto/system_probes_module.cc",
         "src/trace_processor/importers/proto/system_probes_module.h",
         "src/trace_processor/importers/proto/system_probes_parser.cc",
         "src/trace_processor/importers/proto/system_probes_parser.h",
+        "src/trace_processor/importers/proto/track_event_module.cc",
         "src/trace_processor/importers/proto/track_event_module.h",
         "src/trace_processor/importers/proto/track_event_parser.cc",
         "src/trace_processor/importers/proto/track_event_parser.h",
@@ -880,8 +897,6 @@
         "src/trace_processor/track_tracker.h",
         "src/trace_processor/variadic.h",
         "src/trace_processor/virtual_destructors.cc",
-        "src/trace_processor/vulkan_memory_tracker.cc",
-        "src/trace_processor/vulkan_memory_tracker.h",
     ],
 )
 
@@ -1928,6 +1943,7 @@
         "protos/perfetto/trace/gpu/gpu_counter_event.proto",
         "protos/perfetto/trace/gpu/gpu_log.proto",
         "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
+        "protos/perfetto/trace/gpu/vulkan_api_event.proto",
         "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
     ],
     visibility = [
@@ -2509,7 +2525,8 @@
         ":src_trace_processor_lib",
         ":src_trace_processor_metrics_lib",
         ":src_trace_processor_sqlite_sqlite",
-        ":src_trace_processor_storage",
+        ":src_trace_processor_storage_full",
+        ":src_trace_processor_storage_minimal",
         ":src_trace_processor_tables_tables",
     ],
     hdrs = [
@@ -2588,7 +2605,8 @@
         ":src_trace_processor_rpc_httpd",
         ":src_trace_processor_rpc_rpc",
         ":src_trace_processor_sqlite_sqlite",
-        ":src_trace_processor_storage",
+        ":src_trace_processor_storage_full",
+        ":src_trace_processor_storage_minimal",
         ":src_trace_processor_tables_tables",
     ],
     visibility = [
@@ -2738,7 +2756,8 @@
         ":src_trace_processor_lib",
         ":src_trace_processor_metrics_lib",
         ":src_trace_processor_sqlite_sqlite",
-        ":src_trace_processor_storage",
+        ":src_trace_processor_storage_full",
+        ":src_trace_processor_storage_minimal",
         ":src_trace_processor_tables_tables",
         ":tools_trace_to_text_common",
         ":tools_trace_to_text_full",
diff --git a/BUILD.gn b/BUILD.gn
index daf73a9..fb9647d 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -125,6 +125,12 @@
   ]
 }
 
+# The CTS code is built (but not ran) also in standalone builds. This is to
+# catch refactoring breakages earlier without having to wait for treehugger.
+if (is_android && (perfetto_build_standalone || perfetto_build_with_android)) {
+  all_targets += [ "test/cts:perfetto_cts_deps" ]
+}
+
 group("all") {
   testonly = true  # allow to build also test targets
   deps = all_targets
@@ -194,7 +200,7 @@
   # on how to use the Perfetto Client API from the android tree.
   static_library("libperfetto_client_experimental") {
     complete_static_lib = true
-    deps = [
+    public_deps = [
       "gn:default_deps",
       "src/tracing",
       "src/tracing:client_api",
@@ -216,7 +222,7 @@
     public_configs = [ "gn:public_config" ]
     deps = [
       "src/trace_processor:export_json",
-      "src/trace_processor:storage",
+      "src/trace_processor:storage_minimal",
       "src/tracing",
     ]
     configs -= [ "//build/config/compiler:chromium_code" ]
diff --git a/README.md b/README.md
index 27f653a..be4c683 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,13 @@
 
 See [www.perfetto.dev](https://www.perfetto.dev) for docs.
 
+Contributing
+------------
+See [/docs/contributing.md](docs/contributing.md) for instructions.
+
+The source-of-truth repo is [Android's Gerrit][aosp].
+The [GitHub repo](https://github.com/google/perfetto) is a read-only mirror.
+
 Bugs
 ----
 * For bugs affecting Android or the tracing internals use the internal
@@ -16,4 +23,6 @@
 ---------
 You can reach us on our [Discord channel](https://discord.gg/35ShE3A).
 If you prefer using IRC we have an experimental Discord <> IRC bridge
-synced with `#perfetto-dev` on [Freenode](https://webchat.freenode.net/).
\ No newline at end of file
+synced with `#perfetto-dev` on [Freenode](https://webchat.freenode.net/).
+
+[aosp]: https://android.googlesource.com/platform/external/perfetto/
diff --git a/docs/heapprofd.md b/docs/heapprofd.md
index fa2d2ff..1e46ce4 100644
--- a/docs/heapprofd.md
+++ b/docs/heapprofd.md
@@ -19,7 +19,7 @@
 On Linux / MacOS, use the `tools/heap_profile` script to heap profile a
 process. If you are having trouble make sure you are using the
 [latest version](
-https://raw.githubusercontent.com/catapult-project/perfetto/master/tools/heap_profile).
+https://raw.githubusercontent.com/google/perfetto/master/tools/heap_profile).
 
 See all the arguments using `tools/heap_profile -h`, or use the defaults
 and just profile a process (e.g. `system_server`):
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index 1fba09e..bed38a3 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -86,7 +86,6 @@
     "PERFETTO_TP_SYSTEM_PROBES=$enable_perfetto_trace_processor_system_probes",
     "PERFETTO_TP_ANDROID_PROBES=$enable_perfetto_trace_processor_android_probes",
     "PERFETTO_TP_HEAP_GRAPHS=$enable_perfetto_trace_processor_heap_graphs",
-    "PERFETTO_TP_GRAPHICS=$enable_perfetto_trace_processor_graphics",
     "PERFETTO_TP_JSON=$enable_perfetto_trace_processor_json",
     "PERFETTO_TP_JSON_IMPORT=$enable_perfetto_trace_processor_json_import",
     "PERFETTO_TP_FUCHSIA=$enable_perfetto_trace_processor_fuchsia",
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index 360639e..97563dc 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -227,10 +227,6 @@
   enable_perfetto_trace_processor_heap_graphs =
       enable_perfetto_trace_processor && !(build_with_chromium && is_android)
 
-  # Enables graphics event support in the trace processor.
-  enable_perfetto_trace_processor_graphics =
-      enable_perfetto_trace_processor && !(build_with_chromium && is_android)
-
   # Enables JSON support in the trace processor. Required for JSON trace import
   # and export. Importer support can also be disabled using
   # |enable_perfetto_trace_processor_json_import|.
diff --git a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
index 1b35256..004dfe0 100644
--- a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
@@ -40,7 +40,6 @@
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_SYSTEM_PROBES() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_ANDROID_PROBES() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HEAP_GRAPHS() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_GRAPHICS() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON_IMPORT() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_FUCHSIA() (1)
diff --git a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
index 1702d01..a760898 100644
--- a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
@@ -40,7 +40,6 @@
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_SYSTEM_PROBES() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_ANDROID_PROBES() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HEAP_GRAPHS() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_GRAPHICS() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON_IMPORT() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_FUCHSIA() (1)
diff --git a/include/perfetto/trace_processor/basic_types.h b/include/perfetto/trace_processor/basic_types.h
index fdab153..db67e79 100644
--- a/include/perfetto/trace_processor/basic_types.h
+++ b/include/perfetto/trace_processor/basic_types.h
@@ -84,42 +84,6 @@
     return double_value;
   }
 
-  int64_t Compare(const SqlValue& value) const {
-    // TODO(lalitm): this is almost the same as what SQLite does with the
-    // exception of comparisions between long and double - we choose (for
-    // performance reasons) to omit comparisions between them.
-    if (type != value.type)
-      return type - value.type;
-
-    switch (type) {
-      case Type::kNull:
-        return 0;
-      case Type::kLong:
-        return long_value - value.long_value;
-      case Type::kDouble: {
-        return double_value < value.double_value
-                   ? -1
-                   : (double_value > value.double_value ? 1 : 0);
-      }
-      case Type::kString:
-        return strcmp(string_value, value.string_value);
-      case Type::kBytes: {
-        size_t bytes = std::min(bytes_count, value.bytes_count);
-        int ret = memcmp(bytes_value, value.bytes_value, bytes);
-        if (ret != 0)
-          return ret;
-        return static_cast<int64_t>(bytes_count - value.bytes_count);
-      }
-    }
-    PERFETTO_FATAL("For GCC");
-  }
-  bool operator==(const SqlValue& value) const { return Compare(value) == 0; }
-  bool operator<(const SqlValue& value) const { return Compare(value) < 0; }
-  bool operator!=(const SqlValue& value) const { return !(*this == value); }
-  bool operator>=(const SqlValue& value) const { return !(*this < value); }
-  bool operator<=(const SqlValue& value) const { return !(value < *this); }
-  bool operator>(const SqlValue& value) const { return value < *this; }
-
   bool is_null() const { return type == Type::kNull; }
 
   // Up to 1 of these fields can be accessed depending on |type|.
diff --git a/include/perfetto/tracing/internal/track_event_macros.h b/include/perfetto/tracing/internal/track_event_macros.h
index 9b5bcff..f291186 100644
--- a/include/perfetto/tracing/internal/track_event_macros.h
+++ b/include/perfetto/tracing/internal/track_event_macros.h
@@ -90,24 +90,11 @@
 
 // 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, name, ...)                    \
-  ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::CallIfCategoryEnabled<        \
-      PERFETTO_GET_CATEGORY_INDEX(category)>([&](uint32_t instances) {        \
-    /* Check that |name| is a static string. If this fails, you probably want \
-     * to use "constexpr const char*" if the string is computed by an         \
-     * expression, or something like this if the string is fully dynamic:     \
-     *                                                                        \
-     *   TRACE_EVENT("category", nullptr, [&](perfetto::EventContext ctx) {   \
-     *     ctx.event()->set_name(dynamic_name);                               \
-     *   }                                                                    \
-     */                                                                       \
-    static_assert(                                                            \
-        (name) == nullptr || (name) != nullptr,                               \
-        "Track event name must be a (constexpr) static string. Use a trace "  \
-        "lambda if you need a dynamic name (see above).");                    \
-    ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::TraceForCategory<           \
-        PERFETTO_GET_CATEGORY_INDEX(category)>(instances, name,               \
-                                               ##__VA_ARGS__);                \
+#define PERFETTO_INTERNAL_TRACK_EVENT(category, ...)                      \
+  ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::CallIfCategoryEnabled<    \
+      PERFETTO_GET_CATEGORY_INDEX(category)>([&](uint32_t instances) {    \
+    ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::TraceForCategory<       \
+        PERFETTO_GET_CATEGORY_INDEX(category)>(instances, ##__VA_ARGS__); \
   })
 
 // Generate a unique variable name with a given prefix.
diff --git a/include/perfetto/tracing/track_event.h b/include/perfetto/tracing/track_event.h
index 245b31d..438d451 100644
--- a/include/perfetto/tracing/track_event.h
+++ b/include/perfetto/tracing/track_event.h
@@ -141,6 +141,15 @@
 // Begin a thread-scoped slice under |category| with the title |name|. Both
 // strings must be static constants. The track event is only recorded if
 // |category| is enabled for a tracing session.
+//
+// |name| must be a string with static lifetime (i.e., the same
+// address must not be used for a different event name in the future). If you
+// want to use a dynamically allocated name, do this:
+//
+//  TRACE_EVENT("category", nullptr, [&](perfetto::EventContext ctx) {
+//    ctx.event()->set_name(dynamic_name);
+//  });
+//
 #define TRACE_EVENT_BEGIN(category, name, ...) \
   PERFETTO_INTERNAL_TRACK_EVENT(               \
       category, name,                          \
diff --git a/include/perfetto/tracing/track_event_interned_data_index.h b/include/perfetto/tracing/track_event_interned_data_index.h
index 9d8935a..be4c128 100644
--- a/include/perfetto/tracing/track_event_interned_data_index.h
+++ b/include/perfetto/tracing/track_event_interned_data_index.h
@@ -20,6 +20,7 @@
 #include "perfetto/tracing/internal/track_event_internal.h"
 
 #include "perfetto/base/compiler.h"
+#include "perfetto/tracing/event_context.h"
 
 #include <map>
 #include <type_traits>
diff --git a/infra/ci/frontend/static/script.js b/infra/ci/frontend/static/script.js
index d6fe73e..4a537c6 100644
--- a/infra/ci/frontend/static/script.js
+++ b/infra/ci/frontend/static/script.js
@@ -130,7 +130,7 @@
   const logUrl = 'https://goto.google.com/perfetto-ci-logs-';
   const docsUrl = 'https://docs.perfetto.dev/#/continuous-integration';
   return m('header',
-    m('h1', 'Perfetto ', m('span', 'CI')),
+    m('a[href=/#!/cls]', m('h1', 'Perfetto ', m('span', 'CI'))),
     m('nav',
       m(`div${active('cls')}`, m('a[href=/#!/cls]', 'CLs')),
       m(`div${active('jobs')}`, m('a[href=/#!/jobs]', 'Jobs')),
diff --git a/infra/git_mirror_bot/Makefile b/infra/git_mirror_bot/Makefile
index dedaad9..be1af35 100644
--- a/infra/git_mirror_bot/Makefile
+++ b/infra/git_mirror_bot/Makefile
@@ -12,8 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-PROJECT="perfetto-ci"
-VM_NAME="perfetto-ci-git-mirror-bot"
+PROJECT="perfetto-aosp-to-github-bot"
+VM_NAME="perfetto-aosp-to-github-bot"
 ZONE="us-central1-c"
 
 ssh:
@@ -26,23 +26,19 @@
 		instances delete $(VM_NAME) \
 		--zone $(ZONE)
 
-deploy_key:
-	@echo "Download the deploy_key from the teams drive (go/perfetto_deploy_key)"
-	@exit 1
-
-start: deploy_key
+start:
 	gcloud compute \
 		--project $(PROJECT) \
 		instances create $(VM_NAME) \
 		--zone $(ZONE) \
-		--machine-type "n1-highcpu-16" \
+		--machine-type "n1-standard-2" \
 		--subnet "default" \
 		--maintenance-policy "MIGRATE" \
-		--image "debian-9-stretch-v20170918" \
-		--image-project "debian-cloud" \
+		--image "debian-9-drawfork-v20191004" \
+		--image-project "eip-images" \
 		--boot-disk-size "10" \
 		--boot-disk-type "pd-standard" \
 		--boot-disk-device-name "perfetto-ci-git-mirror-bot" \
-		--metadata-from-file=startup-script=startup-script.sh,deploy_key=deploy_key,main=mirror_aosp_to_ghub_repo.py
+		--metadata-from-file=startup-script=startup-script.sh,main=mirror_aosp_to_ghub_repo.py
 
 .PHONY: ssh stop start
diff --git a/infra/git_mirror_bot/mirror_aosp_to_ghub_repo.py b/infra/git_mirror_bot/mirror_aosp_to_ghub_repo.py
index fa17382..e254014 100644
--- a/infra/git_mirror_bot/mirror_aosp_to_ghub_repo.py
+++ b/infra/git_mirror_bot/mirror_aosp_to_ghub_repo.py
@@ -34,14 +34,14 @@
 
 CUR_DIR = os.path.dirname(os.path.abspath(__file__))
 GIT_UPSTREAM = 'https://android.googlesource.com/platform/external/perfetto/'
-GIT_MIRROR = 'git@github.com:catapult-project/perfetto.git'
+GIT_MIRROR = 'git@github.com:google/perfetto.git'
 WORKDIR = os.path.join(CUR_DIR, 'repo')
 
 # Min delay (in seconds) between two consecutive git poll cycles. This is to
 # avoid hitting gerrit API quota limits.
 POLL_PERIOD_SEC = 60
 
-# The actual deploy_key is stored into the internal team drive, undef /infra/.
+# The actual key is stored into the Google Cloud project metadata.
 ENV = {'GIT_SSH_COMMAND': 'ssh -i ' + os.path.join(CUR_DIR, 'deploy_key')}
 
 
@@ -68,7 +68,11 @@
   os.makedirs(WORKDIR)
   GitCmd('init', '--bare', '--quiet')
   GitCmd('remote', 'add', 'upstream', GIT_UPSTREAM)
-  GitCmd('config', 'remote.upstream.fetch', '+refs/*:refs/remotes/upstream/*')
+  GitCmd('config', 'remote.upstream.tagOpt', '--no-tags')
+  GitCmd('config', '--add', 'remote.upstream.fetch',
+         '+refs/heads/*:refs/remotes/upstream/heads/*')
+  GitCmd('config', '--add', 'remote.upstream.fetch',
+         '+refs/tags/*:refs/remotes/upstream/tags/*')
   GitCmd('remote', 'add', 'mirror', GIT_MIRROR, '--mirror=fetch')
 
 
@@ -90,16 +94,17 @@
   for line in all_refs.splitlines():
     ref_sha1, ref = line.split()
 
-    PREFIX = 'refs/heads/'
-    if ref.startswith(PREFIX):
-      branch = ref[len(PREFIX):]
-      current_heads['refs/heads/' + branch] = ref_sha1
+    FILTER_REGEX = r'(heads/master|heads/releases/.*|tags/v\d+\.\d+)$'
+    m = re.match('refs/' + FILTER_REGEX, ref)
+    if m is not None:
+      branch = m.group(1)
+      current_heads['refs/' + branch] = ref_sha1
       continue
 
-    PREFIX = 'refs/remotes/upstream/heads/'
-    if ref.startswith(PREFIX):
-      branch = ref[len(PREFIX):]
-      future_heads['refs/heads/' + branch] = ref_sha1
+    m = re.match('refs/remotes/upstream/' + FILTER_REGEX, ref)
+    if m is not None:
+      branch = m.group(1)
+      future_heads['refs/' + branch] = ref_sha1
       continue
 
   deleted_heads = set(current_heads) - set(future_heads)
@@ -121,7 +126,7 @@
 
   if args.push:
     logging.info('Pushing updates')
-    GitCmd('push', 'mirror', '--all', '--prune', '--force')
+    GitCmd('push', 'mirror', '--all', '--prune', '--force', '--follow-tags')
     GitCmd('gc', '--prune=all', '--aggressive', '--quiet')
   else:
     logging.info('Dry-run mode, skipping git push. Pass --push for prod mode.')
diff --git a/infra/git_mirror_bot/startup-script.sh b/infra/git_mirror_bot/startup-script.sh
index cba2d93..2ae7143 100644
--- a/infra/git_mirror_bot/startup-script.sh
+++ b/infra/git_mirror_bot/startup-script.sh
@@ -39,7 +39,8 @@
 redirect_stderr=true
 EOF
 
-curl -H Metadata-Flavor:Google "http://metadata.google.internal/computeMetadata/v1/instance/attributes/deploy_key" > /home/gitbot/deploy_key
+curl -H Metadata-Flavor:Google "http://metadata.google.internal/computeMetadata/v1/project/attributes/deploy_key" > /home/gitbot/deploy_key
+echo >> /home/gitbot/deploy_key  # metadata server strips trailing \n.
 chown gitbot /home/gitbot/deploy_key
 chmod 400 /home/gitbot/deploy_key
 
@@ -50,8 +51,3 @@
 cd /home/gitbot
 sudo -u gitbot bash -c "mkdir -p .ssh; ssh-keyscan github.com >> .ssh/known_hosts;"
 /usr/bin/supervisord -c /etc/supervisord.conf
-
-dd if=/dev/zero of=/swap bs=1M count=4k
-chmod 600 /swap
-mkswap /swap
-swapon /swap
diff --git a/infra/perfetto-site.appspot.com/index.yaml b/infra/perfetto-site.appspot.com/index.yaml
new file mode 100644
index 0000000..eb9fd6f
--- /dev/null
+++ b/infra/perfetto-site.appspot.com/index.yaml
@@ -0,0 +1,16 @@
+# Copyright (C) 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
+#
+#      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.
+
+indexes:
+# AUTOGENERATED
diff --git a/infra/perfetto-site.appspot.com/main.py b/infra/perfetto-site.appspot.com/main.py
index b42dd96..4a3618a 100644
--- a/infra/perfetto-site.appspot.com/main.py
+++ b/infra/perfetto-site.appspot.com/main.py
@@ -19,7 +19,7 @@
 import webapp2
 
 MEMCACHE_TTL_SEC = 60 * 60 * 24
-BASE = 'https://catapult-project.github.io/perfetto/%s'
+BASE = 'https://google.github.io/perfetto/%s'
 HEADERS = {
     'last-modified', 'content-type', 'content-length', 'content-encoding',
     'etag'
diff --git a/infra/perfetto-site.appspot.com/package-lock.json b/infra/perfetto-site.appspot.com/package-lock.json
index 8b57cd2..b763809 100644
--- a/infra/perfetto-site.appspot.com/package-lock.json
+++ b/infra/perfetto-site.appspot.com/package-lock.json
@@ -212,9 +212,9 @@
       "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
     },
     "lodash": {
-      "version": "4.17.11",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
-      "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
+      "version": "4.17.15",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
     },
     "marked": {
       "version": "0.3.19",
@@ -380,7 +380,7 @@
     },
     "strip-ansi": {
       "version": "3.0.1",
-      "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
       "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
       "requires": {
         "ansi-regex": "^2.0.0"
diff --git a/protos/perfetto/trace/BUILD.gn b/protos/perfetto/trace/BUILD.gn
index 850c133..ebcdfde 100644
--- a/protos/perfetto/trace/BUILD.gn
+++ b/protos/perfetto/trace/BUILD.gn
@@ -58,8 +58,18 @@
   ]
 }
 
+# This is only for tests because bloats binary size.
+group("cpp") {
+  testonly = true
+  public_deps = [
+    ":minimal_cpp",
+    ":non_minimal_cpp",
+  ]
+}
+
 perfetto_proto_library("non_minimal_@TYPE@") {
   proto_generators = [
+    "cpp",
     "lite",
     "zero",
   ]
diff --git a/protos/perfetto/trace/ftrace/BUILD.gn b/protos/perfetto/trace/ftrace/BUILD.gn
index bda3817..3fa8cc0 100644
--- a/protos/perfetto/trace/ftrace/BUILD.gn
+++ b/protos/perfetto/trace/ftrace/BUILD.gn
@@ -18,6 +18,7 @@
 
 perfetto_proto_library("@TYPE@") {
   proto_generators = [
+    "cpp",
     "zero",
     "lite",
   ]
diff --git a/protos/perfetto/trace/ftrace/sde.proto b/protos/perfetto/trace/ftrace/sde.proto
index aafa486..fbafd2e 100644
--- a/protos/perfetto/trace/ftrace/sde.proto
+++ b/protos/perfetto/trace/ftrace/sde.proto
@@ -11,4 +11,5 @@
   optional string trace_name = 2;
   optional uint32 trace_type = 3;
   optional int32 value = 4;
+  optional uint32 trace_begin = 5;
 }
diff --git a/protos/perfetto/trace/gpu/BUILD.gn b/protos/perfetto/trace/gpu/BUILD.gn
index 64b913a..fd1ba9f 100644
--- a/protos/perfetto/trace/gpu/BUILD.gn
+++ b/protos/perfetto/trace/gpu/BUILD.gn
@@ -22,6 +22,7 @@
     "gpu_counter_event.proto",
     "gpu_log.proto",
     "gpu_render_stage_event.proto",
+    "vulkan_api_event.proto",
     "vulkan_memory_event.proto",
   ]
 }
diff --git a/protos/perfetto/trace/gpu/vulkan_api_event.proto b/protos/perfetto/trace/gpu/vulkan_api_event.proto
new file mode 100644
index 0000000..b9a2a9d
--- /dev/null
+++ b/protos/perfetto/trace/gpu/vulkan_api_event.proto
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 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
+ *
+ *      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;
+
+// Message for recording the Vulkan call.
+message VulkanApiEvent {
+  oneof event { VkDebugUtilsObjectName vk_debug_utils_object_name = 1; }
+
+  // For recording vkSetDebugUtilsObjectNameEXT and
+  // vkDebugMarkerSetObjectNameEXT
+  message VkDebugUtilsObjectName {
+    optional int32 pid = 1;
+    optional uint64 vk_device = 2;
+    optional uint64 object = 3;
+    optional string object_name = 4;
+  }
+}
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 4f51daa..eeef7ac 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -3556,7 +3556,7 @@
 // TracePacket(s).
 //
 // Next reserved id: 13 (up to 15).
-// Next id: 64.
+// Next id: 66.
 message TracePacket {
   // The timestamp of the TracePacket.
   // By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
@@ -3606,6 +3606,7 @@
     GraphicsFrameEvent graphics_frame_event = 57;
     // removed field with id 62
     GpuLog gpu_log = 63;
+    VulkanApiEvent vulkan_api_event = 65;
 
     // Only used in profile packets.
     ProfiledFrameSymbols profiled_frame_symbols = 55;
@@ -4718,6 +4719,24 @@
 
 // End of protos/perfetto/trace/gpu/gpu_render_stage_event.proto
 
+// Begin of protos/perfetto/trace/gpu/vulkan_api_event.proto
+
+// Message for recording the Vulkan call.
+message VulkanApiEvent {
+  oneof event { VkDebugUtilsObjectName vk_debug_utils_object_name = 1; }
+
+  // For recording vkSetDebugUtilsObjectNameEXT and
+  // vkDebugMarkerSetObjectNameEXT
+  message VkDebugUtilsObjectName {
+    optional int32 pid = 1;
+    optional uint64 vk_device = 2;
+    optional uint64 object = 3;
+    optional string object_name = 4;
+  }
+}
+
+// End of protos/perfetto/trace/gpu/vulkan_api_event.proto
+
 // Begin of protos/perfetto/config/android/android_log_config.proto
 
 message AndroidLogConfig {
diff --git a/protos/perfetto/trace/trace_packet.proto b/protos/perfetto/trace/trace_packet.proto
index 9603776..da3b6af 100644
--- a/protos/perfetto/trace/trace_packet.proto
+++ b/protos/perfetto/trace/trace_packet.proto
@@ -33,6 +33,7 @@
 import "protos/perfetto/trace/gpu/gpu_log.proto";
 import "protos/perfetto/trace/gpu/gpu_render_stage_event.proto";
 import "protos/perfetto/trace/gpu/vulkan_memory_event.proto";
+import "protos/perfetto/trace/gpu/vulkan_api_event.proto";
 import "protos/perfetto/trace/interned_data/interned_data.proto";
 import "protos/perfetto/trace/perfetto/perfetto_metatrace.proto";
 import "protos/perfetto/trace/power/battery_counters.proto";
@@ -58,7 +59,7 @@
 // TracePacket(s).
 //
 // Next reserved id: 13 (up to 15).
-// Next id: 64.
+// Next id: 66.
 message TracePacket {
   // The timestamp of the TracePacket.
   // By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
@@ -108,6 +109,7 @@
     GraphicsFrameEvent graphics_frame_event = 57;
     VulkanMemoryEvent vulkan_memory_event = 62;
     GpuLog gpu_log = 63;
+    VulkanApiEvent vulkan_api_event = 65;
 
     // Only used in profile packets.
     ProfiledFrameSymbols profiled_frame_symbols = 55;
diff --git a/src/perfetto_cmd/BUILD.gn b/src/perfetto_cmd/BUILD.gn
index 534cdd9..969b732 100644
--- a/src/perfetto_cmd/BUILD.gn
+++ b/src/perfetto_cmd/BUILD.gn
@@ -136,8 +136,7 @@
     "../../include/perfetto/ext/base",
     "../../protos/perfetto/config:cpp",
     "../../protos/perfetto/config/ftrace:cpp",
-    "../../protos/perfetto/trace:lite",
-    "../protozero",
+    "../../protos/perfetto/trace:cpp",
     "../tracing",
   ]
   sources = [
diff --git a/src/perfetto_cmd/packet_writer_unittest.cc b/src/perfetto_cmd/packet_writer_unittest.cc
index 5736099..c1fab21 100644
--- a/src/perfetto_cmd/packet_writer_unittest.cc
+++ b/src/perfetto_cmd/packet_writer_unittest.cc
@@ -27,23 +27,22 @@
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/temp_file.h"
 #include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
 #include "src/perfetto_cmd/packet_writer.h"
 #include "test/gtest_and_gmock.h"
 
+#include "protos/perfetto/trace/test_event.gen.h"
+#include "protos/perfetto/trace/trace.gen.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
+
 namespace perfetto {
 namespace {
 
-using TracePacketZero = protos::pbzero::TracePacket;
+using TracePacketProto = protos::gen::TracePacket;
 
 template <typename F>
 TracePacket CreateTracePacket(F fill_function) {
-  protozero::HeapBuffered<TracePacketZero> msg;
-  fill_function(msg.get());
+  TracePacketProto msg;
+  fill_function(&msg);
   std::vector<uint8_t> buf = msg.SerializeAsArray();
   Slice slice = Slice::Allocate(buf.size());
   memcpy(slice.own_data(), buf.data(), buf.size());
@@ -78,7 +77,7 @@
   return s;
 }
 
-TEST(PacketWriter, FilePacketWriter) {
+TEST(PacketWriterTest, FilePacketWriter) {
   base::TempFile tmp = base::TempFile::Create();
   base::ScopedResource<FILE*, fclose, nullptr> f(
       fdopen(tmp.ReleaseFD().release(), "wb"));
@@ -88,8 +87,8 @@
 
     std::vector<perfetto::TracePacket> packets;
 
-    packets.push_back(CreateTracePacket([](TracePacketZero* msg) {
-      auto* for_testing = msg->set_for_testing();
+    packets.push_back(CreateTracePacket([](TracePacketProto* msg) {
+      auto* for_testing = msg->mutable_for_testing();
       for_testing->set_str("abc");
     }));
 
@@ -101,12 +100,12 @@
   EXPECT_TRUE(base::ReadFileStream(*f, &s));
   EXPECT_GT(s.size(), 0u);
 
-  protos::Trace trace;
+  protos::gen::Trace trace;
   EXPECT_TRUE(trace.ParseFromString(s));
-  EXPECT_EQ(trace.packet().Get(0).for_testing().str(), "abc");
+  EXPECT_EQ(trace.packet()[0].for_testing().str(), "abc");
 }
 
-TEST(PacketWriter, ZipPacketWriter) {
+TEST(PacketWriterTest, ZipPacketWriter) {
   base::TempFile tmp = base::TempFile::Create();
   base::ScopedResource<FILE*, fclose, nullptr> f(
       fdopen(tmp.ReleaseFD().release(), "wb"));
@@ -117,8 +116,8 @@
 
     std::vector<perfetto::TracePacket> packets;
 
-    packets.push_back(CreateTracePacket([](TracePacketZero* msg) {
-      auto* for_testing = msg->set_for_testing();
+    packets.push_back(CreateTracePacket([](TracePacketProto* msg) {
+      auto* for_testing = msg->mutable_for_testing();
       for_testing->set_str("abc");
     }));
 
@@ -130,18 +129,18 @@
   EXPECT_TRUE(base::ReadFileStream(*f, &s));
   EXPECT_GT(s.size(), 0u);
 
-  protos::Trace trace;
+  protos::gen::Trace trace;
   EXPECT_TRUE(trace.ParseFromString(s));
 
-  const std::string& data = trace.packet().Get(0).compressed_packets();
+  const std::string& data = trace.packet()[0].compressed_packets();
   EXPECT_GT(data.size(), 0u);
 
-  protos::Trace subtrace;
+  protos::gen::Trace subtrace;
   EXPECT_TRUE(subtrace.ParseFromString(Decompress(data)));
-  EXPECT_EQ(subtrace.packet().Get(0).for_testing().str(), "abc");
+  EXPECT_EQ(subtrace.packet()[0].for_testing().str(), "abc");
 }
 
-TEST(PacketWriter, ZipPacketWriter_Empty) {
+TEST(PacketWriterTest, ZipPacketWriter_Empty) {
   base::TempFile tmp = base::TempFile::Create();
   base::ScopedResource<FILE*, fclose, nullptr> f(
       fdopen(tmp.ReleaseFD().release(), "wb"));
@@ -154,7 +153,7 @@
   EXPECT_EQ(fseek(*f, 0, SEEK_END), 0);
 }
 
-TEST(PacketWriter, ZipPacketWriter_EmptyWithEmptyWrite) {
+TEST(PacketWriterTest, ZipPacketWriter_EmptyWithEmptyWrite) {
   base::TempFile tmp = base::TempFile::Create();
   base::ScopedResource<FILE*, fclose, nullptr> f(
       fdopen(tmp.ReleaseFD().release(), "wb"));
@@ -170,7 +169,7 @@
   EXPECT_EQ(fseek(*f, 0, SEEK_END), 0);
 }
 
-TEST(PacketWriter, ZipPacketWriter_ShouldCompress) {
+TEST(PacketWriterTest, ZipPacketWriter_ShouldCompress) {
   base::TempFile tmp = base::TempFile::Create();
   base::ScopedResource<FILE*, fclose, nullptr> f(
       fdopen(tmp.ReleaseFD().release(), "wb"));
@@ -183,13 +182,13 @@
     for (size_t i = 0; i < 200; i++) {
       std::vector<perfetto::TracePacket> packets;
 
-      packets.push_back(CreateTracePacket([](TracePacketZero* msg) {
-        auto* for_testing = msg->set_for_testing();
+      packets.push_back(CreateTracePacket([](TracePacketProto* msg) {
+        auto* for_testing = msg->mutable_for_testing();
         for_testing->set_str("abcdefghijklmn");
       }));
 
-      packets.push_back(CreateTracePacket([](TracePacketZero* msg) {
-        auto* for_testing = msg->set_for_testing();
+      packets.push_back(CreateTracePacket([](TracePacketProto* msg) {
+        auto* for_testing = msg->mutable_for_testing();
         for_testing->set_str("abcdefghijklmn");
       }));
 
@@ -206,7 +205,7 @@
   EXPECT_TRUE(base::ReadFileStream(*f, &s));
   EXPECT_GT(s.size(), 0u);
 
-  protos::Trace trace;
+  protos::gen::Trace trace;
   EXPECT_TRUE(trace.ParseFromString(s));
 
   size_t packet_count = 0;
@@ -214,7 +213,7 @@
     const std::string& data = packet.compressed_packets();
     EXPECT_GT(data.size(), 0u);
     EXPECT_LT(data.size(), 500 * 1024u);
-    protos::Trace subtrace;
+    protos::gen::Trace subtrace;
     EXPECT_TRUE(subtrace.ParseFromString(Decompress(data)));
     for (const auto& subpacket : subtrace.packet()) {
       packet_count++;
@@ -225,7 +224,7 @@
   EXPECT_EQ(packet_count, 200 * 2u);
 }
 
-TEST(PacketWriter, ZipPacketWriter_ShouldSplitPackets) {
+TEST(PacketWriterTest, ZipPacketWriter_ShouldSplitPackets) {
   base::TempFile tmp = base::TempFile::Create();
   base::ScopedResource<FILE*, fclose, nullptr> f(
       fdopen(tmp.ReleaseFD().release(), "wb"));
@@ -249,10 +248,10 @@
 
       std::string s = randomString();
 
-      packets.push_back(CreateTracePacket([i, &s](TracePacketZero* msg) {
-        auto* for_testing = msg->set_for_testing();
+      packets.push_back(CreateTracePacket([i, &s](TracePacketProto* msg) {
+        auto* for_testing = msg->mutable_for_testing();
         for_testing->set_seq_value(i);
-        for_testing->set_str(s.data(), s.size());
+        for_testing->set_str(s);
       }));
 
       EXPECT_TRUE(writer->WritePackets(std::move(packets)));
@@ -264,7 +263,7 @@
   EXPECT_TRUE(base::ReadFileStream(*f, &s));
   EXPECT_GT(s.size(), 0u);
 
-  protos::Trace trace;
+  protos::gen::Trace trace;
   EXPECT_TRUE(trace.ParseFromString(s));
 
   size_t packet_count = 0;
@@ -272,7 +271,7 @@
     const std::string& data = packet.compressed_packets();
     EXPECT_GT(data.size(), 0u);
     EXPECT_LT(data.size(), 500 * 1024u);
-    protos::Trace subtrace;
+    protos::gen::Trace subtrace;
     EXPECT_TRUE(subtrace.ParseFromString(Decompress(data)));
     for (const auto& subpacket : subtrace.packet()) {
       EXPECT_EQ(subpacket.for_testing().seq_value(), packet_count++);
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index 614c6d5..dff337c 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -436,7 +436,8 @@
   // 3) A set of option arguments (-t 10s -s 10m).
   // The only cases in which a trace config is not expected is --attach.
   // For this we are just acting on already existing sessions.
-  TraceConfig trace_config_proto;
+  trace_config_.reset(new TraceConfig());
+
   std::vector<std::string> triggers_to_activate;
   bool parsed = false;
   const bool will_trace = !is_attach() && !query_service_;
@@ -452,7 +453,7 @@
           "--buffer, --app, ATRACE_CAT, FTRACE_EVENT");
       return 1;
     }
-    parsed = CreateConfigFromOptions(config_options, &trace_config_proto);
+    parsed = CreateConfigFromOptions(config_options, trace_config_.get());
   } else {
     if (trace_config_raw.empty()) {
       PERFETTO_ELOG("The TraceConfig is empty");
@@ -461,16 +462,14 @@
     PERFETTO_DLOG("Parsing TraceConfig, %zu bytes", trace_config_raw.size());
     if (parse_as_pbtxt) {
       parsed = ParseTraceConfigPbtxt(config_file_name, trace_config_raw,
-                                     &trace_config_proto);
+                                     trace_config_.get());
     } else {
-      parsed = trace_config_proto.ParseFromString(trace_config_raw);
+      parsed = trace_config_->ParseFromString(trace_config_raw);
     }
   }
 
-  trace_config_.reset(new TraceConfig());
   if (parsed) {
-    *trace_config_proto.mutable_statsd_metadata() = std::move(statsd_metadata);
-    trace_config_->FromProto(trace_config_proto);
+    *trace_config_->mutable_statsd_metadata() = std::move(statsd_metadata);
     trace_config_raw.clear();
   } else if (will_trace) {
     PERFETTO_ELOG("The trace config is invalid, bailing out.");
@@ -612,6 +611,7 @@
   args.current_time = base::GetWallTimeS();
   args.ignore_guardrails = ignore_guardrails;
   args.allow_user_build_tracing = trace_config_->allow_user_build_tracing();
+  args.unique_session_name = trace_config_->unique_session_name();
 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_USERDEBUG_BUILD) || \
     PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
   args.max_upload_bytes_override =
diff --git a/src/perfetto_cmd/perfetto_cmd_state.proto b/src/perfetto_cmd/perfetto_cmd_state.proto
index 52b56fb..1d0b14d 100644
--- a/src/perfetto_cmd/perfetto_cmd_state.proto
+++ b/src/perfetto_cmd/perfetto_cmd_state.proto
@@ -20,9 +20,17 @@
 package perfetto;
 
 message PerfettoCmdState {
-  // These are fixed size so that the file is always a constant length.
   optional fixed64 first_trace_timestamp = 1;
   optional fixed64 last_trace_timestamp = 2;
-  // Total of bytes uploaded since first_trace_timestamp.
+  // Total of bytes uploaded for un-named sessions since first_trace_timestamp.
   optional fixed64 total_bytes_uploaded = 3;
+
+  message PerSessionState {
+    optional string session_name = 1;
+    // Total of bytes uploaded by this session since first_trace_timestamp.
+    optional fixed64 total_bytes_uploaded = 3;
+    // Time of last upload for this session.
+    optional fixed64 last_trace_timestamp = 2;
+  }
+  repeated PerSessionState session_state = 4;
 }
diff --git a/src/perfetto_cmd/perfetto_config.descriptor.h b/src/perfetto_cmd/perfetto_config.descriptor.h
index 5b467e1..56296c2 100644
--- a/src/perfetto_cmd/perfetto_config.descriptor.h
+++ b/src/perfetto_cmd/perfetto_config.descriptor.h
@@ -25,7 +25,7 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// 0f193cc67cb890463dcc9ce4ab236c0bb16bed98
+// f242f1ac484bbe7ba4c45e77b56ab588f8015196
 // SHA1(protos/perfetto/config/perfetto_config.proto)
 // 3cad942a7f5da2b1936464abea5d6c3d76525e9e
 
diff --git a/src/perfetto_cmd/rate_limiter.cc b/src/perfetto_cmd/rate_limiter.cc
index c7df19e..daa4403 100644
--- a/src/perfetto_cmd/rate_limiter.cc
+++ b/src/perfetto_cmd/rate_limiter.cc
@@ -16,10 +16,13 @@
 
 #include "src/perfetto_cmd/rate_limiter.h"
 
+#include <inttypes.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <algorithm>
+
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/scoped_file.h"
@@ -29,17 +32,19 @@
 namespace perfetto {
 namespace {
 
-// 5 mins between traces.
-const uint64_t kCooldownInSeconds = 60 * 5;
-
 // Every 24 hours we reset how much we've uploaded.
 const uint64_t kMaxUploadResetPeriodInSeconds = 60 * 60 * 24;
 
 // Maximum of 10mb every 24h.
 const uint64_t kMaxUploadInBytes = 1024 * 1024 * 10;
 
+// Keep track of last 10 observed sessions.
+const uint64_t kMaxSessionsInHistory = 10;
+
 }  // namespace
 
+using PerSessionState = gen::PerfettoCmdState::PerSessionState;
+
 RateLimiter::RateLimiter() = default;
 RateLimiter::~RateLimiter() = default;
 
@@ -88,13 +93,6 @@
       return false;
   }
 
-  // If we've uploaded in the last 5mins we shouldn't trace now.
-  if ((now_in_s - state_.last_trace_timestamp()) < kCooldownInSeconds) {
-    PERFETTO_LOG("Guardrail: Uploaded to DropBox in the last 5mins.");
-    if (!args.ignore_guardrails)
-      return false;
-  }
-
   // First trace was more than 24h ago? Reset state.
   if ((now_in_s - state_.first_trace_timestamp()) >
       kMaxUploadResetPeriodInSeconds) {
@@ -104,19 +102,36 @@
     return true;
   }
 
-  if (args.is_user_build) {
-    // If we've uploaded more than 10mb in the last 24 hours we shouldn't trace
-    // now.
-    uint64_t max_upload_guardrail = args.max_upload_bytes_override > 0
-                                        ? args.max_upload_bytes_override
-                                        : kMaxUploadInBytes;
-    if (state_.total_bytes_uploaded() > max_upload_guardrail) {
-      PERFETTO_ELOG("Guardrail: Uploaded >10mb DropBox in the last 24h.");
-      if (!args.ignore_guardrails)
-        return false;
+  uint64_t max_upload_guardrail = kMaxUploadInBytes;
+  if (args.max_upload_bytes_override > 0) {
+    if (args.unique_session_name.empty()) {
+      PERFETTO_ELOG(
+          "Ignoring max_upload_per_day_bytes override as unique_session_name "
+          "not set");
+    } else {
+      max_upload_guardrail = args.max_upload_bytes_override;
     }
   }
 
+  uint64_t uploaded_so_far = state_.total_bytes_uploaded();
+  if (!args.unique_session_name.empty()) {
+    uploaded_so_far = 0;
+    for (const auto& session_state : state_.session_state()) {
+      if (session_state.session_name() == args.unique_session_name) {
+        uploaded_so_far = session_state.total_bytes_uploaded();
+        break;
+      }
+    }
+  }
+
+  if (uploaded_so_far > max_upload_guardrail) {
+    PERFETTO_ELOG("Guardrail: Uploaded %" PRIu64
+                  " in the last 24h. Limit is %" PRIu64 ".",
+                  uploaded_so_far, max_upload_guardrail);
+    if (!args.ignore_guardrails)
+      return false;
+  }
+
   return true;
 }
 
@@ -137,8 +152,26 @@
     state_.set_first_trace_timestamp(now_in_s);
   // Always updated the last trace timestamp.
   state_.set_last_trace_timestamp(now_in_s);
-  // Add the amount we uploaded to the running total.
-  state_.set_total_bytes_uploaded(state_.total_bytes_uploaded() + bytes);
+
+  if (args.unique_session_name.empty()) {
+    // Add the amount we uploaded to the running total.
+    state_.set_total_bytes_uploaded(state_.total_bytes_uploaded() + bytes);
+  } else {
+    PerSessionState* target_session = nullptr;
+    for (PerSessionState& session : *state_.mutable_session_state()) {
+      if (session.session_name() == args.unique_session_name) {
+        target_session = &session;
+        break;
+      }
+    }
+    if (!target_session) {
+      target_session = state_.add_session_state();
+      target_session->set_session_name(args.unique_session_name);
+    }
+    target_session->set_total_bytes_uploaded(
+        target_session->total_bytes_uploaded() + bytes);
+    target_session->set_last_trace_timestamp(now_in_s);
+  }
 
   if (!SaveState(state_)) {
     PERFETTO_ELOG("Failed to save state.");
@@ -170,17 +203,29 @@
 
 bool RateLimiter::LoadState(gen::PerfettoCmdState* state) {
   base::ScopedFile in_fd(base::OpenFile(GetStateFilePath(), O_RDONLY));
-
   if (!in_fd)
     return false;
-  char buf[1024];
-  ssize_t bytes = PERFETTO_EINTR(read(in_fd.get(), &buf, sizeof(buf)));
-  if (bytes <= 0)
+  std::string s;
+  base::ReadFileDescriptor(in_fd.get(), &s);
+  if (s.size() == 0)
     return false;
-  return state->ParseFromArray(&buf, static_cast<size_t>(bytes));
+  return state->ParseFromString(s);
 }
 
-bool RateLimiter::SaveState(const gen::PerfettoCmdState& state) {
+bool RateLimiter::SaveState(const gen::PerfettoCmdState& input_state) {
+  gen::PerfettoCmdState state = input_state;
+
+  // Keep only the N most recent per session states so the file doesn't
+  // grow indefinitely:
+  std::vector<PerSessionState>* sessions = state.mutable_session_state();
+  std::sort(sessions->begin(), sessions->end(),
+            [](const PerSessionState& a, const PerSessionState& b) {
+              return a.last_trace_timestamp() > b.last_trace_timestamp();
+            });
+  if (sessions->size() > kMaxSessionsInHistory) {
+    sessions->resize(kMaxSessionsInHistory);
+  }
+
   // Rationale for 0666: the cmdline client can be executed under two
   // different Unix UIDs: shell and statsd. If we run one after the
   // other and the file has 0600 permissions, then the 2nd run won't
diff --git a/src/perfetto_cmd/rate_limiter.h b/src/perfetto_cmd/rate_limiter.h
index 1f4866c..5866cd1 100644
--- a/src/perfetto_cmd/rate_limiter.h
+++ b/src/perfetto_cmd/rate_limiter.h
@@ -31,6 +31,7 @@
     bool allow_user_build_tracing = false;
     base::TimeSeconds current_time = base::TimeSeconds(0);
     uint64_t max_upload_bytes_override = 0;
+    std::string unique_session_name = "";
   };
 
   RateLimiter();
diff --git a/src/perfetto_cmd/rate_limiter_unittest.cc b/src/perfetto_cmd/rate_limiter_unittest.cc
index 6e0c462..1f6612d 100644
--- a/src/perfetto_cmd/rate_limiter_unittest.cc
+++ b/src/perfetto_cmd/rate_limiter_unittest.cc
@@ -26,10 +26,11 @@
 #include "test/gtest_and_gmock.h"
 
 using testing::_;
-using testing::NiceMock;
-using testing::StrictMock;
+using testing::Contains;
 using testing::Invoke;
+using testing::NiceMock;
 using testing::Return;
+using testing::StrictMock;
 
 namespace perfetto {
 
@@ -85,6 +86,42 @@
   ASSERT_TRUE(limiter.SaveState(input));
   ASSERT_TRUE(limiter.LoadState(&output));
   ASSERT_EQ(output.total_bytes_uploaded(), 42u);
+  ASSERT_EQ(output.session_state_size(), 0);
+}
+
+TEST(RateLimiterTest, FileIsSensiblyTruncated) {
+  NiceMock<MockRateLimiter> limiter;
+
+  gen::PerfettoCmdState input{};
+  gen::PerfettoCmdState output{};
+
+  input.set_total_bytes_uploaded(42);
+  input.set_first_trace_timestamp(1);
+  input.set_last_trace_timestamp(2);
+
+  for (size_t i = 0; i < 100; ++i) {
+    auto* session = input.add_session_state();
+    session->set_session_name("session_" + std::to_string(i));
+    session->set_total_bytes_uploaded(i * 100);
+    session->set_last_trace_timestamp(i);
+  }
+
+  ASSERT_TRUE(limiter.SaveState(input));
+  ASSERT_TRUE(limiter.LoadState(&output));
+
+  ASSERT_EQ(output.total_bytes_uploaded(), 42u);
+  ASSERT_EQ(output.first_trace_timestamp(), 1u);
+  ASSERT_EQ(output.last_trace_timestamp(), 2u);
+  ASSERT_LE(output.session_state_size(), 50);
+  ASSERT_GE(output.session_state_size(), 5);
+
+  {
+    gen::PerfettoCmdState::PerSessionState session;
+    session.set_session_name("session_99");
+    session.set_total_bytes_uploaded(99 * 100);
+    session.set_last_trace_timestamp(99);
+    ASSERT_THAT(output.session_state(), Contains(session));
+  }
 }
 
 TEST(RateLimiterTest, LoadFromEmpty) {
@@ -206,6 +243,45 @@
             static_cast<uint64_t>(args.current_time.count()));
 }
 
+TEST(RateLimiterTest, DropBox_NormalUploadWithSessionName) {
+  StrictMock<MockRateLimiter> limiter;
+  RateLimiter::Args args;
+
+  gen::PerfettoCmdState input{};
+  input.set_first_trace_timestamp(10000);
+  input.set_last_trace_timestamp(10000 + 60 * 10);
+  input.set_total_bytes_uploaded(1024 * 1024 * 2);
+  ASSERT_TRUE(limiter.SaveStateConcrete(input));
+
+  args.allow_user_build_tracing = true;
+  args.is_dropbox = true;
+  args.unique_session_name = "foo";
+  args.current_time = base::TimeSeconds(input.last_trace_timestamp() + 60 * 10);
+
+  EXPECT_CALL(limiter, LoadState(_));
+  ASSERT_TRUE(limiter.ShouldTrace(args));
+
+  EXPECT_CALL(limiter, SaveState(_));
+  ASSERT_TRUE(limiter.OnTraceDone(args, true, 1024 * 1024));
+
+  gen::PerfettoCmdState output{};
+  ASSERT_TRUE(limiter.LoadStateConcrete(&output));
+  EXPECT_EQ(output.total_bytes_uploaded(), 1024u * 1024u * 2);
+  EXPECT_EQ(output.first_trace_timestamp(), input.first_trace_timestamp());
+  EXPECT_EQ(output.last_trace_timestamp(),
+            static_cast<uint64_t>(args.current_time.count()));
+  ASSERT_GE(output.session_state_size(), 1);
+
+  {
+    gen::PerfettoCmdState::PerSessionState session;
+    session.set_session_name("foo");
+    session.set_total_bytes_uploaded(1024 * 1024);
+    session.set_last_trace_timestamp(
+        static_cast<uint64_t>(args.current_time.count()));
+    ASSERT_THAT(output.session_state(), Contains(session));
+  }
+}
+
 TEST(RateLimiterTest, DropBox_FailedToLoadState) {
   StrictMock<MockRateLimiter> limiter;
   RateLimiter::Args args;
@@ -250,18 +326,43 @@
   EXPECT_EQ(output.last_trace_timestamp(), 0u);
 }
 
-TEST(RateLimiterTest, DropBox_TooSoon) {
+TEST(RateLimiterTest, DropBox_TooMuch_OtherSession) {
   StrictMock<MockRateLimiter> limiter;
   RateLimiter::Args args;
 
   gen::PerfettoCmdState input{};
-  input.set_first_trace_timestamp(10000);
-  input.set_last_trace_timestamp(10000);
+  auto* session = input.add_session_state();
+  session->set_session_name("foo");
+  session->set_total_bytes_uploaded(100 * 1024 * 1024);
+
   ASSERT_TRUE(limiter.SaveStateConcrete(input));
 
+  args.is_user_build = true;
   args.allow_user_build_tracing = true;
   args.is_dropbox = true;
-  args.current_time = base::TimeSeconds(10000 + 60 * 4);
+  args.unique_session_name = "bar";
+  args.current_time = base::TimeSeconds(60 * 60);
+
+  EXPECT_CALL(limiter, LoadState(_));
+  ASSERT_TRUE(limiter.ShouldTrace(args));
+}
+
+TEST(RateLimiterTest, DropBox_TooMuch_Session) {
+  StrictMock<MockRateLimiter> limiter;
+  RateLimiter::Args args;
+
+  gen::PerfettoCmdState input{};
+  auto* session = input.add_session_state();
+  session->set_session_name("foo");
+  session->set_total_bytes_uploaded(100 * 1024 * 1024);
+
+  ASSERT_TRUE(limiter.SaveStateConcrete(input));
+
+  args.is_user_build = true;
+  args.allow_user_build_tracing = true;
+  args.is_dropbox = true;
+  args.unique_session_name = "foo";
+  args.current_time = base::TimeSeconds(60 * 60);
 
   EXPECT_CALL(limiter, LoadState(_));
   ASSERT_FALSE(limiter.ShouldTrace(args));
@@ -289,6 +390,27 @@
   RateLimiter::Args args;
 
   gen::PerfettoCmdState input{};
+  auto* session = input.add_session_state();
+  session->set_session_name("foo");
+  session->set_total_bytes_uploaded(10 * 1024 * 1024 + 1);
+  ASSERT_TRUE(limiter.SaveStateConcrete(input));
+
+  args.allow_user_build_tracing = true;
+  args.is_dropbox = true;
+  args.current_time = base::TimeSeconds(60 * 60);
+  args.max_upload_bytes_override = 10 * 1024 * 1024 + 2;
+  args.unique_session_name = "foo";
+
+  EXPECT_CALL(limiter, LoadState(_));
+  ASSERT_TRUE(limiter.ShouldTrace(args));
+}
+
+// Override doesn't apply to traces without session name.
+TEST(RateLimiterTest, DropBox_OverrideOnEmptySesssionName) {
+  StrictMock<MockRateLimiter> limiter;
+  RateLimiter::Args args;
+
+  gen::PerfettoCmdState input{};
   input.set_total_bytes_uploaded(10 * 1024 * 1024 + 1);
   ASSERT_TRUE(limiter.SaveStateConcrete(input));
 
@@ -298,7 +420,7 @@
   args.max_upload_bytes_override = 10 * 1024 * 1024 + 2;
 
   EXPECT_CALL(limiter, LoadState(_));
-  ASSERT_TRUE(limiter.ShouldTrace(args));
+  ASSERT_FALSE(limiter.ShouldTrace(args));
 }
 
 TEST(RateLimiterTest, DropBox_TooMuchWasUploaded) {
diff --git a/src/profiling/memory/BUILD.gn b/src/profiling/memory/BUILD.gn
index 9ef32c2..1862fb4 100644
--- a/src/profiling/memory/BUILD.gn
+++ b/src/profiling/memory/BUILD.gn
@@ -145,7 +145,7 @@
     ":scoped_spinlock",
     ":wire_protocol",
     "../../../gn:default_deps",
-    "../../../protos/perfetto/config/profiling:lite",
+    "../../../protos/perfetto/config/profiling:cpp",
     "../../base",
     "../../base:unix_socket",
     "../../tracing",
@@ -238,8 +238,8 @@
     "../../../gn:default_deps",
     "../../../gn:gtest_and_gmock",
     "../../../gn:libunwindstack",
-    "../../../include/perfetto/protozero",
-    "../../../protos/perfetto/config/profiling:zero",
+    "../../../protos/perfetto/config/profiling:cpp",
+    "../../../protos/perfetto/trace/profiling:cpp",
     "../../../test:test_helper",
     "../../base",
     "../../base:test_support",
diff --git a/src/profiling/memory/heapprofd_end_to_end_test.cc b/src/profiling/memory/heapprofd_end_to_end_test.cc
index 42e666f..d698650 100644
--- a/src/profiling/memory/heapprofd_end_to_end_test.cc
+++ b/src/profiling/memory/heapprofd_end_to_end_test.cc
@@ -21,17 +21,19 @@
 #include "perfetto/base/build_config.h"
 #include "perfetto/ext/base/pipe.h"
 #include "perfetto/ext/tracing/ipc/default_socket.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/profiling/memory/heapprofd_producer.h"
 #include "test/gtest_and_gmock.h"
 #include "test/test_helper.h"
 
-#include "protos/perfetto/config/profiling/heapprofd_config.pbzero.h"
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
 #include <sys/system_properties.h>
 #endif
 
+#include "protos/perfetto/config/profiling/heapprofd_config.gen.h"
+#include "protos/perfetto/trace/profiling/profile_common.gen.h"
+#include "protos/perfetto/trace/profiling/profile_packet.gen.h"
+
 namespace perfetto {
 namespace profiling {
 namespace {
@@ -166,7 +168,7 @@
   return helper;
 }
 
-std::string FormatHistogram(const protos::ProfilePacket_Histogram& hist) {
+std::string FormatHistogram(const protos::gen::ProfilePacket_Histogram& hist) {
   std::string out;
   std::string prev_upper_limit = "-inf";
   for (const auto& bucket : hist.buckets()) {
@@ -183,7 +185,7 @@
   return out + "\n";
 }
 
-std::string FormatStats(const protos::ProfilePacket_ProcessStats& stats) {
+std::string FormatStats(const protos::gen::ProfilePacket_ProcessStats& stats) {
   return std::string("unwinding_errors: ") +
          std::to_string(stats.unwinding_errors()) + "\n" +
          "heap_samples: " + std::to_string(stats.heap_samples()) + "\n" +
@@ -231,7 +233,7 @@
 
   void PrintStats(TestHelper* helper) {
     const auto& packets = helper->trace();
-    for (const protos::TracePacket& packet : packets) {
+    for (const protos::gen::TracePacket& packet : packets) {
       for (const auto& dump : packet.profile_packet().process_dumps()) {
         // protobuf uint64 does not like the PRIu64 formatter.
         PERFETTO_LOG("Stats for %s: %s", std::to_string(dump.pid()).c_str(),
@@ -244,7 +246,7 @@
                            uint64_t pid,
                            uint64_t alloc_size) {
     const auto& packets = helper->trace();
-    for (const protos::TracePacket& packet : packets) {
+    for (const protos::gen::TracePacket& packet : packets) {
       for (const auto& dump : packet.profile_packet().process_dumps()) {
         if (dump.pid() != pid)
           continue;
@@ -262,7 +264,7 @@
                            uint64_t pid,
                            bool from_startup) {
     const auto& packets = helper->trace();
-    for (const protos::TracePacket& packet : packets) {
+    for (const protos::gen::TracePacket& packet : packets) {
       for (const auto& dump : packet.profile_packet().process_dumps()) {
         if (dump.pid() != pid)
           continue;
@@ -275,7 +277,7 @@
                                   uint64_t pid,
                                   bool rejected_concurrent) {
     const auto& packets = helper->trace();
-    for (const protos::TracePacket& packet : packets) {
+    for (const protos::gen::TracePacket& packet : packets) {
       for (const auto& dump : packet.profile_packet().process_dumps()) {
         if (dump.pid() != pid)
           continue;
@@ -291,7 +293,7 @@
     size_t samples = 0;
     uint64_t last_allocated = 0;
     uint64_t last_freed = 0;
-    for (const protos::TracePacket& packet : packets) {
+    for (const protos::gen::TracePacket& packet : packets) {
       for (const auto& dump : packet.profile_packet().process_dumps()) {
         if (dump.pid() != pid)
           continue;
@@ -312,7 +314,7 @@
   void ValidateOnlyPID(TestHelper* helper, uint64_t pid) {
     size_t dumps = 0;
     const auto& packets = helper->trace();
-    for (const protos::TracePacket& packet : packets) {
+    for (const protos::gen::TracePacket& packet : packets) {
       for (const auto& dump : packet.profile_packet().process_dumps()) {
         EXPECT_EQ(dump.pid(), pid);
         dumps++;
@@ -336,11 +338,11 @@
   ds_config->set_name("android.heapprofd");
   ds_config->set_target_buffer(0);
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_pid(static_cast<uint64_t>(pid));
-  heapprofd_config->set_all(false);
-  auto* cont_config = heapprofd_config->set_continuous_dump_config();
+  protos::gen::HeapprofdConfig heapprofd_config;
+  heapprofd_config.set_sampling_interval_bytes(1);
+  heapprofd_config.add_pid(static_cast<uint64_t>(pid));
+  heapprofd_config.set_all(false);
+  auto* cont_config = heapprofd_config.mutable_continuous_dump_config();
   cont_config->set_dump_phase_ms(0);
   cont_config->set_dump_interval_ms(100);
   ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
@@ -371,11 +373,11 @@
   ds_config->set_name("android.heapprofd");
   ds_config->set_target_buffer(0);
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_pid(static_cast<uint64_t>(pid));
-  heapprofd_config->add_pid(static_cast<uint64_t>(pid2));
-  heapprofd_config->set_all(false);
+  protos::gen::HeapprofdConfig heapprofd_config;
+  heapprofd_config.set_sampling_interval_bytes(1);
+  heapprofd_config.add_pid(static_cast<uint64_t>(pid));
+  heapprofd_config.add_pid(static_cast<uint64_t>(pid2));
+  heapprofd_config.set_all(false);
   ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
 
   auto helper = Trace(trace_config);
@@ -405,10 +407,10 @@
   ds_config->set_name("android.heapprofd");
   ds_config->set_target_buffer(0);
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_pid(static_cast<uint64_t>(pid));
-  heapprofd_config->set_all(false);
+  protos::gen::HeapprofdConfig heapprofd_config;
+  heapprofd_config.set_sampling_interval_bytes(1);
+  heapprofd_config.add_pid(static_cast<uint64_t>(pid));
+  heapprofd_config.set_all(false);
   ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
 
   auto helper = Trace(trace_config);
@@ -432,10 +434,10 @@
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("android.heapprofd");
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_process_cmdline("heapprofd_continuous_malloc");
-  heapprofd_config->set_all(false);
+  protos::gen::HeapprofdConfig heapprofd_config;
+  heapprofd_config.set_sampling_interval_bytes(1);
+  heapprofd_config.add_process_cmdline("heapprofd_continuous_malloc");
+  heapprofd_config.set_all(false);
   ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
 
   helper->StartTracing(trace_config);
@@ -481,12 +483,12 @@
   size_t samples = 0;
   uint64_t total_allocated = 0;
   uint64_t total_freed = 0;
-  for (const protos::TracePacket& packet : packets) {
+  for (const protos::gen::TracePacket& packet : packets) {
     if (packet.has_profile_packet() &&
         packet.profile_packet().process_dumps().size() > 0) {
       const auto& dumps = packet.profile_packet().process_dumps();
-      ASSERT_EQ(dumps.size(), 1);
-      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
+      ASSERT_EQ(dumps.size(), 1u);
+      const protos::gen::ProfilePacket_ProcessHeapSamples& dump = dumps[0];
       EXPECT_EQ(static_cast<pid_t>(dump.pid()), pid);
       profile_packets++;
       for (const auto& sample : dump.samples()) {
@@ -513,10 +515,10 @@
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("android.heapprofd");
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_process_cmdline("heapprofd_continuous_malloc@1.2.3");
-  heapprofd_config->set_all(false);
+  protos::gen::HeapprofdConfig heapprofd_config;
+  heapprofd_config.set_sampling_interval_bytes(1);
+  heapprofd_config.add_process_cmdline("heapprofd_continuous_malloc@1.2.3");
+  heapprofd_config.set_all(false);
   ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
 
   helper->StartTracing(trace_config);
@@ -562,12 +564,12 @@
   size_t samples = 0;
   uint64_t total_allocated = 0;
   uint64_t total_freed = 0;
-  for (const protos::TracePacket& packet : packets) {
+  for (const protos::gen::TracePacket& packet : packets) {
     if (packet.has_profile_packet() &&
         packet.profile_packet().process_dumps().size() > 0) {
       const auto& dumps = packet.profile_packet().process_dumps();
-      ASSERT_EQ(dumps.size(), 1);
-      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
+      ASSERT_EQ(dumps.size(), 1u);
+      const protos::gen::ProfilePacket_ProcessHeapSamples& dump = dumps[0];
       EXPECT_EQ(static_cast<pid_t>(dump.pid()), pid);
       profile_packets++;
       for (const auto& sample : dump.samples()) {
@@ -594,10 +596,10 @@
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("android.heapprofd");
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_process_cmdline("heapprofd_continuous_malloc");
-  heapprofd_config->set_all(false);
+  protos::gen::HeapprofdConfig heapprofd_config;
+  heapprofd_config.set_sampling_interval_bytes(1);
+  heapprofd_config.add_process_cmdline("heapprofd_continuous_malloc");
+  heapprofd_config.set_all(false);
   ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
 
   // Make sure the forked process does not get reparented to init.
@@ -639,12 +641,12 @@
   size_t samples = 0;
   uint64_t total_allocated = 0;
   uint64_t total_freed = 0;
-  for (const protos::TracePacket& packet : packets) {
+  for (const protos::gen::TracePacket& packet : packets) {
     if (packet.has_profile_packet() &&
         packet.profile_packet().process_dumps().size() > 0) {
       const auto& dumps = packet.profile_packet().process_dumps();
-      ASSERT_EQ(dumps.size(), 1);
-      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
+      ASSERT_EQ(dumps.size(), 1u);
+      const protos::gen::ProfilePacket_ProcessHeapSamples& dump = dumps[0];
       EXPECT_EQ(static_cast<pid_t>(dump.pid()), pid);
       profile_packets++;
       for (const auto& sample : dump.samples()) {
@@ -671,10 +673,10 @@
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("android.heapprofd");
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_process_cmdline("heapprofd_continuous_malloc@1.2.3");
-  heapprofd_config->set_all(false);
+  protos::gen::HeapprofdConfig heapprofd_config;
+  heapprofd_config.set_sampling_interval_bytes(1);
+  heapprofd_config.add_process_cmdline("heapprofd_continuous_malloc@1.2.3");
+  heapprofd_config.set_all(false);
   ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
 
   // Make sure the forked process does not get reparented to init.
@@ -716,12 +718,12 @@
   size_t samples = 0;
   uint64_t total_allocated = 0;
   uint64_t total_freed = 0;
-  for (const protos::TracePacket& packet : packets) {
+  for (const protos::gen::TracePacket& packet : packets) {
     if (packet.has_profile_packet() &&
         packet.profile_packet().process_dumps().size() > 0) {
       const auto& dumps = packet.profile_packet().process_dumps();
-      ASSERT_EQ(dumps.size(), 1);
-      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
+      ASSERT_EQ(dumps.size(), 1u);
+      const protos::gen::ProfilePacket_ProcessHeapSamples& dump = dumps[0];
       EXPECT_EQ(static_cast<pid_t>(dump.pid()), pid);
       profile_packets++;
       for (const auto& sample : dump.samples()) {
@@ -785,10 +787,10 @@
   ds_config->set_name("android.heapprofd");
   ds_config->set_target_buffer(0);
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_pid(static_cast<uint64_t>(pid));
-  heapprofd_config->set_all(false);
+  protos::gen::HeapprofdConfig heapprofd_config;
+  heapprofd_config.set_sampling_interval_bytes(1);
+  heapprofd_config.add_pid(static_cast<uint64_t>(pid));
+  heapprofd_config.set_all(false);
   ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
 
   auto helper = Trace(trace_config);
@@ -833,11 +835,11 @@
   ds_config->set_name("android.heapprofd");
   ds_config->set_target_buffer(0);
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_pid(static_cast<uint64_t>(pid));
-  heapprofd_config->set_all(false);
-  auto* cont_config = heapprofd_config->set_continuous_dump_config();
+  protos::gen::HeapprofdConfig heapprofd_config;
+  heapprofd_config.set_sampling_interval_bytes(1);
+  heapprofd_config.add_pid(static_cast<uint64_t>(pid));
+  heapprofd_config.set_all(false);
+  auto* cont_config = heapprofd_config.mutable_continuous_dump_config();
   cont_config->set_dump_phase_ms(0);
   cont_config->set_dump_interval_ms(100);
   ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
@@ -906,9 +908,9 @@
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("android.heapprofd");
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_pid(static_cast<uint64_t>(pid));
+  protos::gen::HeapprofdConfig heapprofd_config;
+  heapprofd_config.set_sampling_interval_bytes(1);
+  heapprofd_config.add_pid(static_cast<uint64_t>(pid));
   ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
 
   // Wait for child to have been scheduled at least once.
@@ -940,12 +942,12 @@
   size_t profile_packets = 0;
   size_t samples = 0;
   uint64_t total_allocated = 0;
-  for (const protos::TracePacket& packet : packets) {
+  for (const protos::gen::TracePacket& packet : packets) {
     if (packet.has_profile_packet() &&
         packet.profile_packet().process_dumps().size() > 0) {
       const auto& dumps = packet.profile_packet().process_dumps();
-      ASSERT_EQ(dumps.size(), 1);
-      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
+      ASSERT_EQ(dumps.size(), 1u);
+      const protos::gen::ProfilePacket_ProcessHeapSamples& dump = dumps[0];
       EXPECT_EQ(static_cast<pid_t>(dump.pid()), pid);
       profile_packets++;
       for (const auto& sample : dump.samples()) {
diff --git a/src/protozero/protoc_plugin/cppgen_plugin.cc b/src/protozero/protoc_plugin/cppgen_plugin.cc
index 060903f..cc499ab 100644
--- a/src/protozero/protoc_plugin/cppgen_plugin.cc
+++ b/src/protozero/protoc_plugin/cppgen_plugin.cc
@@ -217,6 +217,9 @@
       local_enums.push_back(enum_desc);
   };
 
+  for (int i = 0; i < file->enum_type_count(); i++)
+    add_enum(file->enum_type(i));
+
   std::stack<const Descriptor*> recursion_stack;
   for (int i = 0; i < file->message_type_count(); i++)
     recursion_stack.push(file->message_type(i));
@@ -558,17 +561,6 @@
   p->Print("std::vector<uint8_t> SerializeAsArray() const override;\n");
   p->Print("void Serialize(::protozero::Message*) const;\n");
 
-  p->Print("// (DEPRECATED) Conversion methods from/to libprotobuf types.\n");
-  p->Print("// These two will go away soon, see go/perfetto-libprotobuf.\n");
-  p->Print(
-      "template <typename T /*$p$*/> void FromProto(const T& pb_obj) { "
-      "ParseFromString(pb_obj.SerializeAsString()); }\n",
-      "p", proto_type);
-  p->Print(
-      "template <typename T /*$p$*/> void ToProto(T* pb_obj) const { "
-      "pb_obj->Clear(); pb_obj->ParseFromString(SerializeAsString()); }\n",
-      "p", proto_type);
-
   // Generate accessors.
   for (int i = 0; i < msg->field_count(); i++) {
     const FieldDescriptor* field = msg->field(i);
diff --git a/src/protozero/test/example_proto/test_messages.descriptor.h b/src/protozero/test/example_proto/test_messages.descriptor.h
index 8cda24c..f26c058 100644
--- a/src/protozero/test/example_proto/test_messages.descriptor.h
+++ b/src/protozero/test/example_proto/test_messages.descriptor.h
@@ -25,7 +25,7 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// 0f193cc67cb890463dcc9ce4ab236c0bb16bed98
+// f242f1ac484bbe7ba4c45e77b56ab588f8015196
 // SHA1(src/protozero/test/example_proto/test_messages.proto)
 // 61c0771c4c18c994996335be97413d944ce8f80d
 
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index b868d46..df2329f 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -44,6 +44,22 @@
   }
 }
 
+source_set("protozero_to_text") {
+  sources = [
+    "importers/proto/track_event.descriptor.h",
+    "protozero_to_text.cc",
+    "protozero_to_text.h",
+  ]
+  deps = [
+    ":descriptors",
+    "../../gn:default_deps",
+    "../../protos/perfetto/common:zero",
+    "../../protos/perfetto/trace/track_event:zero",
+    "../base",
+    "../protozero:protozero",
+  ]
+}
+
 source_set("descriptors") {
   sources = [
     "descriptors.cc",
@@ -58,7 +74,7 @@
   ]
 }
 
-source_set("storage") {
+source_set("storage_minimal") {
   sources = [
     "args_tracker.cc",
     "args_tracker.h",
@@ -77,6 +93,7 @@
     "heap_profile_tracker.cc",
     "heap_profile_tracker.h",
     "importers/ftrace/ftrace_descriptors.h",
+    "importers/ftrace/ftrace_module.cc",
     "importers/ftrace/ftrace_module.h",
     "importers/ftrace/ftrace_parser.h",
     "importers/ftrace/ftrace_tokenizer.h",
@@ -87,8 +104,6 @@
     "importers/proto/args_table_utils.cc",
     "importers/proto/args_table_utils.h",
     "importers/proto/chrome_compositor_scheduler_state.descriptor.h",
-    "importers/proto/graphics_event_module.h",
-    "importers/proto/graphics_event_parser.h",
     "importers/proto/heap_graph_module.h",
     "importers/proto/heap_graph_tracker.h",
     "importers/proto/heap_graph_walker.h",
@@ -102,6 +117,7 @@
     "importers/proto/proto_trace_tokenizer.h",
     "importers/proto/system_probes_module.h",
     "importers/proto/system_probes_parser.h",
+    "importers/proto/track_event_module.cc",
     "importers/proto/track_event_module.h",
     "importers/proto/track_event_parser.cc",
     "importers/proto/track_event_parser.h",
@@ -134,7 +150,6 @@
     "track_tracker.h",
     "variadic.h",
     "virtual_destructors.cc",
-    "vulkan_memory_tracker.h",
   ]
 
   deps = [
@@ -142,13 +157,18 @@
     ":descriptors",
     "../../gn:default_deps",
     "../../gn:zlib",
+    "../base",
+    "../protozero",
+    "tables",
+  ]
+  public_deps = [
+    "../../include/perfetto/trace_processor:storage",
     "../../protos/perfetto/common:zero",
     "../../protos/perfetto/config:zero",
     "../../protos/perfetto/trace:zero",
     "../../protos/perfetto/trace/android:zero",
     "../../protos/perfetto/trace/chrome:zero",
     "../../protos/perfetto/trace/ftrace:zero",
-    "../../protos/perfetto/trace/gpu:zero",
     "../../protos/perfetto/trace/interned_data:zero",
     "../../protos/perfetto/trace/perfetto:zero",
     "../../protos/perfetto/trace/power:zero",
@@ -156,12 +176,6 @@
     "../../protos/perfetto/trace/ps:zero",
     "../../protos/perfetto/trace/sys_stats:zero",
     "../../protos/perfetto/trace/track_event:zero",
-    "../base",
-    "../protozero",
-    "tables",
-  ]
-  public_deps = [
-    "../../include/perfetto/trace_processor:storage",
   ]
   if (enable_perfetto_trace_processor_json_import) {
     sources += [
@@ -177,6 +191,7 @@
   if (enable_perfetto_trace_processor_ftrace) {
     sources += [
       "importers/ftrace/ftrace_descriptors.cc",
+      "importers/ftrace/ftrace_module_impl.cc",
       "importers/ftrace/ftrace_parser.cc",
       "importers/ftrace/ftrace_tokenizer.cc",
       "importers/ftrace/sched_event_tracker.cc",
@@ -189,11 +204,17 @@
     sources += [ "ftrace_utils.cc" ]
   }
   if (enable_perfetto_trace_processor_system_probes) {
-    sources += [ "importers/proto/system_probes_parser.cc" ]
+    sources += [
+      "importers/proto/system_probes_module.cc",
+      "importers/proto/system_probes_parser.cc",
+    ]
     deps += [ "../../include/perfetto/ext/traced:sys_stats_counters" ]
   }
   if (enable_perfetto_trace_processor_android_probes) {
-    sources += [ "importers/proto/android_probes_parser.cc" ]
+    sources += [
+      "importers/proto/android_probes_module.cc",
+      "importers/proto/android_probes_parser.cc",
+    ]
   }
   if (enable_perfetto_trace_processor_heap_graphs) {
     sources += [
@@ -202,13 +223,6 @@
       "importers/proto/heap_graph_walker.cc",
     ]
   }
-  if (enable_perfetto_trace_processor_graphics) {
-    sources += [
-      "importers/proto/graphics_event_module.cc",
-      "importers/proto/graphics_event_parser.cc",
-      "vulkan_memory_tracker.cc",
-    ]
-  }
   if (enable_perfetto_trace_processor_fuchsia) {
     sources += [
       "importers/fuchsia/fuchsia_provider_view.cc",
@@ -231,6 +245,33 @@
   }
 }
 
+source_set("storage_full") {
+  sources = [
+    "importers/proto/graphics_event_module.cc",
+    "importers/proto/graphics_event_module.h",
+    "importers/proto/graphics_event_parser.cc",
+    "importers/proto/graphics_event_parser.h",
+    "importers/proto/vulkan_memory_tracker.cc",
+    "importers/proto/vulkan_memory_tracker.h",
+    "register_additional_modules.cc",
+    "register_additional_modules.h",
+  ]
+  public_deps = [
+    ":storage_minimal",
+  ]
+  deps = [
+    "../../protos/perfetto/common:zero",
+    "../../protos/perfetto/trace:zero",
+    "../../protos/perfetto/trace/android:zero",
+    "../../protos/perfetto/trace/gpu:zero",
+    "../../protos/perfetto/trace/interned_data:zero",
+    "../protozero",
+  ]
+  if (enable_perfetto_trace_processor_json) {
+    public_deps += [ "../../gn:jsoncpp" ]
+  }
+}
+
 if (enable_perfetto_trace_processor_json) {
   source_set("export_json") {
     sources = [
@@ -238,7 +279,7 @@
       "export_json.h",
     ]
     deps = [
-      ":storage",
+      ":storage_minimal",
       "../../gn:default_deps",
       "../../gn:jsoncpp",
       "../base",
@@ -303,7 +344,7 @@
 
     deps = [
       ":common",
-      ":storage",
+      ":storage_full",
       "../../gn:default_deps",
       "../../gn:sqlite",
       "../../protos/perfetto/trace/ftrace:zero",
@@ -375,7 +416,6 @@
 perfetto_unittest_source_set("unittests") {
   testonly = true
   sources = [
-    "basic_types_unittest.cc",
     "clock_tracker_unittest.cc",
     "event_tracker_unittest.cc",
     "forwarding_trace_parser_unittest.cc",
@@ -385,6 +425,7 @@
     "importers/systrace/systrace_parser_unittest.cc",
     "null_term_string_view_unittest.cc",
     "process_tracker_unittest.cc",
+    "protozero_to_text_unittests.cc",
     "slice_tracker_unittest.cc",
     "string_pool_unittest.cc",
     "trace_sorter_unittest.cc",
@@ -392,7 +433,8 @@
   deps = [
     ":common",
     ":descriptors",
-    ":storage",
+    ":protozero_to_text",
+    ":storage_full",
     "../../gn:default_deps",
     "../../gn:gtest_and_gmock",
     "../../protos/perfetto/common:zero",
@@ -473,10 +515,9 @@
     sources += [ "trace_database_integrationtest.cc" ]
     deps += [
       ":lib",
-      ":storage",
+      ":storage_full",
       "../../gn:default_deps",
       "../../gn:gtest_and_gmock",
-      "../../protos/perfetto/trace:lite",
       "../base",
       "../base:test_support",
       "sqlite",
@@ -494,7 +535,7 @@
     "trace_parsing_fuzzer.cc",
   ]
   deps = [
-    ":storage",
+    ":storage_full",
     "../../gn:default_deps",
     "../base",
   ]
diff --git a/src/trace_processor/basic_types_unittest.cc b/src/trace_processor/basic_types_unittest.cc
deleted file mode 100644
index a2a0fd2..0000000
--- a/src/trace_processor/basic_types_unittest.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 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
- *
- *      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.
- */
-
-#include "perfetto/trace_processor/basic_types.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-TEST(SqlValueTest, DifferentTypes) {
-  ASSERT_LT(SqlValue(), SqlValue::Long(10));
-  ASSERT_LT(SqlValue::Long(10), SqlValue::Double(10.0));
-  ASSERT_LT(SqlValue::Double(10.0), SqlValue::String("10"));
-}
-
-TEST(SqlValueTest, CompareLong) {
-  SqlValue int32_min = SqlValue::Long(std::numeric_limits<int32_t>::min());
-  SqlValue minus_1 = SqlValue::Long(-1);
-  SqlValue zero = SqlValue::Long(0);
-  SqlValue uint32_max = SqlValue::Long(std::numeric_limits<uint32_t>::max());
-
-  ASSERT_LT(int32_min, minus_1);
-  ASSERT_LT(int32_min, uint32_max);
-  ASSERT_LT(minus_1, uint32_max);
-
-  ASSERT_GT(uint32_max, zero);
-
-  ASSERT_EQ(zero, zero);
-}
-
-TEST(SqlValueTest, CompareDouble) {
-  SqlValue int32_min = SqlValue::Double(std::numeric_limits<int32_t>::min());
-  SqlValue minus_1 = SqlValue::Double(-1.0);
-  SqlValue zero = SqlValue::Double(0);
-  SqlValue uint32_max = SqlValue::Double(std::numeric_limits<uint32_t>::max());
-
-  ASSERT_LT(int32_min, minus_1);
-  ASSERT_LT(int32_min, uint32_max);
-  ASSERT_LT(minus_1, uint32_max);
-
-  ASSERT_GT(uint32_max, zero);
-
-  ASSERT_EQ(zero, zero);
-}
-
-TEST(SqlValueTest, CompareString) {
-  SqlValue a = SqlValue::String("a");
-  SqlValue aa = SqlValue::String("aa");
-  SqlValue b = SqlValue::String("b");
-
-  ASSERT_LT(a, aa);
-  ASSERT_LT(aa, b);
-  ASSERT_LT(a, b);
-
-  ASSERT_GT(aa, a);
-
-  ASSERT_EQ(a, a);
-  ASSERT_EQ(aa, SqlValue::String("aa"));
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/db/BUILD.gn b/src/trace_processor/db/BUILD.gn
index 57366d2..30e2518 100644
--- a/src/trace_processor/db/BUILD.gn
+++ b/src/trace_processor/db/BUILD.gn
@@ -22,6 +22,7 @@
     "bit_vector_iterators.h",
     "column.cc",
     "column.h",
+    "compare.h",
     "row_map.cc",
     "row_map.h",
     "sparse_vector.h",
@@ -42,6 +43,7 @@
   testonly = true
   sources = [
     "bit_vector_unittest.cc",
+    "compare_unittest.cc",
     "row_map_unittest.cc",
     "sparse_vector_unittest.cc",
   ]
diff --git a/src/trace_processor/db/column.cc b/src/trace_processor/db/column.cc
index d3daf67..fd9f6b2 100644
--- a/src/trace_processor/db/column.cc
+++ b/src/trace_processor/db/column.cc
@@ -16,6 +16,7 @@
 
 #include "src/trace_processor/db/column.h"
 
+#include "src/trace_processor/db/compare.h"
 #include "src/trace_processor/db/table.h"
 
 namespace perfetto {
@@ -66,33 +67,33 @@
   switch (type_) {
     case ColumnType::kInt32: {
       if (IsNullable()) {
-        FilterIntoLongSlow<int32_t, true /* is_nullable */>(op, value, rm);
+        FilterIntoNumericSlow<int32_t, true /* is_nullable */>(op, value, rm);
       } else {
-        FilterIntoLongSlow<int32_t, false /* is_nullable */>(op, value, rm);
+        FilterIntoNumericSlow<int32_t, false /* is_nullable */>(op, value, rm);
       }
       break;
     }
     case ColumnType::kUint32: {
       if (IsNullable()) {
-        FilterIntoLongSlow<uint32_t, true /* is_nullable */>(op, value, rm);
+        FilterIntoNumericSlow<uint32_t, true /* is_nullable */>(op, value, rm);
       } else {
-        FilterIntoLongSlow<uint32_t, false /* is_nullable */>(op, value, rm);
+        FilterIntoNumericSlow<uint32_t, false /* is_nullable */>(op, value, rm);
       }
       break;
     }
     case ColumnType::kInt64: {
       if (IsNullable()) {
-        FilterIntoLongSlow<int64_t, true /* is_nullable */>(op, value, rm);
+        FilterIntoNumericSlow<int64_t, true /* is_nullable */>(op, value, rm);
       } else {
-        FilterIntoLongSlow<int64_t, false /* is_nullable */>(op, value, rm);
+        FilterIntoNumericSlow<int64_t, false /* is_nullable */>(op, value, rm);
       }
       break;
     }
     case ColumnType::kDouble: {
       if (IsNullable()) {
-        FilterIntoDoubleSlow<true /* is_nullable */>(op, value, rm);
+        FilterIntoNumericSlow<double, true /* is_nullable */>(op, value, rm);
       } else {
-        FilterIntoDoubleSlow<false /* is_nullable */>(op, value, rm);
+        FilterIntoNumericSlow<double, false /* is_nullable */>(op, value, rm);
       }
       break;
     }
@@ -108,9 +109,12 @@
 }
 
 template <typename T, bool is_nullable>
-void Column::FilterIntoLongSlow(FilterOp op, SqlValue value, RowMap* rm) const {
+void Column::FilterIntoNumericSlow(FilterOp op,
+                                   SqlValue value,
+                                   RowMap* rm) const {
   PERFETTO_DCHECK(IsNullable() == is_nullable);
   PERFETTO_DCHECK(type_ == ToColumnType<T>());
+  PERFETTO_DCHECK(std::is_arithmetic<T>::value);
 
   if (op == FilterOp::kIsNull) {
     PERFETTO_DCHECK(value.is_null());
@@ -132,165 +136,107 @@
     return;
   }
 
-  if (value.type != SqlValue::Type::kLong) {
+  if (value.type == SqlValue::Type::kDouble) {
+    double double_value = value.double_value;
+    if (std::is_same<T, double>::value) {
+      auto fn = [double_value](T v) {
+        // We static cast here as this code will be compiled even when T ==
+        // int64_t as we don't have if constexpr in C++11. In reality the cast
+        // is a noop but we cannot statically verify that for the compiler.
+        return compare::Numeric(static_cast<double>(v), double_value);
+      };
+      FilterIntoNumericWithComparatorSlow<T, is_nullable>(op, rm, fn);
+    } else {
+      auto fn = [double_value](T v) {
+        // We static cast here as this code will be compiled even when T ==
+        // double as we don't have if constexpr in C++11. In reality the cast is
+        // a noop but we cannot statically verify that for the compiler.
+        return compare::LongToDouble(static_cast<int64_t>(v), double_value);
+      };
+      FilterIntoNumericWithComparatorSlow<T, is_nullable>(op, rm, fn);
+    }
+  } else if (value.type == SqlValue::Type::kLong) {
+    int64_t long_value = value.long_value;
+    if (std::is_same<T, double>::value) {
+      auto fn = [long_value](T v) {
+        // We negate the return value as the long is always the first parameter
+        // for this function even though the LHS of the comparator should
+        // actually be |v|. This saves us having a duplicate implementation of
+        // the comparision function.
+        return -compare::LongToDouble(long_value, v);
+      };
+      FilterIntoNumericWithComparatorSlow<T, is_nullable>(op, rm, fn);
+    } else {
+      auto fn = [long_value](T v) {
+        // We static cast here as this code will be compiled even when T ==
+        // double as we don't have if constexpr in C++11. In reality the cast is
+        // a noop but we cannot statically verify that for the compiler.
+        return compare::Numeric(static_cast<int64_t>(v), long_value);
+      };
+      FilterIntoNumericWithComparatorSlow<T, is_nullable>(op, rm, fn);
+    }
+  } else {
     rm->Intersect(RowMap());
-    return;
-  }
-
-  int64_t long_value = value.long_value;
-  switch (op) {
-    case FilterOp::kLt:
-      row_map().FilterInto(rm, [this, long_value](uint32_t idx) {
-        if (is_nullable) {
-          auto opt_value = sparse_vector<T>().Get(idx);
-          return opt_value && *opt_value < long_value;
-        }
-        return sparse_vector<T>().GetNonNull(idx) < long_value;
-      });
-      break;
-    case FilterOp::kEq:
-      row_map().FilterInto(rm, [this, long_value](uint32_t idx) {
-        if (is_nullable) {
-          auto opt_value = sparse_vector<T>().Get(idx);
-          return opt_value && opt_value == long_value;
-        }
-        return sparse_vector<T>().GetNonNull(idx) == long_value;
-      });
-      break;
-    case FilterOp::kGt:
-      row_map().FilterInto(rm, [this, long_value](uint32_t idx) {
-        if (is_nullable) {
-          auto opt_value = sparse_vector<T>().Get(idx);
-          return opt_value && opt_value > long_value;
-        }
-        return sparse_vector<T>().GetNonNull(idx) > long_value;
-      });
-      break;
-    case FilterOp::kNe:
-      row_map().FilterInto(rm, [this, long_value](uint32_t idx) {
-        if (is_nullable) {
-          auto opt_value = sparse_vector<T>().Get(idx);
-          return opt_value && opt_value != long_value;
-        }
-        return sparse_vector<T>().GetNonNull(idx) != long_value;
-      });
-      break;
-    case FilterOp::kLe:
-      row_map().FilterInto(rm, [this, long_value](uint32_t idx) {
-        if (is_nullable) {
-          auto opt_value = sparse_vector<T>().Get(idx);
-          return opt_value && opt_value <= long_value;
-        }
-        return sparse_vector<T>().GetNonNull(idx) <= long_value;
-      });
-      break;
-    case FilterOp::kGe:
-      row_map().FilterInto(rm, [this, long_value](uint32_t idx) {
-        if (is_nullable) {
-          auto opt_value = sparse_vector<T>().Get(idx);
-          return opt_value && opt_value >= long_value;
-        }
-        return sparse_vector<T>().GetNonNull(idx) >= long_value;
-      });
-      break;
-    case FilterOp::kLike:
-      rm->Intersect(RowMap());
-      break;
-    case FilterOp::kIsNull:
-    case FilterOp::kIsNotNull:
-      PERFETTO_FATAL("Should be handled above");
   }
 }
 
-template <bool is_nullable>
-void Column::FilterIntoDoubleSlow(FilterOp op,
-                                  SqlValue value,
-                                  RowMap* rm) const {
-  PERFETTO_DCHECK(IsNullable() == is_nullable);
-  PERFETTO_DCHECK(type_ == ColumnType::kDouble);
-
-  if (op == FilterOp::kIsNull) {
-    PERFETTO_DCHECK(value.is_null());
-    if (is_nullable) {
-      row_map().FilterInto(rm, [this](uint32_t row) {
-        return !sparse_vector<double>().Get(row).has_value();
-      });
-    } else {
-      rm->Intersect(RowMap());
-    }
-    return;
-  } else if (op == FilterOp::kIsNotNull) {
-    PERFETTO_DCHECK(value.is_null());
-    if (is_nullable) {
-      row_map().FilterInto(rm, [this](uint32_t row) {
-        return sparse_vector<double>().Get(row).has_value();
-      });
-    }
-    return;
-  }
-
-  if (value.type != SqlValue::Type::kDouble) {
-    rm->Intersect(RowMap());
-    return;
-  }
-
-  double double_value = value.double_value;
+template <typename T, bool is_nullable, typename Comparator>
+void Column::FilterIntoNumericWithComparatorSlow(FilterOp op,
+                                                 RowMap* rm,
+                                                 Comparator cmp) const {
   switch (op) {
     case FilterOp::kLt:
-      row_map().FilterInto(rm, [this, double_value](uint32_t idx) {
+      row_map().FilterInto(rm, [this, &cmp](uint32_t idx) {
         if (is_nullable) {
-          auto opt_value = sparse_vector<double>().Get(idx);
-          return opt_value && opt_value < double_value;
+          auto opt_value = sparse_vector<T>().Get(idx);
+          return opt_value && cmp(*opt_value) < 0;
         }
-        return sparse_vector<double>().GetNonNull(idx) < double_value;
+        return cmp(sparse_vector<T>().GetNonNull(idx)) < 0;
       });
       break;
     case FilterOp::kEq:
-      row_map().FilterInto(rm, [this, double_value](uint32_t idx) {
+      row_map().FilterInto(rm, [this, &cmp](uint32_t idx) {
         if (is_nullable) {
-          auto opt_value = sparse_vector<double>().Get(idx);
-          return opt_value && std::equal_to<double>()(*opt_value, double_value);
+          auto opt_value = sparse_vector<T>().Get(idx);
+          return opt_value && cmp(*opt_value) == 0;
         }
-        auto v = sparse_vector<double>().GetNonNull(idx);
-        return std::equal_to<double>()(v, double_value);
+        return cmp(sparse_vector<T>().GetNonNull(idx)) == 0;
       });
       break;
     case FilterOp::kGt:
-      row_map().FilterInto(rm, [this, double_value](uint32_t idx) {
+      row_map().FilterInto(rm, [this, &cmp](uint32_t idx) {
         if (is_nullable) {
-          auto opt_value = sparse_vector<double>().Get(idx);
-          return opt_value && opt_value > double_value;
+          auto opt_value = sparse_vector<T>().Get(idx);
+          return opt_value && cmp(*opt_value) > 0;
         }
-        return sparse_vector<double>().GetNonNull(idx) > double_value;
+        return cmp(sparse_vector<T>().GetNonNull(idx)) > 0;
       });
       break;
     case FilterOp::kNe:
-      row_map().FilterInto(rm, [this, double_value](uint32_t idx) {
+      row_map().FilterInto(rm, [this, &cmp](uint32_t idx) {
         if (is_nullable) {
-          auto opt_value = sparse_vector<double>().Get(idx);
-          return opt_value &&
-                 std::not_equal_to<double>()(*opt_value, double_value);
+          auto opt_value = sparse_vector<T>().Get(idx);
+          return opt_value && cmp(*opt_value) != 0;
         }
-        auto v = sparse_vector<double>().GetNonNull(idx);
-        return std::not_equal_to<double>()(v, double_value);
+        return cmp(sparse_vector<T>().GetNonNull(idx)) != 0;
       });
       break;
     case FilterOp::kLe:
-      row_map().FilterInto(rm, [this, double_value](uint32_t idx) {
+      row_map().FilterInto(rm, [this, &cmp](uint32_t idx) {
         if (is_nullable) {
-          auto opt_value = sparse_vector<double>().Get(idx);
-          return opt_value && opt_value <= double_value;
+          auto opt_value = sparse_vector<T>().Get(idx);
+          return opt_value && cmp(*opt_value) <= 0;
         }
-        return sparse_vector<double>().GetNonNull(idx) <= double_value;
+        return cmp(sparse_vector<T>().GetNonNull(idx)) <= 0;
       });
       break;
     case FilterOp::kGe:
-      row_map().FilterInto(rm, [this, double_value](uint32_t idx) {
+      row_map().FilterInto(rm, [this, &cmp](uint32_t idx) {
         if (is_nullable) {
-          auto opt_value = sparse_vector<double>().Get(idx);
-          return opt_value && opt_value >= double_value;
+          auto opt_value = sparse_vector<T>().Get(idx);
+          return opt_value && cmp(*opt_value) >= 0;
         }
-        return sparse_vector<double>().GetNonNull(idx) >= double_value;
+        return cmp(sparse_vector<T>().GetNonNull(idx)) >= 0;
       });
       break;
     case FilterOp::kLike:
@@ -327,41 +273,43 @@
   }
 
   NullTermStringView str_value = value.string_value;
+  PERFETTO_DCHECK(str_value.data() != nullptr);
+
   switch (op) {
     case FilterOp::kLt:
       row_map().FilterInto(rm, [this, str_value](uint32_t idx) {
         auto v = GetStringPoolStringAtIdx(idx);
-        return v.data() != nullptr && v < str_value;
+        return v.data() != nullptr && compare::String(v, str_value) < 0;
       });
       break;
     case FilterOp::kEq:
       row_map().FilterInto(rm, [this, str_value](uint32_t idx) {
         auto v = GetStringPoolStringAtIdx(idx);
-        return v.data() != nullptr && v == str_value;
+        return v.data() != nullptr && compare::String(v, str_value) == 0;
       });
       break;
     case FilterOp::kGt:
       row_map().FilterInto(rm, [this, str_value](uint32_t idx) {
         auto v = GetStringPoolStringAtIdx(idx);
-        return v.data() != nullptr && v > str_value;
+        return v.data() != nullptr && compare::String(v, str_value) > 0;
       });
       break;
     case FilterOp::kNe:
       row_map().FilterInto(rm, [this, str_value](uint32_t idx) {
         auto v = GetStringPoolStringAtIdx(idx);
-        return v.data() != nullptr && v != str_value;
+        return v.data() != nullptr && compare::String(v, str_value) != 0;
       });
       break;
     case FilterOp::kLe:
       row_map().FilterInto(rm, [this, str_value](uint32_t idx) {
         auto v = GetStringPoolStringAtIdx(idx);
-        return v.data() != nullptr && v <= str_value;
+        return v.data() != nullptr && compare::String(v, str_value) <= 0;
       });
       break;
     case FilterOp::kGe:
       row_map().FilterInto(rm, [this, str_value](uint32_t idx) {
         auto v = GetStringPoolStringAtIdx(idx);
-        return v.data() != nullptr && v >= str_value;
+        return v.data() != nullptr && compare::String(v, str_value) >= 0;
       });
       break;
     case FilterOp::kLike:
@@ -395,28 +343,34 @@
   uint32_t id_value = static_cast<uint32_t>(value.long_value);
   switch (op) {
     case FilterOp::kLt:
-      row_map().FilterInto(rm,
-                           [id_value](uint32_t idx) { return idx < id_value; });
+      row_map().FilterInto(rm, [id_value](uint32_t idx) {
+        return compare::Numeric(idx, id_value) < 0;
+      });
       break;
     case FilterOp::kEq:
-      row_map().FilterInto(
-          rm, [id_value](uint32_t idx) { return idx == id_value; });
+      row_map().FilterInto(rm, [id_value](uint32_t idx) {
+        return compare::Numeric(idx, id_value) == 0;
+      });
       break;
     case FilterOp::kGt:
-      row_map().FilterInto(rm,
-                           [id_value](uint32_t idx) { return idx > id_value; });
+      row_map().FilterInto(rm, [id_value](uint32_t idx) {
+        return compare::Numeric(idx, id_value) > 0;
+      });
       break;
     case FilterOp::kNe:
-      row_map().FilterInto(
-          rm, [id_value](uint32_t idx) { return idx != id_value; });
+      row_map().FilterInto(rm, [id_value](uint32_t idx) {
+        return compare::Numeric(idx, id_value) != 0;
+      });
       break;
     case FilterOp::kLe:
-      row_map().FilterInto(
-          rm, [id_value](uint32_t idx) { return idx <= id_value; });
+      row_map().FilterInto(rm, [id_value](uint32_t idx) {
+        return compare::Numeric(idx, id_value) <= 0;
+      });
       break;
     case FilterOp::kGe:
-      row_map().FilterInto(
-          rm, [id_value](uint32_t idx) { return idx >= id_value; });
+      row_map().FilterInto(rm, [id_value](uint32_t idx) {
+        return compare::Numeric(idx, id_value) >= 0;
+      });
       break;
     case FilterOp::kLike:
       rm->Intersect(RowMap());
@@ -432,33 +386,33 @@
   switch (type_) {
     case ColumnType::kInt32: {
       if (IsNullable()) {
-        StableSort<desc, int32_t, true /* is_nullable */>(out);
+        StableSortNumeric<desc, int32_t, true /* is_nullable */>(out);
       } else {
-        StableSort<desc, int32_t, false /* is_nullable */>(out);
+        StableSortNumeric<desc, int32_t, false /* is_nullable */>(out);
       }
       break;
     }
     case ColumnType::kUint32: {
       if (IsNullable()) {
-        StableSort<desc, uint32_t, true /* is_nullable */>(out);
+        StableSortNumeric<desc, uint32_t, true /* is_nullable */>(out);
       } else {
-        StableSort<desc, uint32_t, false /* is_nullable */>(out);
+        StableSortNumeric<desc, uint32_t, false /* is_nullable */>(out);
       }
       break;
     }
     case ColumnType::kInt64: {
       if (IsNullable()) {
-        StableSort<desc, int64_t, true /* is_nullable */>(out);
+        StableSortNumeric<desc, int64_t, true /* is_nullable */>(out);
       } else {
-        StableSort<desc, int64_t, false /* is_nullable */>(out);
+        StableSortNumeric<desc, int64_t, false /* is_nullable */>(out);
       }
       break;
     }
     case ColumnType::kDouble: {
       if (IsNullable()) {
-        StableSort<desc, double, true /* is_nullable */>(out);
+        StableSortNumeric<desc, double, true /* is_nullable */>(out);
       } else {
-        StableSort<desc, double, false /* is_nullable */>(out);
+        StableSortNumeric<desc, double, false /* is_nullable */>(out);
       }
       break;
     }
@@ -466,19 +420,22 @@
       row_map().StableSort(out, [this](uint32_t a_idx, uint32_t b_idx) {
         auto a_str = GetStringPoolStringAtIdx(a_idx);
         auto b_str = GetStringPoolStringAtIdx(b_idx);
-        return desc ? b_str < a_str : a_str < b_str;
+
+        int res = compare::NullableString(a_str, b_str);
+        return desc ? res > 0 : res < 0;
       });
       break;
     }
     case ColumnType::kId:
       row_map().StableSort(out, [](uint32_t a_idx, uint32_t b_idx) {
-        return desc ? b_idx < a_idx : a_idx < b_idx;
+        int res = compare::Numeric(a_idx, b_idx);
+        return desc ? res > 0 : res < 0;
       });
   }
 }
 
 template <bool desc, typename T, bool is_nullable>
-void Column::StableSort(std::vector<uint32_t>* out) const {
+void Column::StableSortNumeric(std::vector<uint32_t>* out) const {
   PERFETTO_DCHECK(IsNullable() == is_nullable);
   PERFETTO_DCHECK(ToColumnType<T>() == type_);
 
@@ -487,11 +444,15 @@
     if (is_nullable) {
       auto a_val = sv.Get(a_idx);
       auto b_val = sv.Get(b_idx);
-      return desc ? b_val < a_val : a_val < b_val;
+
+      int res = compare::NullableNumeric(a_val, b_val);
+      return desc ? res > 0 : res < 0;
     }
     auto a_val = sv.GetNonNull(a_idx);
     auto b_val = sv.GetNonNull(b_idx);
-    return desc ? b_val < a_val : a_val < b_val;
+
+    int res = compare::Numeric(a_val, b_val);
+    return desc ? res > 0 : res < 0;
   });
 }
 
diff --git a/src/trace_processor/db/column.h b/src/trace_processor/db/column.h
index 73990d2..0e3d927 100644
--- a/src/trace_processor/db/column.h
+++ b/src/trace_processor/db/column.h
@@ -22,6 +22,7 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/optional.h"
 #include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/db/compare.h"
 #include "src/trace_processor/db/row_map.h"
 #include "src/trace_processor/db/sparse_vector.h"
 #include "src/trace_processor/string_pool.h"
@@ -131,7 +132,7 @@
       case ColumnType::kDouble:
       case ColumnType::kString: {
         for (uint32_t i = 0; i < row_map().size(); i++) {
-          if (Get(i) == value)
+          if (compare::SqlValue(Get(i), value) == 0)
             return i;
         }
         return base::nullopt;
@@ -389,28 +390,34 @@
     Iterator e(this, row_map().size());
     switch (op) {
       case FilterOp::kEq: {
-        uint32_t beg = std::distance(b, std::lower_bound(b, e, value));
-        uint32_t end = std::distance(b, std::upper_bound(b, e, value));
+        uint32_t beg = std::distance(
+            b, std::lower_bound(b, e, value, &compare::SqlValueComparator));
+        uint32_t end = std::distance(
+            b, std::upper_bound(b, e, value, &compare::SqlValueComparator));
         rm->Intersect(RowMap(beg, end));
         return true;
       }
       case FilterOp::kLe: {
-        uint32_t end = std::distance(b, std::upper_bound(b, e, value));
+        uint32_t end = std::distance(
+            b, std::upper_bound(b, e, value, &compare::SqlValueComparator));
         rm->Intersect(RowMap(0, end));
         return true;
       }
       case FilterOp::kLt: {
-        uint32_t end = std::distance(b, std::lower_bound(b, e, value));
+        uint32_t end = std::distance(
+            b, std::lower_bound(b, e, value, &compare::SqlValueComparator));
         rm->Intersect(RowMap(0, end));
         return true;
       }
       case FilterOp::kGe: {
-        uint32_t beg = std::distance(b, std::lower_bound(b, e, value));
+        uint32_t beg = std::distance(
+            b, std::lower_bound(b, e, value, &compare::SqlValueComparator));
         rm->Intersect(RowMap(beg, row_map().size()));
         return true;
       }
       case FilterOp::kGt: {
-        uint32_t beg = std::distance(b, std::upper_bound(b, e, value));
+        uint32_t beg = std::distance(
+            b, std::upper_bound(b, e, value, &compare::SqlValueComparator));
         rm->Intersect(RowMap(beg, row_map().size()));
         return true;
       }
@@ -426,13 +433,16 @@
   // Slow path filter method which will perform a full table scan.
   void FilterIntoSlow(FilterOp op, SqlValue value, RowMap* rm) const;
 
-  // Slow path filter method for integers which will perform a full table scan.
+  // Slow path filter method for numerics which will perform a full table scan.
   template <typename T, bool is_nullable>
-  void FilterIntoLongSlow(FilterOp op, SqlValue value, RowMap* rm) const;
+  void FilterIntoNumericSlow(FilterOp op, SqlValue value, RowMap* rm) const;
 
-  // Slow path filter method for doubles which will perform a full table scan.
-  template <bool is_nullable>
-  void FilterIntoDoubleSlow(FilterOp op, SqlValue value, RowMap* rm) const;
+  // Slow path filter method for numerics with a comparator which will perform a
+  // full table scan.
+  template <typename T, bool is_nullable, typename Comparator = int(T)>
+  void FilterIntoNumericWithComparatorSlow(FilterOp op,
+                                           RowMap* rm,
+                                           Comparator cmp) const;
 
   // Slow path filter method for strings which will perform a full table scan.
   void FilterIntoStringSlow(FilterOp op, SqlValue value, RowMap* rm) const;
@@ -447,7 +457,7 @@
   // Stable sorts this column storing the result in |out|.
   // |T| and |is_nullable| should match the type and nullability of this column.
   template <bool desc, typename T, bool is_nullable>
-  void StableSort(std::vector<uint32_t>* out) const;
+  void StableSortNumeric(std::vector<uint32_t>* out) const;
 
   template <typename T>
   static ColumnType ToColumnType() {
diff --git a/src/trace_processor/db/compare.h b/src/trace_processor/db/compare.h
new file mode 100644
index 0000000..9f3f9a5
--- /dev/null
+++ b/src/trace_processor/db/compare.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 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
+ *
+ *      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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_DB_COMPARE_H_
+#define SRC_TRACE_PROCESSOR_DB_COMPARE_H_
+
+#include <stdint.h>
+
+#include "perfetto/ext/base/optional.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/trace_processor/basic_types.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace compare {
+
+// This file contains the de-facto impleemntation of all comparisions used by
+// trace processor in every setting. All of this is centralised in one file to
+// ensure both internal consistency with SQLite and consistency with SQLite.
+
+// Compare a non-null numeric to a double; returns:
+//  * <0 if i < d,
+//  * >0 if i > d.
+//  *  0 otherwise
+// This code matches the behaviour of sqlite3IntFloatCompare.
+inline int LongToDouble(int64_t i, double d) {
+  // First check if we are out of range for a int64_t. We use the constants
+  // directly instead of using numeric_limits as the casts introduces rounding
+  // in the doubles as a double cannot exactly represent int64::max().
+  if (d >= 9223372036854775808.0)
+    return -1;
+  if (d < -9223372036854775808.0)
+    return 1;
+
+  // Then, try to compare in int64 space to try and keep as much precision as
+  // possible.
+  int64_t d_i = static_cast<int64_t>(d);
+  if (i < d_i)
+    return -1;
+  if (i > d_i)
+    return 1;
+
+  // Finally, try and compare in double space, sacrificing precision if
+  // necessary.
+  double i_d = static_cast<double>(i);
+  return (i_d < d) ? -1 : (i_d > d ? 1 : 0);
+}
+
+// Compares two non-null numeric values; returns:
+//  * <0 if a < b,
+//  * >0 if a > b.
+//  *  0 otherwise
+// This code matches the behaviour of the inline code in the comparision path of
+// sqlite3VdbeExec (for ints) and the behaviour of sqlite3MemCompare (for
+// doubles).
+template <typename T>
+inline int Numeric(T a, T b) {
+  static_assert(std::is_arithmetic<T>::value,
+                "Numeric comparision performed with non-numeric type");
+  return a < b ? -1 : (a > b ? 1 : 0);
+}
+
+// Compares two non-null bytes values; returns:
+//  * <0 if a < b,
+//  * >0 if a > b.
+//  *  0 otherwise
+// This code matches the behaviour of sqlite3BlobCompare.
+inline int Bytes(const void* a, size_t a_n, const void* b, size_t b_n) {
+  int res = memcmp(a, b, std::min(a_n, b_n));
+  return res != 0 ? res
+                  : static_cast<int>(static_cast<int64_t>(a_n) -
+                                     static_cast<int64_t>(b_n));
+}
+
+// Compares two non-null string values; returns:
+//  * <0 if a < b,
+//  * >0 if a > b.
+//  *  0 otherwise
+// This code matches the behaviour of sqlite3BlobCompare which is called when
+// there is no collation sequence defined in sqlite3MemCompare.
+inline int String(base::StringView a, base::StringView b) {
+  PERFETTO_DCHECK(a.data() != nullptr);
+  PERFETTO_DCHECK(b.data() != nullptr);
+  return Bytes(a.data(), a.size(), b.data(), b.size());
+}
+
+// Compares two nullable numeric values; returns:
+//  *  0 if both a and b are null
+//  * <0 if a is null and b is non null
+//  * >0 if a is non null and b is null
+//  * <0 if a < b (a and b both non null)
+//  * >0 if a > b (a and b both non null)
+//  *  0 otherwise
+// Should only be used for defining an ordering on value of type T. For filter
+// functions, compare::Numeric should be used above after checking if the value
+// is null.
+// This method was defined from observing the behaviour of SQLite when sorting
+// on columns containing nulls.
+template <typename T>
+inline int NullableNumeric(base::Optional<T> a, base::Optional<T> b) {
+  if (!a)
+    return b ? -1 : 0;
+
+  if (!b)
+    return 1;
+
+  return compare::Numeric(*a, *b);
+}
+
+// Compares two strings, either of which can be null; returns:
+//  *  0 if both a and b are null
+//  * <0 if a is null and b is non null
+//  * >0 if a is non null and b is null
+//  * <0 if a < b (a and b both non null)
+//  * >0 if a > b (a and b both non null)
+//  *  0 otherwise
+// Should only be used for defining an ordering on value of type T. For filter
+// functions, compare::String should be used above after checking if the value
+// is null.
+// This method was defined from observing the behaviour of SQLite when sorting
+// on columns containing nulls.
+inline int NullableString(base::StringView a, base::StringView b) {
+  if (!a.data())
+    return b.data() ? -1 : 0;
+
+  if (!b.data())
+    return 1;
+
+  return compare::String(a, b);
+}
+
+// Compares two SqlValue; returns:
+//  * <0 if a.type < b.type and a and b are not both numeric
+//  * >0 if a.type > b.type and a and b are not both numeric
+//  * <0 if a < b (a and b both non null and either of same type or numeric)
+//  * >0 if a > b (a and b both non null and either of same type or numeric)
+//  *  0 otherwise
+// This code roughly matches the behaviour of the code in the comparision path
+// of sqlite3VdbeExec except we are intentionally more strict than SQLite when
+// it comes to casting between strings and numerics - we disallow moving between
+// the two. We do allow comparing between doubles and longs however as doubles
+// can easily appear by using constants in SQL even when intending to use longs.
+inline int SqlValue(const SqlValue& a, const SqlValue& b) {
+  if (a.type != b.type) {
+    if (a.type == SqlValue::kLong && b.type == SqlValue::kDouble)
+      return compare::LongToDouble(a.long_value, b.double_value);
+
+    if (a.type == SqlValue::kDouble && b.type == SqlValue::kLong)
+      return -compare::LongToDouble(b.long_value, a.double_value);
+
+    return a.type - b.type;
+  }
+
+  switch (a.type) {
+    case SqlValue::Type::kLong:
+      return compare::Numeric(a.long_value, b.long_value);
+    case SqlValue::Type::kDouble:
+      return compare::Numeric(a.double_value, b.double_value);
+    case SqlValue::Type::kString:
+      return compare::String(a.string_value, b.string_value);
+    case SqlValue::Type::kBytes:
+      return compare::Bytes(a.bytes_value, a.bytes_count, b.bytes_value,
+                            b.bytes_count);
+    case SqlValue::Type::kNull:
+      return 0;
+  }
+  PERFETTO_FATAL("For GCC");
+}
+
+// Implements a comparator for SqlValues to use for std algorithms.
+// See documentation of compare::SqlValue for details of how this function
+// works.
+inline int SqlValueComparator(const trace_processor::SqlValue& a,
+                              const trace_processor::SqlValue& b) {
+  return compare::SqlValue(a, b) < 0;
+}
+
+}  // namespace compare
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_DB_COMPARE_H_
diff --git a/src/trace_processor/db/compare_unittest.cc b/src/trace_processor/db/compare_unittest.cc
new file mode 100644
index 0000000..190fb9a
--- /dev/null
+++ b/src/trace_processor/db/compare_unittest.cc
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 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
+ *
+ *      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.
+ */
+
+#include "src/trace_processor/db/compare.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+TEST(CompareTest, SqlValueDifferentTypes) {
+  ASSERT_LT(compare::SqlValue(SqlValue(), SqlValue::Long(10)), 0);
+  ASSERT_LT(compare::SqlValue(SqlValue::Double(10.0), SqlValue::String("10")),
+            0);
+
+  // Numerics should still compare equal even if they have different types.
+  ASSERT_EQ(compare::SqlValue(SqlValue::Long(10), SqlValue::Double(10.0)), 0);
+}
+
+TEST(CompareTest, SqlValueLong) {
+  SqlValue int32_min = SqlValue::Long(std::numeric_limits<int32_t>::min());
+  SqlValue minus_1 = SqlValue::Long(-1);
+  SqlValue zero = SqlValue::Long(0);
+  SqlValue uint32_max = SqlValue::Long(std::numeric_limits<uint32_t>::max());
+
+  ASSERT_LT(compare::SqlValue(int32_min, minus_1), 0);
+  ASSERT_LT(compare::SqlValue(int32_min, uint32_max), 0);
+  ASSERT_LT(compare::SqlValue(minus_1, uint32_max), 0);
+
+  ASSERT_GT(compare::SqlValue(uint32_max, zero), 0);
+
+  ASSERT_EQ(compare::SqlValue(zero, zero), 0);
+}
+
+TEST(CompareTest, SqlValueDouble) {
+  SqlValue int32_min = SqlValue::Double(std::numeric_limits<int32_t>::min());
+  SqlValue minus_1 = SqlValue::Double(-1.0);
+  SqlValue zero = SqlValue::Double(0);
+  SqlValue uint32_max = SqlValue::Double(std::numeric_limits<uint32_t>::max());
+
+  ASSERT_LT(compare::SqlValue(int32_min, minus_1), 0);
+  ASSERT_LT(compare::SqlValue(int32_min, uint32_max), 0);
+  ASSERT_LT(compare::SqlValue(minus_1, uint32_max), 0);
+
+  ASSERT_GT(compare::SqlValue(uint32_max, zero), 0);
+
+  ASSERT_EQ(compare::SqlValue(zero, zero), 0);
+}
+
+TEST(CompareTest, SqlValueString) {
+  SqlValue a = SqlValue::String("a");
+  SqlValue aa = SqlValue::String("aa");
+  SqlValue b = SqlValue::String("b");
+
+  ASSERT_LT(compare::SqlValue(a, aa), 0);
+  ASSERT_LT(compare::SqlValue(aa, b), 0);
+  ASSERT_LT(compare::SqlValue(a, b), 0);
+
+  ASSERT_GT(compare::SqlValue(aa, a), 0);
+
+  ASSERT_EQ(compare::SqlValue(a, a), 0);
+  ASSERT_EQ(compare::SqlValue(aa, SqlValue::String("aa")), 0);
+}
+
+}  // namespace
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/db/row_map.h b/src/trace_processor/db/row_map.h
index 6e42e55..9b2805e 100644
--- a/src/trace_processor/db/row_map.h
+++ b/src/trace_processor/db/row_map.h
@@ -439,17 +439,36 @@
   void FilterInto(RowMap* out, Predicate p) const {
     PERFETTO_DCHECK(size() >= out->size());
 
-    switch (mode_) {
-      case Mode::kRange:
-        FilterInto(out, RangeIterator(this), p);
-        break;
-      case Mode::kBitVector:
-        FilterInto(out, bit_vector_.IterateSetBits(), p);
-        break;
-      case Mode::kIndexVector:
-        FilterInto(out, IndexVectorIterator(this), p);
-        break;
+    if (out->size() == 0) {
+      // If the output RowMap is empty, we don't need to do anything.
+      return;
     }
+
+    if (out->size() == 1) {
+      // If the output RowMap has a single entry, just lookup that entry and see
+      // if we should keep it.
+      if (!p(Get(out->Get(0))))
+        *out = RowMap();
+      return;
+    }
+
+    // TODO(lalitm): investigate whether we should have another fast path for
+    // cases where |out| has only a few entries so we can scan |out| instead of
+    // scanning |this|.
+
+    // TODO(lalit): investigate whether we should also scan |out| if |this| is
+    // a range or index vector as, in those cases, it would be fast to lookup
+    // |this| by index.
+
+    // We choose to full scan |this| rather than |out| as the performance
+    // penalty of incorrectly scanning |out| is much worse than mistakely
+    // scanning |this|.
+    // This is because scans on |out| involve an indexed lookup on |this| which
+    // (in the case of a bitvector) can be very expensive. On the other hand,
+    // scanning |this| means we never have to do indexed lookups but we may
+    // scan many more rows than necessary (as they may have already been
+    // excluded in out).
+    FilterIntoScanSelf(out, p);
   }
 
   template <typename Comparator>
@@ -482,8 +501,29 @@
     kIndexVector,
   };
 
+  // Filters the current RowMap into |out| by performing a full scan on |this|.
+  // See |FilterInto| for a full breakdown of the semantics of this function.
+  template <typename Predicate>
+  void FilterIntoScanSelf(RowMap* out, Predicate p) const {
+    switch (mode_) {
+      case Mode::kRange:
+        FilterIntoScanSelf(out, RangeIterator(this), p);
+        break;
+      case Mode::kBitVector:
+        FilterIntoScanSelf(out, bit_vector_.IterateSetBits(), p);
+        break;
+      case Mode::kIndexVector:
+        FilterIntoScanSelf(out, IndexVectorIterator(this), p);
+        break;
+    }
+  }
+
+  // Filters the current RowMap into |out| by performing a full scan on |this|
+  // using the |it|, a strongly typed iterator on |this| (a strongly typed
+  // iterator is used for performance reasons).
+  // See |FilterInto| for a full breakdown of the semantics of this function.
   template <typename Iterator, typename Predicate>
-  void FilterInto(RowMap* out, Iterator it, Predicate p) const {
+  void FilterIntoScanSelf(RowMap* out, Iterator it, Predicate p) const {
     switch (out->mode_) {
       case Mode::kRange: {
         // TODO(lalitm): investigate whether we can reuse the data inside
@@ -534,7 +574,8 @@
   void InsertIntoBitVector(uint32_t row) {
     PERFETTO_DCHECK(mode_ == Mode::kBitVector);
 
-    bit_vector_.Resize(row + 1, false);
+    if (row >= bit_vector_.size())
+      bit_vector_.Resize(row + 1, false);
     bit_vector_.Set(row);
   }
 
diff --git a/src/trace_processor/db/row_map_unittest.cc b/src/trace_processor/db/row_map_unittest.cc
index b0929af..042154d 100644
--- a/src/trace_processor/db/row_map_unittest.cc
+++ b/src/trace_processor/db/row_map_unittest.cc
@@ -87,6 +87,18 @@
   ASSERT_EQ(rm.IndexOf(10u), 4u);
 }
 
+TEST(RowMapUnittest, InsertToBitVectorBefore) {
+  RowMap rm(BitVector{true, false, true, true, false, true});
+  rm.Insert(1u);
+
+  ASSERT_EQ(rm.size(), 5u);
+  ASSERT_EQ(rm.Get(0u), 0u);
+  ASSERT_EQ(rm.Get(1u), 1u);
+  ASSERT_EQ(rm.Get(2u), 2u);
+  ASSERT_EQ(rm.Get(3u), 3u);
+  ASSERT_EQ(rm.Get(4u), 5u);
+}
+
 TEST(RowMapUnittest, InsertToBitVectorAfter) {
   RowMap rm(BitVector{true, false, true, true, false, true});
   rm.Insert(10u);
@@ -277,6 +289,37 @@
   ASSERT_EQ(rm.Get(2u), 3u);
 }
 
+TEST(RowMapUnittest, FilterIntoEmptyOutput) {
+  RowMap rm(0, 10000);
+  RowMap filter(4, 4);
+  rm.FilterInto(&filter, [](uint32_t) -> bool {
+    ADD_FAILURE() << "Should not have called lambda";
+    return true;
+  });
+
+  ASSERT_EQ(filter.size(), 0u);
+}
+
+TEST(RowMapUnittest, FilterIntoSingleRowTrue) {
+  RowMap rm(100, 10000);
+  RowMap filter(6, 7);
+  rm.FilterInto(&filter, [](uint32_t row) { return row == 106u; });
+
+  ASSERT_EQ(filter.size(), 1u);
+  ASSERT_EQ(filter.Get(0u), 6u);
+}
+
+TEST(RowMapUnittest, FilterIntoSingleRowFalse) {
+  RowMap rm(100, 10000);
+  RowMap filter(6, 7);
+  rm.FilterInto(&filter, [](uint32_t row) {
+    EXPECT_EQ(row, 106u);
+    return row != 106u;
+  });
+
+  ASSERT_EQ(filter.size(), 0u);
+}
+
 TEST(RowMapUnittest, FilterIntoRangeWithRange) {
   RowMap rm(93, 157);
   RowMap filter(4, 7);
diff --git a/src/trace_processor/db/sparse_vector_unittest.cc b/src/trace_processor/db/sparse_vector_unittest.cc
index e6474ea..cd8e43a 100644
--- a/src/trace_processor/db/sparse_vector_unittest.cc
+++ b/src/trace_processor/db/sparse_vector_unittest.cc
@@ -47,8 +47,11 @@
   sv.Set(0, 15);
   sv.Set(3, 30);
 
-  ASSERT_EQ(sv.Get(0), base::Optional<int64_t>(15));
-  ASSERT_EQ(sv.Get(3), base::Optional<int64_t>(30));
+  ASSERT_EQ(*sv.Get(0), 15);
+  ASSERT_EQ(*sv.Get(1), 20);
+  ASSERT_EQ(sv.Get(2), base::nullopt);
+  ASSERT_EQ(*sv.Get(3), 30);
+  ASSERT_EQ(*sv.Get(4), 40);
 }
 
 TEST(SparseVector, SetNonNull) {
diff --git a/src/trace_processor/db/table.cc b/src/trace_processor/db/table.cc
index 2fa7a41..823f57f 100644
--- a/src/trace_processor/db/table.cc
+++ b/src/trace_processor/db/table.cc
@@ -61,35 +61,7 @@
   return table;
 }
 
-Table Table::Filter(const std::vector<Constraint>& cs) const {
-  // TODO(lalitm): we can add optimizations here depending on whether this is
-  // an lvalue or rvalue.
-
-  if (cs.empty())
-    return Copy();
-
-  // Create a RowMap indexing all rows and filter this down to the rows which
-  // meet all the constraints.
-  RowMap rm(0, size_);
-  for (const Constraint& c : cs) {
-    columns_[c.col_idx].FilterInto(c.op, c.value, &rm);
-  }
-
-  // Return a copy of this table with the RowMaps using the computed filter
-  // RowMap and with the updated size.
-  Table table = CopyExceptRowMaps();
-  table.size_ = rm.size();
-  for (const RowMap& map : row_maps_) {
-    table.row_maps_.emplace_back(map.SelectRows(rm));
-    PERFETTO_DCHECK(table.row_maps_.back().size() == table.size());
-  }
-  return table;
-}
-
 Table Table::Sort(const std::vector<Order>& od) const {
-  // TODO(lalitm): we can add optimizations here depending on whether this is
-  // an lvalue or rvalue.
-
   if (od.empty())
     return Copy();
 
diff --git a/src/trace_processor/db/table.h b/src/trace_processor/db/table.h
index 4d29002..cc3a3d8 100644
--- a/src/trace_processor/db/table.h
+++ b/src/trace_processor/db/table.h
@@ -76,7 +76,34 @@
   Table& operator=(Table&& other) noexcept;
 
   // Filters the Table using the specified filter constraints.
-  Table Filter(const std::vector<Constraint>& cs) const;
+  Table Filter(const std::vector<Constraint>& cs) const {
+    return Apply(FilterToRowMap(cs));
+  }
+
+  // Filters the Table using the specified filter constraints.
+  // Returns a RowMap which, if applied to the table, would contain the rows
+  // post filter.
+  RowMap FilterToRowMap(const std::vector<Constraint>& cs) const {
+    RowMap rm(0, size_);
+    for (const Constraint& c : cs) {
+      columns_[c.col_idx].FilterInto(c.op, c.value, &rm);
+    }
+    return rm;
+  }
+
+  // Applies the given RowMap to the current table by picking out the rows
+  // specified in the RowMap to be present in the output table.
+  // Note: the RowMap should not reorder this table; this is guaranteed if the
+  // passed RowMap is generated using |FilterToRowMap|.
+  Table Apply(RowMap rm) const {
+    Table table = CopyExceptRowMaps();
+    table.size_ = rm.size();
+    for (const RowMap& map : row_maps_) {
+      table.row_maps_.emplace_back(map.SelectRows(rm));
+      PERFETTO_DCHECK(table.row_maps_.back().size() == table.size());
+    }
+    return table;
+  }
 
   // Sorts the Table using the specified order by constraints.
   Table Sort(const std::vector<Order>& od) const;
diff --git a/src/trace_processor/heap_profile_tracker.cc b/src/trace_processor/heap_profile_tracker.cc
index bcf85af..dc637c9 100644
--- a/src/trace_processor/heap_profile_tracker.cc
+++ b/src/trace_processor/heap_profile_tracker.cc
@@ -29,18 +29,22 @@
 
 HeapProfileTracker::~HeapProfileTracker() = default;
 
-void HeapProfileTracker::SetProfilePacketIndex(uint64_t index) {
-  if (last_profile_packet_index_ != 0 &&
-      last_profile_packet_index_ + 1 != index) {
+void HeapProfileTracker::SetProfilePacketIndex(uint32_t seq_id,
+                                               uint64_t index) {
+  SequenceState& sequence_state = sequence_state_[seq_id];
+  if (sequence_state.last_profile_packet_index != 0 &&
+      sequence_state.last_profile_packet_index + 1 != index) {
     context_->storage->IncrementStats(stats::heapprofd_missing_packet);
   }
-  last_profile_packet_index_ = index;
+  sequence_state.last_profile_packet_index = index;
 }
 
 void HeapProfileTracker::AddAllocation(
+    uint32_t seq_id,
     StackProfileTracker* stack_profile_tracker,
     const SourceAllocation& alloc,
     const StackProfileTracker::InternLookup* intern_lookup) {
+  SequenceState& sequence_state = sequence_state_[seq_id];
   auto maybe_callstack_id =
       stack_profile_tracker->FindCallstack(alloc.callstack_id, intern_lookup);
   if (!maybe_callstack_id)
@@ -64,22 +68,22 @@
   TraceStorage::HeapProfileAllocations::Row alloc_delta = alloc_row;
   TraceStorage::HeapProfileAllocations::Row free_delta = free_row;
 
-  auto prev_alloc_it = prev_alloc_.find({upid, callstack_id});
-  if (prev_alloc_it == prev_alloc_.end()) {
-    std::tie(prev_alloc_it, std::ignore) =
-        prev_alloc_.emplace(std::make_pair(upid, callstack_id),
-                            TraceStorage::HeapProfileAllocations::Row{});
+  auto prev_alloc_it = sequence_state.prev_alloc.find({upid, callstack_id});
+  if (prev_alloc_it == sequence_state.prev_alloc.end()) {
+    std::tie(prev_alloc_it, std::ignore) = sequence_state.prev_alloc.emplace(
+        std::make_pair(upid, callstack_id),
+        TraceStorage::HeapProfileAllocations::Row{});
   }
 
   TraceStorage::HeapProfileAllocations::Row& prev_alloc = prev_alloc_it->second;
   alloc_delta.count -= prev_alloc.count;
   alloc_delta.size -= prev_alloc.size;
 
-  auto prev_free_it = prev_free_.find({upid, callstack_id});
-  if (prev_free_it == prev_free_.end()) {
-    std::tie(prev_free_it, std::ignore) =
-        prev_free_.emplace(std::make_pair(upid, callstack_id),
-                           TraceStorage::HeapProfileAllocations::Row{});
+  auto prev_free_it = sequence_state.prev_free.find({upid, callstack_id});
+  if (prev_free_it == sequence_state.prev_free.end()) {
+    std::tie(prev_free_it, std::ignore) = sequence_state.prev_free.emplace(
+        std::make_pair(upid, callstack_id),
+        TraceStorage::HeapProfileAllocations::Row{});
   }
 
   TraceStorage::HeapProfileAllocations::Row& prev_free = prev_free_it->second;
@@ -95,22 +99,27 @@
   prev_free = free_row;
 }
 
-void HeapProfileTracker::StoreAllocation(SourceAllocation alloc) {
-  pending_allocs_.emplace_back(std::move(alloc));
+void HeapProfileTracker::StoreAllocation(uint32_t seq_id,
+                                         SourceAllocation alloc) {
+  SequenceState& sequence_state = sequence_state_[seq_id];
+  sequence_state.pending_allocs.emplace_back(std::move(alloc));
 }
 
 void HeapProfileTracker::CommitAllocations(
+    uint32_t seq_id,
     StackProfileTracker* stack_profile_tracker,
     const StackProfileTracker::InternLookup* intern_lookup) {
-  for (const auto& p : pending_allocs_)
-    AddAllocation(stack_profile_tracker, p, intern_lookup);
-  pending_allocs_.clear();
+  SequenceState& sequence_state = sequence_state_[seq_id];
+  for (const auto& p : sequence_state.pending_allocs)
+    AddAllocation(seq_id, stack_profile_tracker, p, intern_lookup);
+  sequence_state.pending_allocs.clear();
 }
 
 void HeapProfileTracker::FinalizeProfile(
+    uint32_t seq_id,
     StackProfileTracker* stack_profile_tracker,
     const StackProfileTracker::InternLookup* intern_lookup) {
-  CommitAllocations(stack_profile_tracker, intern_lookup);
+  CommitAllocations(seq_id, stack_profile_tracker, intern_lookup);
   stack_profile_tracker->ClearIndices();
 }
 
diff --git a/src/trace_processor/heap_profile_tracker.h b/src/trace_processor/heap_profile_tracker.h
index 8b3984f..30629b5 100644
--- a/src/trace_processor/heap_profile_tracker.h
+++ b/src/trace_processor/heap_profile_tracker.h
@@ -18,6 +18,7 @@
 #define SRC_TRACE_PROCESSOR_HEAP_PROFILE_TRACKER_H_
 
 #include <deque>
+#include <unordered_map>
 
 #include "perfetto/ext/base/optional.h"
 
@@ -45,42 +46,48 @@
     uint64_t free_count = 0;
   };
 
-  void SetProfilePacketIndex(uint64_t id);
+  void SetProfilePacketIndex(uint32_t seq_id, uint64_t id);
 
   explicit HeapProfileTracker(TraceProcessorContext* context);
 
-  void StoreAllocation(SourceAllocation);
+  void StoreAllocation(uint32_t seq_id, SourceAllocation);
 
   // Call after the last profile packet of a dump to commit the allocations
   // that had been stored using StoreAllocation and clear internal indices
   // for that dump.
-  void FinalizeProfile(StackProfileTracker* stack_profile_tracker,
+  void FinalizeProfile(uint32_t seq_id,
+                       StackProfileTracker* stack_profile_tracker,
                        const StackProfileTracker::InternLookup* lookup);
 
   // Only commit the allocations that had been stored using StoreAllocations.
   // This is only needed in tests, use FinalizeProfile instead.
-  void CommitAllocations(StackProfileTracker* stack_profile_tracker,
+  void CommitAllocations(uint32_t seq_id,
+                         StackProfileTracker* stack_profile_tracker,
                          const StackProfileTracker::InternLookup* lookup);
 
   ~HeapProfileTracker();
 
  private:
   void AddAllocation(
+      uint32_t seq_id,
       StackProfileTracker* stack_profile_tracker,
       const SourceAllocation&,
       const StackProfileTracker::InternLookup* intern_lookup = nullptr);
 
-  std::vector<SourceAllocation> pending_allocs_;
+  struct SequenceState {
+    std::vector<SourceAllocation> pending_allocs;
 
-  std::unordered_map<std::pair<UniquePid, int64_t>,
-                     TraceStorage::HeapProfileAllocations::Row>
-      prev_alloc_;
-  std::unordered_map<std::pair<UniquePid, int64_t>,
-                     TraceStorage::HeapProfileAllocations::Row>
-      prev_free_;
+    std::unordered_map<std::pair<UniquePid, int64_t>,
+                       TraceStorage::HeapProfileAllocations::Row>
+        prev_alloc;
+    std::unordered_map<std::pair<UniquePid, int64_t>,
+                       TraceStorage::HeapProfileAllocations::Row>
+        prev_free;
 
+    uint64_t last_profile_packet_index = 0;
+  };
+  std::map<uint32_t, SequenceState> sequence_state_;
   TraceProcessorContext* const context_;
-  uint64_t last_profile_packet_index_ = 0;
   const StringId empty_;
 };
 
diff --git a/src/trace_processor/heap_profile_tracker_unittest.cc b/src/trace_processor/heap_profile_tracker_unittest.cc
index f503096..ce978bf 100644
--- a/src/trace_processor/heap_profile_tracker_unittest.cc
+++ b/src/trace_processor/heap_profile_tracker_unittest.cc
@@ -40,6 +40,7 @@
 constexpr auto kMappingStart = 234;
 constexpr auto kMappingEnd = 345;
 constexpr auto kMappingLoadBias = 456;
+constexpr auto kDefaultSequence = 1;
 
 // heapprofd on Android Q has large callstack ideas, explicitly test large
 // values.
@@ -114,11 +115,11 @@
 // interned, and assert we only store one.
 TEST_F(HeapProfileTrackerDupTest, Mapping) {
   InsertMapping(kFirstPacket);
-  context.heap_profile_tracker->FinalizeProfile(stack_profile_tracker.get(),
-                                                nullptr);
+  context.heap_profile_tracker->FinalizeProfile(
+      kDefaultSequence, stack_profile_tracker.get(), nullptr);
   InsertMapping(kSecondPacket);
-  context.heap_profile_tracker->FinalizeProfile(stack_profile_tracker.get(),
-                                                nullptr);
+  context.heap_profile_tracker->FinalizeProfile(
+      kDefaultSequence, stack_profile_tracker.get(), nullptr);
 
   EXPECT_THAT(context.storage->stack_profile_mappings().build_ids(),
               ElementsAre(context.storage->InternString({kBuildIDHexName})));
@@ -140,11 +141,11 @@
 // interned, and assert we only store one.
 TEST_F(HeapProfileTrackerDupTest, Frame) {
   InsertFrame(kFirstPacket);
-  context.heap_profile_tracker->FinalizeProfile(stack_profile_tracker.get(),
-                                                nullptr);
+  context.heap_profile_tracker->FinalizeProfile(
+      kDefaultSequence, stack_profile_tracker.get(), nullptr);
   InsertFrame(kSecondPacket);
-  context.heap_profile_tracker->FinalizeProfile(stack_profile_tracker.get(),
-                                                nullptr);
+  context.heap_profile_tracker->FinalizeProfile(
+      kDefaultSequence, stack_profile_tracker.get(), nullptr);
 
   EXPECT_THAT(context.storage->stack_profile_frames().names(),
               ElementsAre(frame_name));
@@ -158,11 +159,11 @@
 // stored once.
 TEST_F(HeapProfileTrackerDupTest, Callstack) {
   InsertCallsite(kFirstPacket);
-  context.heap_profile_tracker->FinalizeProfile(stack_profile_tracker.get(),
-                                                nullptr);
+  context.heap_profile_tracker->FinalizeProfile(
+      kDefaultSequence, stack_profile_tracker.get(), nullptr);
   InsertCallsite(kSecondPacket);
-  context.heap_profile_tracker->FinalizeProfile(stack_profile_tracker.get(),
-                                                nullptr);
+  context.heap_profile_tracker->FinalizeProfile(
+      kDefaultSequence, stack_profile_tracker.get(), nullptr);
 
   const auto& callsite_table = context.storage->stack_profile_callsite_table();
   const auto& depth = callsite_table.depth();
@@ -218,7 +219,7 @@
   mapping.load_bias = 0;
   mapping.name_ids = {kMappingNameId1, kMappingNameId2};
   spt->AddMapping(0, mapping);
-  hpt->CommitAllocations(spt.get(), nullptr);
+  hpt->CommitAllocations(kDefaultSequence, spt.get(), nullptr);
   auto foo_bar_id = context.storage->string_pool().GetId("/foo/bar");
   ASSERT_NE(foo_bar_id, base::nullopt);
   EXPECT_THAT(context.storage->stack_profile_mappings().names(),
@@ -321,7 +322,7 @@
   for (uint32_t i = 0; i < base::ArraySize(callstacks); ++i)
     spt->AddCallstack(i, callstacks[i]);
 
-  hpt->CommitAllocations(spt.get(), nullptr);
+  hpt->CommitAllocations(kDefaultSequence, spt.get(), nullptr);
 
   for (size_t i = 0; i < base::ArraySize(callstacks); ++i) {
     int64_t parent = -1;
@@ -336,7 +337,7 @@
     }
   }
 
-  hpt->FinalizeProfile(spt.get(), nullptr);
+  hpt->FinalizeProfile(kDefaultSequence, spt.get(), nullptr);
 }
 
 }  // namespace
diff --git a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
index b5d69f4..e193077 100644
--- a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
@@ -3555,13 +3555,14 @@
     },
     {
         "sde_tracing_mark_write",
-        4,
+        5,
         {
             {},
             {"pid", ProtoSchemaType::kInt32},
             {"trace_name", ProtoSchemaType::kString},
             {"trace_type", ProtoSchemaType::kUint32},
             {"value", ProtoSchemaType::kInt32},
+            {"trace_begin", ProtoSchemaType::kUint32},
         },
     },
 }};
diff --git a/src/trace_processor/importers/ftrace/ftrace_module.cc b/src/trace_processor/importers/ftrace/ftrace_module.cc
new file mode 100644
index 0000000..840f330
--- /dev/null
+++ b/src/trace_processor/importers/ftrace/ftrace_module.cc
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 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
+ *
+ *      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.
+ */
+
+#include "src/trace_processor/importers/ftrace/ftrace_module.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+void FtraceModule::ParseFtracePacket(uint32_t /*cpu*/,
+                                     const TimestampedTracePiece&) {}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/importers/ftrace/ftrace_module.h b/src/trace_processor/importers/ftrace/ftrace_module.h
index fd1ace0..5f43490 100644
--- a/src/trace_processor/importers/ftrace/ftrace_module.h
+++ b/src/trace_processor/importers/ftrace/ftrace_module.h
@@ -29,44 +29,29 @@
 namespace perfetto {
 namespace trace_processor {
 
-class FtraceModule
-    : public ProtoImporterModuleBase<PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)> {
+class FtraceModule : public ProtoImporterModule {
  public:
-  explicit FtraceModule(TraceProcessorContext* context)
-      : ProtoImporterModuleBase(context),
-        tokenizer_(context),
-        parser_(context) {}
+  virtual void ParseFtracePacket(uint32_t cpu,
+                                 const TimestampedTracePiece& ttp);
+};
+
+class FtraceModuleImpl : public FtraceModule {
+ public:
+  FtraceModuleImpl(TraceProcessorContext* context);
 
   ModuleResult TokenizePacket(
       const protos::pbzero::TracePacket::Decoder& decoder,
       TraceBlobView* packet,
-      int64_t /*packet_timestamp*/,
-      PacketSequenceState* /*state*/) {
-    if (decoder.has_ftrace_events()) {
-      auto ftrace_field = decoder.ftrace_events();
-      const size_t fld_off = packet->offset_of(ftrace_field.data);
-      tokenizer_.TokenizeFtraceBundle(
-          packet->slice(fld_off, ftrace_field.size));
-      return ModuleResult::Handled();
-    }
-    return ModuleResult::Ignored();
-  }
+      int64_t packet_timestamp,
+      PacketSequenceState* state,
+      uint32_t field_id) override;
 
-  ModuleResult ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
-                           const TimestampedTracePiece&) {
-    // TODO(eseckler): implement.
-    if (decoder.has_ftrace_stats()) {
-      parser_.ParseFtraceStats(decoder.ftrace_stats());
-      return ModuleResult::Handled();
-    }
+  void ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
+                   const TimestampedTracePiece&,
+                   uint32_t field_id) override;
 
-    return ModuleResult::Ignored();
-  }
-
-  ModuleResult ParseFtracePacket(uint32_t cpu,
-                                 const TimestampedTracePiece& ttp) {
-    return parser_.ParseFtraceEvent(cpu, ttp);
-  }
+  void ParseFtracePacket(uint32_t cpu,
+                         const TimestampedTracePiece& ttp) override;
 
  private:
   FtraceTokenizer tokenizer_;
diff --git a/src/trace_processor/importers/ftrace/ftrace_module_impl.cc b/src/trace_processor/importers/ftrace/ftrace_module_impl.cc
new file mode 100644
index 0000000..2347196
--- /dev/null
+++ b/src/trace_processor/importers/ftrace/ftrace_module_impl.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 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
+ *
+ *      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.
+ */
+
+#include "perfetto/base/build_config.h"
+#include "src/trace_processor/importers/ftrace/ftrace_module.h"
+#include "src/trace_processor/importers/ftrace/ftrace_parser.h"
+#include "src/trace_processor/importers/ftrace/ftrace_tokenizer.h"
+#include "src/trace_processor/timestamped_trace_piece.h"
+#include "src/trace_processor/trace_blob_view.h"
+
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+using perfetto::protos::pbzero::TracePacket;
+
+FtraceModuleImpl::FtraceModuleImpl(TraceProcessorContext* context)
+    : tokenizer_(context), parser_(context) {
+  RegisterForField(TracePacket::kFtraceEventsFieldNumber, context);
+  RegisterForField(TracePacket::kFtraceStatsFieldNumber, context);
+}
+
+ModuleResult FtraceModuleImpl::TokenizePacket(
+    const protos::pbzero::TracePacket::Decoder& decoder,
+    TraceBlobView* packet,
+    int64_t /*packet_timestamp*/,
+    PacketSequenceState* /*state*/,
+    uint32_t field_id) {
+  if (field_id == TracePacket::kFtraceEventsFieldNumber) {
+    auto ftrace_field = decoder.ftrace_events();
+    const size_t fld_off = packet->offset_of(ftrace_field.data);
+    tokenizer_.TokenizeFtraceBundle(packet->slice(fld_off, ftrace_field.size));
+    return ModuleResult::Handled();
+  }
+  return ModuleResult::Ignored();
+}
+
+void FtraceModuleImpl::ParsePacket(
+    const protos::pbzero::TracePacket::Decoder& decoder,
+    const TimestampedTracePiece&,
+    uint32_t field_id) {
+  if (field_id == TracePacket::kFtraceStatsFieldNumber) {
+    parser_.ParseFtraceStats(decoder.ftrace_stats());
+  }
+}
+
+void FtraceModuleImpl::ParseFtracePacket(uint32_t cpu,
+                                         const TimestampedTracePiece& ttp) {
+  util::Status res = parser_.ParseFtraceEvent(cpu, ttp);
+  if (!res.ok()) {
+    PERFETTO_ELOG("%s", res.message().c_str());
+  }
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index 2882a06..c07fd8d 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -538,10 +538,15 @@
                                             ConstBytes blob) {
   protos::pbzero::SdeTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
                                                               blob.size);
+  if (!evt.has_trace_type() && !evt.has_trace_begin()) {
+    context_->storage->IncrementStats(stats::systrace_parse_failure);
+    return;
+  }
+
   uint32_t tgid = static_cast<uint32_t>(evt.pid());
   context_->systrace_parser->ParseSdeTracingMarkWrite(
-      ts, pid, static_cast<char>(evt.trace_type()), evt.trace_name(),
-      tgid, evt.value());
+      ts, pid, static_cast<char>(evt.trace_type()), evt.trace_begin(),
+      evt.trace_name(), tgid, evt.value());
 }
 
 void FtraceParser::ParseRssStat(int64_t ts, uint32_t pid, ConstBytes blob) {
diff --git a/src/trace_processor/importers/proto/android_probes_module.cc b/src/trace_processor/importers/proto/android_probes_module.cc
new file mode 100644
index 0000000..5f6c034
--- /dev/null
+++ b/src/trace_processor/importers/proto/android_probes_module.cc
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 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
+ *
+ *      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.
+ */
+
+#include "src/trace_processor/importers/proto/android_probes_module.h"
+#include "perfetto/base/build_config.h"
+#include "src/trace_processor/importers/proto/android_probes_parser.h"
+#include "src/trace_processor/timestamped_trace_piece.h"
+
+#include "protos/perfetto/config/trace_config.pbzero.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+using perfetto::protos::pbzero::TracePacket;
+
+AndroidProbesModule::AndroidProbesModule(TraceProcessorContext* context)
+    : parser_(context) {
+  RegisterForField(TracePacket::kBatteryFieldNumber, context);
+  RegisterForField(TracePacket::kPowerRailsFieldNumber, context);
+  RegisterForField(TracePacket::kAndroidLogFieldNumber, context);
+  RegisterForField(TracePacket::kPackagesListFieldNumber, context);
+}
+
+void AndroidProbesModule::ParsePacket(const TracePacket::Decoder& decoder,
+                                      const TimestampedTracePiece& ttp,
+                                      uint32_t field_id) {
+  switch (field_id) {
+    case TracePacket::kBatteryFieldNumber:
+      parser_.ParseBatteryCounters(ttp.timestamp, decoder.battery());
+      return;
+    case TracePacket::kPowerRailsFieldNumber:
+      parser_.ParsePowerRails(ttp.timestamp, decoder.power_rails());
+      return;
+    case TracePacket::kAndroidLogFieldNumber:
+      parser_.ParseAndroidLogPacket(decoder.android_log());
+      return;
+    case TracePacket::kPackagesListFieldNumber:
+      parser_.ParseAndroidPackagesList(decoder.packages_list());
+      return;
+  }
+}
+
+void AndroidProbesModule::ParseTraceConfig(
+    const protos::pbzero::TraceConfig::Decoder& decoder) {
+  if (decoder.has_statsd_metadata()) {
+    parser_.ParseStatsdMetadata(decoder.statsd_metadata());
+  }
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/android_probes_module.h b/src/trace_processor/importers/proto/android_probes_module.h
index 94d90a5..2ba7b19 100644
--- a/src/trace_processor/importers/proto/android_probes_module.h
+++ b/src/trace_processor/importers/proto/android_probes_module.h
@@ -28,45 +28,16 @@
 namespace perfetto {
 namespace trace_processor {
 
-class AndroidProbesModule : public ProtoImporterModuleBase<PERFETTO_BUILDFLAG(
-                                PERFETTO_TP_ANDROID_PROBES)> {
+class AndroidProbesModule : public ProtoImporterModule {
  public:
-  explicit AndroidProbesModule(TraceProcessorContext* context)
-      : ProtoImporterModuleBase(context), parser_(context) {}
+  explicit AndroidProbesModule(TraceProcessorContext* context);
 
-  ModuleResult ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
-                           const TimestampedTracePiece& ttp) {
-    if (decoder.has_battery()) {
-      parser_.ParseBatteryCounters(ttp.timestamp, decoder.battery());
-      return ModuleResult::Handled();
-    }
+  void ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
+                   const TimestampedTracePiece& ttp,
+                   uint32_t field_id) override;
 
-    if (decoder.has_power_rails()) {
-      parser_.ParsePowerRails(ttp.timestamp, decoder.power_rails());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_android_log()) {
-      parser_.ParseAndroidLogPacket(decoder.android_log());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_packages_list()) {
-      parser_.ParseAndroidPackagesList(decoder.packages_list());
-      return ModuleResult::Handled();
-    }
-
-    return ModuleResult::Ignored();
-  }
-
-  ModuleResult ParseTraceConfig(
-      const protos::pbzero::TraceConfig::Decoder& decoder) {
-    if (decoder.has_statsd_metadata()) {
-      parser_.ParseStatsdMetadata(decoder.statsd_metadata());
-      return ModuleResult::Handled();
-    }
-    return ModuleResult::Ignored();
-  }
+  void ParseTraceConfig(
+      const protos::pbzero::TraceConfig::Decoder& decoder) override;
 
  private:
   AndroidProbesParser parser_;
diff --git a/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h b/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h
index 1a6b94f..f13eaa1 100644
--- a/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h
+++ b/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h
@@ -25,7 +25,7 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// 0f193cc67cb890463dcc9ce4ab236c0bb16bed98
+// f242f1ac484bbe7ba4c45e77b56ab588f8015196
 // SHA1(protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto)
 // 360017d4658dfd81fbf16af8cc2abb994958af05
 
diff --git a/src/trace_processor/importers/proto/graphics_event_module.cc b/src/trace_processor/importers/proto/graphics_event_module.cc
index 7a75a99..4c9bfc2 100644
--- a/src/trace_processor/importers/proto/graphics_event_module.cc
+++ b/src/trace_processor/importers/proto/graphics_event_module.cc
@@ -28,6 +28,7 @@
   RegisterForField(TracePacket::kGpuLogFieldNumber, context);
   RegisterForField(TracePacket::kGraphicsFrameEventFieldNumber, context);
   RegisterForField(TracePacket::kVulkanMemoryEventFieldNumber, context);
+  RegisterForField(TracePacket::kVulkanApiEventFieldNumber, context);
 }
 
 GraphicsEventModule::~GraphicsEventModule() = default;
@@ -55,6 +56,9 @@
                                      ttp.packet_sequence_state_generation,
                                      decoder.vulkan_memory_event());
       return;
+    case TracePacket::kVulkanApiEventFieldNumber:
+      parser_.ParseVulkanApiEvent(decoder.vulkan_api_event());
+      return;
   }
 }
 
diff --git a/src/trace_processor/importers/proto/graphics_event_module.h b/src/trace_processor/importers/proto/graphics_event_module.h
index 6774c62..f7a36dd 100644
--- a/src/trace_processor/importers/proto/graphics_event_module.h
+++ b/src/trace_processor/importers/proto/graphics_event_module.h
@@ -27,7 +27,7 @@
 namespace perfetto {
 namespace trace_processor {
 
-class GraphicsEventModule : public NewProtoImporterModule {
+class GraphicsEventModule : public ProtoImporterModule {
  public:
   explicit GraphicsEventModule(TraceProcessorContext* context);
 
diff --git a/src/trace_processor/importers/proto/graphics_event_parser.cc b/src/trace_processor/importers/proto/graphics_event_parser.cc
index 90f062d..d4add51 100644
--- a/src/trace_processor/importers/proto/graphics_event_parser.cc
+++ b/src/trace_processor/importers/proto/graphics_event_parser.cc
@@ -29,6 +29,8 @@
 #include "protos/perfetto/trace/gpu/gpu_counter_event.pbzero.h"
 #include "protos/perfetto/trace/gpu/gpu_log.pbzero.h"
 #include "protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h"
+#include "protos/perfetto/trace/gpu/vulkan_api_event.pbzero.h"
+#include "protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h"
 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
 
 namespace perfetto {
@@ -36,6 +38,8 @@
 
 GraphicsEventParser::GraphicsEventParser(TraceProcessorContext* context)
     : context_(context),
+      vulkan_memory_tracker_(context),
+      description_id_(context->storage->InternString("description")),
       gpu_render_stage_scope_id_(
           context->storage->InternString("gpu_render_stage")),
       graphics_event_scope_id_(
@@ -64,10 +68,11 @@
            context->storage->InternString("Detach") /* DETACH */,
            context->storage->InternString("Attach") /* ATTACH */,
            context->storage->InternString("Cancel") /* CANCEL */}},
-      present_frame_name_(base::StringWriter(present_frame_,
-                                            sizeof(present_frame_))),
-      present_frame_layer_name_(base::StringWriter(present_frame_layer_,
-                                                  sizeof(present_frame_layer_))),
+      present_frame_name_(
+          base::StringWriter(present_frame_, sizeof(present_frame_))),
+      present_frame_layer_name_(
+          base::StringWriter(present_frame_layer_,
+                             sizeof(present_frame_layer_))),
       gpu_log_track_name_id_(context_->storage->InternString("GPU Log")),
       gpu_log_scope_id_(context_->storage->InternString("gpu_log")),
       tag_id_(context_->storage->InternString("tag")),
@@ -168,6 +173,40 @@
   }
 }
 
+const StringId GraphicsEventParser::GetFullStageName(
+    const protos::pbzero::GpuRenderStageEvent_Decoder& event) {
+  size_t stage_id = static_cast<size_t>(event.stage_id());
+  StringId stage_name;
+
+  if (stage_id < gpu_render_stage_ids_.size()) {
+    stage_name = gpu_render_stage_ids_[stage_id].first;
+  } else {
+    char buffer[64];
+    snprintf(buffer, sizeof(buffer), "render stage(%zu)", stage_id);
+    stage_name = context_->storage->InternString(buffer);
+  }
+  // If the slice has a render target handle, we append the hex value of the
+  // handle to the name.  If a debug marker is available, we append the name
+  // of the render target.
+  if (event.has_render_target_handle()) {
+    char buffer[256];
+    base::StringWriter str_writer(buffer, sizeof(buffer));
+    str_writer.AppendString(context_->storage->GetString(stage_name));
+    auto debug_marker_name =
+        debug_marker_names_.find(event.render_target_handle());
+    str_writer.AppendChar('[');
+    if (debug_marker_name == debug_marker_names_.end()) {
+      str_writer.AppendLiteral("0x");
+      str_writer.AppendHexInt(event.render_target_handle());
+    } else {
+      str_writer.AppendString(debug_marker_name->second);
+    }
+    str_writer.AppendChar(']');
+    stage_name = context_->storage->InternString(str_writer.GetStringView());
+  }
+  return stage_name;
+}
+
 void GraphicsEventParser::ParseGpuRenderStageEvent(int64_t ts,
                                                    ConstBytes blob) {
   protos::pbzero::GpuRenderStageEvent::Decoder event(blob.data, blob.size);
@@ -182,6 +221,8 @@
         StringId track_name = context_->storage->InternString(hw_queue.name());
         tables::GpuTrackTable::Row track(track_name.id);
         track.scope = gpu_render_stage_scope_id_;
+        track.description =
+            context_->storage->InternString(hw_queue.description());
         gpu_hw_queue_ids_.emplace_back(
             context_->track_tracker->InternGpuTrack(track));
       }
@@ -190,13 +231,20 @@
       protos::pbzero::GpuRenderStageEvent_Specifications_Description::Decoder
           stage(*it);
       if (stage.has_name()) {
-        gpu_render_stage_ids_.emplace_back(
-            context_->storage->InternString(stage.name()));
+        gpu_render_stage_ids_.emplace_back(std::make_pair(
+            context_->storage->InternString(stage.name()),
+            context_->storage->InternString(stage.description())));
       }
     }
   }
 
   auto args_callback = [this, &event](ArgsTracker* args_tracker, RowId row_id) {
+    auto description =
+        gpu_render_stage_ids_[static_cast<size_t>(event.stage_id())].second;
+    if (description != kNullStringId) {
+      args_tracker->AddArg(row_id, description_id_, description_id_,
+                           Variadic::String(description));
+    }
     for (auto it = event.extra_data(); it; ++it) {
       protos::pbzero::GpuRenderStageEvent_ExtraData_Decoder datum(*it);
       StringId name_id = context_->storage->InternString(datum.name());
@@ -207,15 +255,7 @@
   };
 
   if (event.has_event_id()) {
-    size_t stage_id = static_cast<size_t>(event.stage_id());
-    StringId stage_name;
-    if (stage_id < gpu_render_stage_ids_.size()) {
-      stage_name = gpu_render_stage_ids_[stage_id];
-    } else {
-      char buffer[64];
-      snprintf(buffer, 64, "render stage(%zu)", stage_id);
-      stage_name = context_->storage->InternString(buffer);
-    }
+    StringId stage_name = GetFullStageName(event);
     TrackId track_id =
         gpu_hw_queue_ids_[static_cast<size_t>(event.hw_queue_id())];
     const auto slice_id = context_->slice_tracker->Scoped(
@@ -408,9 +448,8 @@
         case VulkanMemoryEvent::OP_ANNOTATIONS:
           return;
       }
-      track_id =
-          context_->vulkan_memory_tracker->FindAllocationScopeCounterString(
-              allocation_scope);
+      track_id = vulkan_memory_tracker_.FindAllocationScopeCounterString(
+          allocation_scope);
       track =
           context_->track_tracker->InternProcessCounterTrack(track_id, upid);
       context_->event_tracker->PushCounter(
@@ -435,7 +474,7 @@
         case VulkanMemoryEvent::OP_ANNOTATIONS:
           return;
       }
-      track_id = context_->vulkan_memory_tracker->FindMemoryTypeCounterString(
+      track_id = vulkan_memory_tracker_.FindMemoryTypeCounterString(
           memory_type,
           VulkanMemoryTracker::DeviceCounterType::kAllocationCounter);
       track =
@@ -463,7 +502,7 @@
         case VulkanMemoryEvent::OP_ANNOTATIONS:
           return;
       }
-      track_id = context_->vulkan_memory_tracker->FindMemoryTypeCounterString(
+      track_id = vulkan_memory_tracker_.FindMemoryTypeCounterString(
           memory_type, VulkanMemoryTracker::DeviceCounterType::kBindCounter);
       track =
           context_->track_tracker->InternProcessCounterTrack(track_id, upid);
@@ -484,11 +523,10 @@
   using protos::pbzero::InternedData;
   VulkanMemoryEvent::Decoder vulkan_memory_event(blob.data, blob.size);
   tables::VulkanMemoryAllocationsTable::Row vulkan_memory_event_row;
-  vulkan_memory_event_row.source =
-      context_->vulkan_memory_tracker->FindSourceString(
-          static_cast<VulkanMemoryEvent::Source>(vulkan_memory_event.source()));
+  vulkan_memory_event_row.source = vulkan_memory_tracker_.FindSourceString(
+      static_cast<VulkanMemoryEvent::Source>(vulkan_memory_event.source()));
   vulkan_memory_event_row.operation =
-      context_->vulkan_memory_tracker->FindOperationString(
+      vulkan_memory_tracker_.FindOperationString(
           static_cast<VulkanMemoryEvent::Operation>(
               vulkan_memory_event.operation()));
   vulkan_memory_event_row.timestamp = vulkan_memory_event.timestamp();
@@ -506,8 +544,8 @@
     vulkan_memory_event_row.memory_type = vulkan_memory_event.memory_type();
   if (vulkan_memory_event.has_caller_iid()) {
     vulkan_memory_event_row.function_name =
-        context_->vulkan_memory_tracker
-            ->GetInternedString<InternedData::kFunctionNamesFieldNumber>(
+        vulkan_memory_tracker_
+            .GetInternedString<InternedData::kFunctionNamesFieldNumber>(
                 sequence_state, sequence_state_generation,
                 static_cast<uint64_t>(vulkan_memory_event.caller_iid()));
   }
@@ -522,7 +560,7 @@
         static_cast<int64_t>(vulkan_memory_event.memory_size());
   if (vulkan_memory_event.has_allocation_scope())
     vulkan_memory_event_row.scope =
-        context_->vulkan_memory_tracker->FindAllocationScopeString(
+        vulkan_memory_tracker_.FindAllocationScopeString(
             static_cast<VulkanMemoryEvent::AllocationScope>(
                 vulkan_memory_event.allocation_scope()));
 
@@ -541,8 +579,8 @@
       protos::pbzero::VulkanMemoryEventAnnotation::Decoder annotation(*it);
 
       auto key_id =
-          context_->vulkan_memory_tracker
-              ->GetInternedString<InternedData::kVulkanMemoryKeysFieldNumber>(
+          vulkan_memory_tracker_
+              .GetInternedString<InternedData::kVulkanMemoryKeysFieldNumber>(
                   sequence_state, sequence_state_generation,
                   static_cast<uint64_t>(annotation.key_iid()));
 
@@ -556,8 +594,8 @@
             Variadic::Real(annotation.double_value()));
       } else if (annotation.has_string_iid()) {
         auto string_id =
-            context_->vulkan_memory_tracker
-                ->GetInternedString<InternedData::kVulkanMemoryKeysFieldNumber>(
+            vulkan_memory_tracker_
+                .GetInternedString<InternedData::kVulkanMemoryKeysFieldNumber>(
                     sequence_state, sequence_state_generation,
                     static_cast<uint64_t>(annotation.string_iid()));
 
@@ -602,5 +640,14 @@
   context_->storage->mutable_gpu_slice_table()->Insert(row);
 }
 
+void GraphicsEventParser::ParseVulkanApiEvent(ConstBytes blob) {
+  protos::pbzero::VulkanApiEvent::Decoder vk_event(blob.data, blob.size);
+  if (vk_event.has_vk_debug_utils_object_name()) {
+    protos::pbzero::VulkanApiEvent_VkDebugUtilsObjectName::Decoder event(
+        vk_event.vk_debug_utils_object_name());
+    debug_marker_names_[event.object()] = event.object_name();
+  }
+}
+
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/graphics_event_parser.h b/src/trace_processor/importers/proto/graphics_event_parser.h
index 38a0a8d..a0727de 100644
--- a/src/trace_processor/importers/proto/graphics_event_parser.h
+++ b/src/trace_processor/importers/proto/graphics_event_parser.h
@@ -21,12 +21,21 @@
 
 #include "perfetto/protozero/field.h"
 #include "src/trace_processor/importers/proto/proto_incremental_state.h"
+#include "src/trace_processor/importers/proto/vulkan_memory_tracker.h"
 #include "src/trace_processor/trace_storage.h"
-#include "src/trace_processor/vulkan_memory_tracker.h"
 
 #include "protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h"
 
 namespace perfetto {
+
+namespace protos {
+namespace pbzero {
+
+class GpuRenderStageEvent_Decoder;
+
+}  // namespace pbzero
+}  // namespace protos
+
 namespace trace_processor {
 
 class TraceProcessorContext;
@@ -57,14 +66,22 @@
   void UpdateVulkanMemoryAllocationCounters(UniquePid,
                                             const VulkanMemoryEvent::Decoder&);
 
+  void ParseVulkanApiEvent(ConstBytes);
+
  private:
+  const StringId GetFullStageName(
+      const protos::pbzero::GpuRenderStageEvent_Decoder& event);
+
   TraceProcessorContext* const context_;
+  VulkanMemoryTracker vulkan_memory_tracker_;
   // For GpuCounterEvent
   std::unordered_map<uint32_t, TrackId> gpu_counter_track_ids_;
   // For GpuRenderStageEvent
+  const StringId description_id_;
   const StringId gpu_render_stage_scope_id_;
   std::vector<TrackId> gpu_hw_queue_ids_;
-  std::vector<StringId> gpu_render_stage_ids_;
+  // Map of stage ID -> pair(stage name, stage description)
+  std::vector<std::pair<StringId, StringId>> gpu_render_stage_ids_;
   // For GraphicsFrameEvent
   const StringId graphics_event_scope_id_;
   const StringId unknown_event_name_id_;
@@ -93,6 +110,8 @@
   const StringId tag_id_;
   const StringId log_message_id_;
   std::array<StringId, 7> log_severity_ids_;
+  // For Vulkan events.
+  std::unordered_map<uint64_t, ::protozero::ConstChars> debug_marker_names_;
 };
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/heap_graph_module.cc b/src/trace_processor/importers/proto/heap_graph_module.cc
index f89aafd..3004131 100644
--- a/src/trace_processor/importers/proto/heap_graph_module.cc
+++ b/src/trace_processor/importers/proto/heap_graph_module.cc
@@ -89,11 +89,37 @@
 
 }  // namespace
 
-void HeapGraphModule::ParseHeapGraph(int64_t ts, protozero::ConstBytes blob) {
+using perfetto::protos::pbzero::TracePacket;
+
+HeapGraphModule::HeapGraphModule(TraceProcessorContext* context)
+    : context_(context) {
+  context_->heap_graph_tracker.reset(new HeapGraphTracker(context_));
+  RegisterForField(TracePacket::kHeapGraphFieldNumber, context);
+  RegisterForField(TracePacket::kDeobfuscationMappingFieldNumber, context);
+}
+
+void HeapGraphModule::ParsePacket(
+    const protos::pbzero::TracePacket::Decoder& decoder,
+    const TimestampedTracePiece& ttp,
+    uint32_t field_id) {
+  switch (field_id) {
+    case TracePacket::kHeapGraphFieldNumber:
+      ParseHeapGraph(decoder.trusted_packet_sequence_id(), ttp.timestamp,
+                     decoder.heap_graph());
+      return;
+    case TracePacket::kDeobfuscationMappingFieldNumber:
+      ParseDeobfuscationMapping(decoder.deobfuscation_mapping());
+      return;
+  }
+}
+
+void HeapGraphModule::ParseHeapGraph(uint32_t seq_id,
+                                     int64_t ts,
+                                     protozero::ConstBytes blob) {
   protos::pbzero::HeapGraph::Decoder heap_graph(blob.data, blob.size);
   UniquePid upid = context_->process_tracker->GetOrCreateProcess(
       static_cast<uint32_t>(heap_graph.pid()));
-  context_->heap_graph_tracker->SetPacketIndex(heap_graph.index());
+  context_->heap_graph_tracker->SetPacketIndex(seq_id, heap_graph.index());
   for (auto it = heap_graph.objects(); it; ++it) {
     protos::pbzero::HeapGraphObject::Decoder object(*it);
     HeapGraphTracker::SourceObject obj;
@@ -131,7 +157,7 @@
       ref.owned_object_id = object_ids[i];
       obj.references.emplace_back(std::move(ref));
     }
-    context_->heap_graph_tracker->AddObject(upid, ts, std::move(obj));
+    context_->heap_graph_tracker->AddObject(seq_id, upid, ts, std::move(obj));
   }
   for (auto it = heap_graph.type_names(); it; ++it) {
     protos::pbzero::InternedString::Decoder entry(*it);
@@ -139,7 +165,7 @@
     auto str_view = base::StringView(str, entry.str().size);
 
     context_->heap_graph_tracker->AddInternedTypeName(
-        entry.iid(), context_->storage->InternString(str_view));
+        seq_id, entry.iid(), context_->storage->InternString(str_view));
   }
   for (auto it = heap_graph.field_names(); it; ++it) {
     protos::pbzero::InternedString::Decoder entry(*it);
@@ -147,7 +173,7 @@
     auto str_view = base::StringView(str, entry.str().size);
 
     context_->heap_graph_tracker->AddInternedFieldName(
-        entry.iid(), context_->storage->InternString(str_view));
+        seq_id, entry.iid(), context_->storage->InternString(str_view));
   }
   for (auto it = heap_graph.roots(); it; ++it) {
     protos::pbzero::HeapGraphRoot::Decoder entry(*it);
@@ -166,10 +192,11 @@
           stats::heap_graph_malformed_packet, static_cast<int>(upid));
       break;
     }
-    context_->heap_graph_tracker->AddRoot(upid, ts, std::move(src_root));
+    context_->heap_graph_tracker->AddRoot(seq_id, upid, ts,
+                                          std::move(src_root));
   }
   if (!heap_graph.continued()) {
-    context_->heap_graph_tracker->FinalizeProfile();
+    context_->heap_graph_tracker->FinalizeProfile(seq_id);
   }
 }
 
diff --git a/src/trace_processor/importers/proto/heap_graph_module.h b/src/trace_processor/importers/proto/heap_graph_module.h
index 5d9755e..2fde80e 100644
--- a/src/trace_processor/importers/proto/heap_graph_module.h
+++ b/src/trace_processor/importers/proto/heap_graph_module.h
@@ -27,31 +27,19 @@
 namespace perfetto {
 namespace trace_processor {
 
-class HeapGraphModule : public ProtoImporterModuleBase<PERFETTO_BUILDFLAG(
-                            PERFETTO_TP_HEAP_GRAPHS)> {
+class HeapGraphModule : public ProtoImporterModule {
  public:
-  explicit HeapGraphModule(TraceProcessorContext* context)
-      : ProtoImporterModuleBase(context) {
-    context_->heap_graph_tracker.reset(new HeapGraphTracker(context_));
-  }
+  explicit HeapGraphModule(TraceProcessorContext* context);
 
-  ModuleResult ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
-                           const TimestampedTracePiece& ttp) {
-    if (decoder.has_heap_graph()) {
-      ParseHeapGraph(ttp.timestamp, decoder.heap_graph());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_deobfuscation_mapping()) {
-      ParseDeobfuscationMapping(decoder.deobfuscation_mapping());
-      return ModuleResult::Handled();
-    }
-    return ModuleResult::Ignored();
-  }
+  void ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
+                   const TimestampedTracePiece& ttp,
+                   uint32_t field_id) override;
 
  private:
-  void ParseHeapGraph(int64_t ts, protozero::ConstBytes);
+  void ParseHeapGraph(uint32_t seq_id, int64_t ts, protozero::ConstBytes);
   void ParseDeobfuscationMapping(protozero::ConstBytes);
+
+  TraceProcessorContext* context_;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.cc b/src/trace_processor/importers/proto/heap_graph_tracker.cc
index 3a8ace5..930528d 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker.cc
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.cc
@@ -22,79 +22,110 @@
 HeapGraphTracker::HeapGraphTracker(TraceProcessorContext* context)
     : context_(context) {}
 
-bool HeapGraphTracker::SetPidAndTimestamp(UniquePid upid, int64_t ts) {
-  if (current_upid_ != 0 && current_upid_ != upid) {
+HeapGraphTracker::SequenceState& HeapGraphTracker::GetOrCreateSequence(
+    uint32_t seq_id) {
+  auto seq_it = sequence_state_.find(seq_id);
+  if (seq_it == sequence_state_.end()) {
+    std::tie(seq_it, std::ignore) = sequence_state_.emplace(seq_id, this);
+  }
+  return seq_it->second;
+}
+
+bool HeapGraphTracker::SetPidAndTimestamp(SequenceState* sequence_state,
+                                          UniquePid upid,
+                                          int64_t ts) {
+  if (sequence_state->current_upid != 0 &&
+      sequence_state->current_upid != upid) {
     context_->storage->IncrementStats(stats::heap_graph_non_finalized_graph);
     return false;
   }
-  if (current_ts_ != 0 && current_ts_ != ts) {
+  if (sequence_state->current_ts != 0 && sequence_state->current_ts != ts) {
     context_->storage->IncrementStats(stats::heap_graph_non_finalized_graph);
     return false;
   }
-  current_upid_ = upid;
-  current_ts_ = ts;
+  sequence_state->current_upid = upid;
+  sequence_state->current_ts = ts;
   return true;
 }
 
-void HeapGraphTracker::AddObject(UniquePid upid, int64_t ts, SourceObject obj) {
-  if (!SetPidAndTimestamp(upid, ts))
+void HeapGraphTracker::AddObject(uint32_t seq_id,
+                                 UniquePid upid,
+                                 int64_t ts,
+                                 SourceObject obj) {
+  SequenceState& sequence_state = GetOrCreateSequence(seq_id);
+
+  if (!SetPidAndTimestamp(&sequence_state, upid, ts))
     return;
 
-  current_objects_.emplace_back(std::move(obj));
+  sequence_state.current_objects.emplace_back(std::move(obj));
 }
 
-void HeapGraphTracker::AddRoot(UniquePid upid, int64_t ts, SourceRoot root) {
-  if (!SetPidAndTimestamp(upid, ts))
+void HeapGraphTracker::AddRoot(uint32_t seq_id,
+                               UniquePid upid,
+                               int64_t ts,
+                               SourceRoot root) {
+  SequenceState& sequence_state = GetOrCreateSequence(seq_id);
+  if (!SetPidAndTimestamp(&sequence_state, upid, ts))
     return;
 
-  current_roots_.emplace_back(std::move(root));
+  sequence_state.current_roots.emplace_back(std::move(root));
 }
 
-void HeapGraphTracker::AddInternedTypeName(uint64_t intern_id,
+void HeapGraphTracker::AddInternedTypeName(uint32_t seq_id,
+                                           uint64_t intern_id,
                                            StringPool::Id strid) {
-  interned_type_names_.emplace(intern_id, strid);
+  SequenceState& sequence_state = GetOrCreateSequence(seq_id);
+  sequence_state.interned_type_names.emplace(intern_id, strid);
 }
 
-void HeapGraphTracker::AddInternedFieldName(uint64_t intern_id,
+void HeapGraphTracker::AddInternedFieldName(uint32_t seq_id,
+                                            uint64_t intern_id,
                                             StringPool::Id strid) {
-  interned_field_names_.emplace(intern_id, strid);
+  SequenceState& sequence_state = GetOrCreateSequence(seq_id);
+  sequence_state.interned_field_names.emplace(intern_id, strid);
 }
 
-void HeapGraphTracker::SetPacketIndex(uint64_t index) {
-  if (prev_index_ != 0 && prev_index_ + 1 != index) {
+void HeapGraphTracker::SetPacketIndex(uint32_t seq_id, uint64_t index) {
+  SequenceState& sequence_state = GetOrCreateSequence(seq_id);
+  if (sequence_state.prev_index != 0 &&
+      sequence_state.prev_index + 1 != index) {
     PERFETTO_ELOG("Missing packets between %" PRIu64 " and %" PRIu64,
-                  prev_index_, index);
-    context_->storage->IncrementIndexedStats(stats::heap_graph_missing_packet,
-                                             static_cast<int>(current_upid_));
+                  sequence_state.prev_index, index);
+    context_->storage->IncrementIndexedStats(
+        stats::heap_graph_missing_packet,
+        static_cast<int>(sequence_state.current_upid));
   }
-  prev_index_ = index;
+  sequence_state.prev_index = index;
 }
 
-void HeapGraphTracker::FinalizeProfile() {
-  for (const SourceObject& obj : current_objects_) {
-    auto it = interned_type_names_.find(obj.type_id);
-    if (it == interned_type_names_.end()) {
+void HeapGraphTracker::FinalizeProfile(uint32_t seq_id) {
+  SequenceState& sequence_state = GetOrCreateSequence(seq_id);
+  for (const SourceObject& obj : sequence_state.current_objects) {
+    auto it = sequence_state.interned_type_names.find(obj.type_id);
+    if (it == sequence_state.interned_type_names.end()) {
       context_->storage->IncrementIndexedStats(
-          stats::heap_graph_invalid_string_id, static_cast<int>(current_upid_));
+          stats::heap_graph_invalid_string_id,
+          static_cast<int>(sequence_state.current_upid));
       continue;
     }
     StringPool::Id type_name = it->second;
     context_->storage->mutable_heap_graph_object_table()->Insert(
-        {current_upid_, current_ts_, static_cast<int64_t>(obj.object_id),
+        {sequence_state.current_upid, sequence_state.current_ts,
+         static_cast<int64_t>(obj.object_id),
          static_cast<int64_t>(obj.self_size), /*retained_size=*/-1,
          /*unique_retained_size=*/-1, /*reference_set_id=*/-1,
          /*reachable=*/0, /*type_name=*/type_name,
          /*deobfuscated_type_name=*/base::nullopt,
          /*root_type=*/base::nullopt});
     int64_t row = context_->storage->heap_graph_object_table().size() - 1;
-    object_id_to_row_.emplace(obj.object_id, row);
+    sequence_state.object_id_to_row.emplace(obj.object_id, row);
     class_to_rows_[type_name].emplace_back(row);
-    walker_.AddNode(row, obj.self_size);
+    sequence_state.walker.AddNode(row, obj.self_size);
   }
 
-  for (const SourceObject& obj : current_objects_) {
-    auto it = object_id_to_row_.find(obj.object_id);
-    if (it == object_id_to_row_.end())
+  for (const SourceObject& obj : sequence_state.current_objects) {
+    auto it = sequence_state.object_id_to_row.find(obj.object_id);
+    if (it == sequence_state.object_id_to_row.end())
       continue;
     int64_t owner_row = it->second;
 
@@ -106,23 +137,24 @@
       if (ref.owned_object_id == 0)
         continue;
 
-      it = object_id_to_row_.find(ref.owned_object_id);
+      it = sequence_state.object_id_to_row.find(ref.owned_object_id);
       // This can only happen for an invalid type string id, which is already
       // reported as an error. Silently continue here.
-      if (it == object_id_to_row_.end())
+      if (it == sequence_state.object_id_to_row.end())
         continue;
 
       int64_t owned_row = it->second;
       bool inserted;
       std::tie(std::ignore, inserted) = seen_owned.emplace(owned_row);
       if (inserted)
-        walker_.AddEdge(owner_row, owned_row);
+        sequence_state.walker.AddEdge(owner_row, owned_row);
 
-      auto field_name_it = interned_field_names_.find(ref.field_name_id);
-      if (field_name_it == interned_field_names_.end()) {
+      auto field_name_it =
+          sequence_state.interned_field_names.find(ref.field_name_id);
+      if (field_name_it == sequence_state.interned_field_names.end()) {
         context_->storage->IncrementIndexedStats(
             stats::heap_graph_invalid_string_id,
-            static_cast<int>(current_upid_));
+            static_cast<int>(sequence_state.current_upid));
         continue;
       }
       StringPool::Id field_name = field_name_it->second;
@@ -137,38 +169,24 @@
         ->Set(static_cast<uint32_t>(owner_row), reference_set_id);
   }
 
-  for (const SourceRoot& root : current_roots_) {
+  for (const SourceRoot& root : sequence_state.current_roots) {
     for (uint64_t obj_id : root.object_ids) {
-      auto it = object_id_to_row_.find(obj_id);
+      auto it = sequence_state.object_id_to_row.find(obj_id);
       // This can only happen for an invalid type string id, which is already
       // reported as an error. Silently continue here.
-      if (it == object_id_to_row_.end())
+      if (it == sequence_state.object_id_to_row.end())
         continue;
 
       int64_t obj_row = it->second;
-      walker_.MarkRoot(obj_row);
+      sequence_state.walker.MarkRoot(obj_row);
       context_->storage->mutable_heap_graph_object_table()
           ->mutable_root_type()
           ->Set(static_cast<uint32_t>(obj_row), root.root_type);
     }
   }
 
-  walker_.CalculateRetained();
-
-  // TODO(fmayer): Track these fields per sequence, then delete the
-  // current sequence's data here.
-  current_upid_ = 0;
-  current_ts_ = 0;
-  current_objects_.clear();
-  current_roots_.clear();
-  interned_type_names_.clear();
-  interned_field_names_.clear();
-  object_id_to_row_.clear();
-  prev_index_ = 0;
-  walker_ = HeapGraphWalker(this);
-
-  // class_to_rows_ and field_to_rows_ need to outlive this to handle
-  // DeobfuscationMapping later.
+  sequence_state.walker.CalculateRetained();
+  sequence_state_.erase(seq_id);
 }
 
 void HeapGraphTracker::MarkReachable(int64_t row) {
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.h b/src/trace_processor/importers/proto/heap_graph_tracker.h
index 4bf74f5..86ca98d 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker.h
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.h
@@ -54,12 +54,16 @@
 
   explicit HeapGraphTracker(TraceProcessorContext* context);
 
-  void AddRoot(UniquePid upid, int64_t ts, SourceRoot root);
-  void AddObject(UniquePid upid, int64_t ts, SourceObject obj);
-  void AddInternedTypeName(uint64_t intern_id, StringPool::Id strid);
-  void AddInternedFieldName(uint64_t intern_id, StringPool::Id strid);
-  void FinalizeProfile();
-  void SetPacketIndex(uint64_t index);
+  void AddRoot(uint32_t seq_id, UniquePid upid, int64_t ts, SourceRoot root);
+  void AddObject(uint32_t seq_id, UniquePid upid, int64_t ts, SourceObject obj);
+  void AddInternedTypeName(uint32_t seq_id,
+                           uint64_t intern_id,
+                           StringPool::Id strid);
+  void AddInternedFieldName(uint32_t seq_id,
+                            uint64_t intern_id,
+                            StringPool::Id strid);
+  void FinalizeProfile(uint32_t seq);
+  void SetPacketIndex(uint32_t seq_id, uint64_t index);
 
   ~HeapGraphTracker() override = default;
   // HeapGraphTracker::Delegate
@@ -83,19 +87,25 @@
   }
 
  private:
-  bool SetPidAndTimestamp(UniquePid upid, int64_t ts);
+  struct SequenceState {
+    SequenceState(HeapGraphTracker* tracker) : walker(tracker) {}
+
+    UniquePid current_upid = 0;
+    int64_t current_ts = 0;
+    std::vector<SourceObject> current_objects;
+    std::vector<SourceRoot> current_roots;
+    std::map<uint64_t, StringPool::Id> interned_type_names;
+    std::map<uint64_t, StringPool::Id> interned_field_names;
+    std::map<uint64_t, int64_t> object_id_to_row;
+    uint64_t prev_index = 0;
+    HeapGraphWalker walker;
+  };
+
+  SequenceState& GetOrCreateSequence(uint32_t seq_id);
+  bool SetPidAndTimestamp(SequenceState* seq, UniquePid upid, int64_t ts);
+
   TraceProcessorContext* const context_;
-
-  UniquePid current_upid_ = 0;
-  int64_t current_ts_ = 0;
-  std::vector<SourceObject> current_objects_;
-  std::vector<SourceRoot> current_roots_;
-  std::map<uint64_t, StringPool::Id> interned_type_names_;
-  std::map<uint64_t, StringPool::Id> interned_field_names_;
-  std::map<uint64_t, int64_t> object_id_to_row_;
-  uint64_t prev_index_ = 0;
-
-  HeapGraphWalker walker_{this};
+  std::map<uint32_t, SequenceState> sequence_state_;
 
   std::map<StringPool::Id, std::vector<int64_t>> class_to_rows_;
   std::map<StringPool::Id, std::vector<int64_t>> field_to_rows_;
diff --git a/src/trace_processor/importers/proto/proto_importer_module.cc b/src/trace_processor/importers/proto/proto_importer_module.cc
index 48f41ef..4524384 100644
--- a/src/trace_processor/importers/proto/proto_importer_module.cc
+++ b/src/trace_processor/importers/proto/proto_importer_module.cc
@@ -20,11 +20,11 @@
 namespace perfetto {
 namespace trace_processor {
 
-NewProtoImporterModule::NewProtoImporterModule() {}
+ProtoImporterModule::ProtoImporterModule() {}
 
-NewProtoImporterModule::~NewProtoImporterModule() {}
+ProtoImporterModule::~ProtoImporterModule() {}
 
-ModuleResult NewProtoImporterModule::TokenizePacket(
+ModuleResult ProtoImporterModule::TokenizePacket(
     const protos::pbzero::TracePacket_Decoder&,
     TraceBlobView* /*packet*/,
     int64_t /*packet_timestamp*/,
@@ -33,16 +33,16 @@
   return ModuleResult::Ignored();
 }
 
-void NewProtoImporterModule::ParsePacket(
+void ProtoImporterModule::ParsePacket(
     const protos::pbzero::TracePacket_Decoder&,
     const TimestampedTracePiece&,
     uint32_t /*field_id*/) {}
 
-void NewProtoImporterModule::ParseTraceConfig(
+void ProtoImporterModule::ParseTraceConfig(
     const protos::pbzero::TraceConfig_Decoder&) {}
 
-void NewProtoImporterModule::RegisterForField(uint32_t field_id,
-                                              TraceProcessorContext* context) {
+void ProtoImporterModule::RegisterForField(uint32_t field_id,
+                                           TraceProcessorContext* context) {
   if (context->modules_by_field.size() <= field_id) {
     context->modules_by_field.resize(field_id + 1, nullptr);
   }
diff --git a/src/trace_processor/importers/proto/proto_importer_module.h b/src/trace_processor/importers/proto/proto_importer_module.h
index 8579213..60a0218 100644
--- a/src/trace_processor/importers/proto/proto_importer_module.h
+++ b/src/trace_processor/importers/proto/proto_importer_module.h
@@ -36,23 +36,18 @@
 struct TimestampedTracePiece;
 class TraceProcessorContext;
 
-// This file contains helper and base class templates for
-// ProtoTraceTokenizer/Parser modules. A module implements support for a subset
-// of features of the TracePacket proto format. Modules inherit from
-// ProtoImporterModuleBase, and should be instantiated using the
-// ProtoImporterModule<> wrapper template in trace_processor_context.h.
-//
+// This file contains a base class for ProtoTraceTokenizer/Parser modules.
+// A module implements support for a subset of features of the TracePacket
+// proto format.
 // To add and integrate a new module:
-// (1) Add MyModule as a subclass of ProtoImporterModuleBase<IsEnabled>,
-//     defining the TokenizePacket() and/or ParsePacket() methods.
-//     Typically, a build-time macro will inform the value of IsEnabled.
-//     See ftrace_module.h for an example.
-// (2) Add a member of type std::unique_ptr<ProtoImporterModule<MyModule>> to
-//     TraceProcessorContext (trace_processor_context.h) and init it from
-//     TraceProcessorImpl() and appropriate tests.
-// (3) Add an include of my_module.h and calls to your module's TokenizePacket /
-//     ParsePacket methods in ProtoTraceTokenizer and/or ProtoTraceParser
-//     (proxying via the wrapper).
+// (1) Add MyModule as a subclass of ProtoImporterModule,
+//     overriding the TokenizePacket(), ParsePacket() and/or ParseTraceConfig()
+//     methods.
+// (2) In the constructor call the RegisterForField method for every field
+//     that the module knows how to handle.
+// (3) Create a module instance and add it to the |modules| vector in
+//     TraceProcessorContext.
+// See GraphicsEventModule for an example.
 
 class ModuleResult {
  public:
@@ -96,119 +91,12 @@
   base::Optional<std::string> error_;
 };
 
-// Wrapper class for a module. This wrapper allows modules to be disabled
-// disabled at compile time to remove support for its features from the trace
-// processor.
-//
-// The trace processor will instantiate enabled modules for each
-// TraceProcessorContext. The tokenizer and parser notify individual modules
-// about trace data by calling their respective methods via the wrapper class.
-// If the module is enabled, the wrapper will forward the call to the module
-// implementation. This way, we avoid virtual methods, so that calling any of
-// the module's methods is zero overhead - they can be inlined by the compiler
-// at callsites directly.
-template <class ModuleType>
+// Base class for modules.
 class ProtoImporterModule {
  public:
-  ProtoImporterModule(TraceProcessorContext* context) {
-    if (ModuleType::kEnabled)
-      impl_.reset(new ModuleType(context));
-  }
+  ProtoImporterModule();
 
-  // ModuleType may specify methods with the signatures below.
-  // ProtoImporterModule<ModuleType> acts as a wrapper for these methods.
-  // ModuleType only needs to specify the methods that
-  // ProtoTraceParser/Tokenizer actually calls on the respective module.
-
-  // Wraps ModuleType::TokenizePacket(). If the module is disabled, compiles
-  // into a noop in optimized builds. Called by ProtoTraceTokenizer for each
-  // TracePacket during the tokenization stage, i.e. before sorting. If this
-  // returns a result other than ModuleResult::Ignored(), tokenization of the
-  // packet will be aborted after the module.
-  ModuleResult TokenizePacket(
-      const protos::pbzero::TracePacket_Decoder& decoder,
-      TraceBlobView* packet,
-      int64_t packet_timestamp,
-      PacketSequenceState* state) {
-    if (ModuleType::kEnabled) {
-      return impl_->TokenizePacket(decoder, packet, packet_timestamp, state);
-    }
-    return ModuleResult::Ignored();
-  }
-
-  // Wraps ModuleType::ParsePacket(). If the module is disabled, compiles into a
-  // noop in optimized builds. Called by ProtoTraceParser for each non-ftrace
-  // TracePacket after the sorting stage. If this returns a result other than
-  // ModuleResult::Ignored(), parsing of the packet will be aborted after the
-  // module.
-  ModuleResult ParsePacket(const protos::pbzero::TracePacket_Decoder& decoder,
-                           const TimestampedTracePiece& ttp) {
-    if (ModuleType::kEnabled)
-      return impl_->ParsePacket(decoder, ttp);
-    return ModuleResult::Ignored();
-  }
-
-  // Wraps ModuleType::ParseTraceConfig(). If the module is disabled, compiles
-  // into a noop in optimized builds. Called by ProtoTraceParser for trace
-  // config packets after the sorting stage.
-  ModuleResult ParseTraceConfig(
-      const protos::pbzero::TraceConfig_Decoder& decoder) {
-    if (ModuleType::kEnabled)
-      return impl_->ParseTraceConfig(decoder);
-    return ModuleResult::Ignored();
-  }
-
-  // For FtraceModule only. Wraps ModuleType::ParseFtracePacket(). If the module
-  // is disabled, compiles into a noop in optimized builds. Called by
-  // ProtoTraceParser for each ftrace TracePacket after the sorting stage.
-  // Ftrace packets are handled specially here because they are sorted in
-  // separate queues per CPU. If this returns a result other than
-  // ModuleResult::Ignored(), parsing of the packet will be aborted after the
-  // module.
-  ModuleResult ParseFtracePacket(uint32_t cpu,
-                                 const TimestampedTracePiece& ttp) {
-    if (ModuleType::kEnabled)
-      return impl_->ParseFtracePacket(cpu, ttp);
-    return ModuleResult::Ignored();
-  }
-
- private:
-  // Only initialized if the module is enabled.
-  std::unique_ptr<ModuleType> impl_;
-};
-
-// Base class for a proto trace module that can be disabled at compile time.
-// Typically, a build-time macro will inform the value of IsEnabled.
-template <int IsEnabled>
-class ProtoImporterModuleBase {
- public:
-  static constexpr bool kEnabled = static_cast<bool>(IsEnabled);
-
-  explicit ProtoImporterModuleBase(TraceProcessorContext* context)
-      : context_(context) {}
-  ~ProtoImporterModuleBase() {}
-
-  // See ProtoTraceModule<> for the public methods subclasses may implement.
-
- protected:
-  TraceProcessorContext* context_;
-};
-
-// This is a new module superclass that allows registering modules at runtime.
-// To add and integrate a new module:
-// (1) Add MyModule as a subclass of NewProtoImporterModule,
-//     overriding the TokenizePacket(), ParsePacket() and/or ParseTraceConfig()
-//     methods.
-// (2) In the constructor call the RegisterForField method for every field
-//     that the module knows how to handle.
-// See GraphicsEventModule for an example.
-// TODO(b/141459049): Rename this to ProtoImporterModule after all modules
-// are based on it.
-class NewProtoImporterModule {
- public:
-  NewProtoImporterModule();
-
-  virtual ~NewProtoImporterModule();
+  virtual ~ProtoImporterModule();
 
   // Called by ProtoTraceTokenizer during the tokenization stage, i.e. before
   // sorting. It's called for each TracePacket that contains fields for which
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index b4bbaf9..7dce80c 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -30,14 +30,11 @@
 #include "perfetto/ext/base/uuid.h"
 #include "perfetto/trace_processor/status.h"
 #include "src/trace_processor/args_tracker.h"
+#include "src/trace_processor/clock_tracker.h"
 #include "src/trace_processor/event_tracker.h"
 #include "src/trace_processor/heap_profile_tracker.h"
 #include "src/trace_processor/importers/ftrace/ftrace_module.h"
-#include "src/trace_processor/importers/proto/android_probes_module.h"
-#include "src/trace_processor/importers/proto/heap_graph_module.h"
 #include "src/trace_processor/importers/proto/packet_sequence_state.h"
-#include "src/trace_processor/importers/proto/system_probes_module.h"
-#include "src/trace_processor/importers/proto/track_event_module.h"
 #include "src/trace_processor/metadata.h"
 #include "src/trace_processor/process_tracker.h"
 #include "src/trace_processor/slice_tracker.h"
@@ -203,21 +200,6 @@
     TimestampedTracePiece ttp,
     const protos::pbzero::TracePacket::Decoder& packet) {
   // TODO(eseckler): Propagate statuses from modules.
-  if (!context_->ftrace_module->ParsePacket(packet, ttp).ignored())
-    return;
-
-  if (!context_->track_event_module->ParsePacket(packet, ttp).ignored())
-    return;
-
-  if (!context_->system_probes_module->ParsePacket(packet, ttp).ignored())
-    return;
-
-  if (!context_->android_probes_module->ParsePacket(packet, ttp).ignored())
-    return;
-
-  if (!context_->heap_graph_module->ParsePacket(packet, ttp).ignored())
-    return;
-
   auto& modules = context_->modules_by_field;
   for (uint32_t field_id = 1; field_id < modules.size(); ++field_id) {
     if (modules[field_id] && packet.Get(field_id).valid()) {
@@ -230,9 +212,9 @@
     ParseTraceStats(packet.trace_stats());
 
   if (packet.has_profile_packet()) {
-    ParseProfilePacket(ts, ttp.packet_sequence_state,
-                       ttp.packet_sequence_state_generation,
-                       packet.profile_packet());
+    ParseProfilePacket(
+        ts, ttp.packet_sequence_state, ttp.packet_sequence_state_generation,
+        packet.trusted_packet_sequence_id(), packet.profile_packet());
   }
 
   if (packet.has_streaming_profile_packet()) {
@@ -266,13 +248,8 @@
                                          int64_t /*ts*/,
                                          TimestampedTracePiece ttp) {
   PERFETTO_DCHECK(ttp.json_value == nullptr);
-
-  ModuleResult res = context_->ftrace_module->ParseFtracePacket(cpu, ttp);
-  PERFETTO_DCHECK(!res.ignored());
-  // TODO(eseckler): Propagate status.
-  if (!res.ok()) {
-    PERFETTO_ELOG("%s", res.message().c_str());
-  }
+  PERFETTO_DCHECK(context_->ftrace_module);
+  context_->ftrace_module->ParseFtracePacket(cpu, ttp);
 
   // TODO(lalitm): maybe move this to the flush method in the trace processor
   // once we have it. This may reduce performance in the ArgsTracker though so
@@ -345,9 +322,10 @@
 void ProtoTraceParser::ParseProfilePacket(int64_t,
                                           PacketSequenceState* sequence_state,
                                           size_t sequence_state_generation,
+                                          uint32_t seq_id,
                                           ConstBytes blob) {
   protos::pbzero::ProfilePacket::Decoder packet(blob.data, blob.size);
-  context_->heap_profile_tracker->SetProfilePacketIndex(packet.index());
+  context_->heap_profile_tracker->SetProfilePacketIndex(seq_id, packet.index());
 
   for (auto it = packet.strings(); it; ++it) {
     protos::pbzero::InternedString::Decoder entry(*it);
@@ -381,6 +359,17 @@
   for (auto it = packet.process_dumps(); it; ++it) {
     protos::pbzero::ProfilePacket::ProcessHeapSamples::Decoder entry(*it);
 
+    auto maybe_timestamp = context_->clock_tracker->ToTraceTime(
+        protos::pbzero::ClockSnapshot::Clock::MONOTONIC_COARSE,
+        static_cast<int64_t>(entry.timestamp()));
+
+    if (!maybe_timestamp) {
+      context_->storage->IncrementStats(stats::clock_sync_failure);
+      continue;
+    }
+
+    int64_t timestamp = *maybe_timestamp;
+
     int pid = static_cast<int>(entry.pid());
 
     if (entry.buffer_corrupted())
@@ -398,14 +387,14 @@
 
       HeapProfileTracker::SourceAllocation src_allocation;
       src_allocation.pid = entry.pid();
-      src_allocation.timestamp = static_cast<int64_t>(entry.timestamp());
+      src_allocation.timestamp = timestamp;
       src_allocation.callstack_id = sample.callstack_id();
       src_allocation.self_allocated = sample.self_allocated();
       src_allocation.self_freed = sample.self_freed();
       src_allocation.alloc_count = sample.alloc_count();
       src_allocation.free_count = sample.free_count();
 
-      context_->heap_profile_tracker->StoreAllocation(src_allocation);
+      context_->heap_profile_tracker->StoreAllocation(seq_id, src_allocation);
     }
   }
   if (!packet.continued()) {
@@ -413,7 +402,7 @@
     ProfilePacketInternLookup intern_lookup(sequence_state,
                                             sequence_state_generation);
     context_->heap_profile_tracker->FinalizeProfile(
-        &sequence_state->stack_profile_tracker(), &intern_lookup);
+        seq_id, &sequence_state->stack_profile_tracker(), &intern_lookup);
   }
 }
 
@@ -605,8 +594,6 @@
   protos::pbzero::TraceConfig::Decoder trace_config(blob.data, blob.size);
 
   // TODO(eseckler): Propagate statuses from modules.
-  context_->android_probes_module->ParseTraceConfig(trace_config);
-
   for (auto& module : context_->modules) {
     module->ParseTraceConfig(trace_config);
   }
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.h b/src/trace_processor/importers/proto/proto_trace_parser.h
index bae7341..4827ebf 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.h
+++ b/src/trace_processor/importers/proto/proto_trace_parser.h
@@ -64,6 +64,7 @@
   void ParseProfilePacket(int64_t ts,
                           PacketSequenceState*,
                           size_t sequence_state_generation,
+                          uint32_t seq_id,
                           ConstBytes);
   void ParseStreamingProfilePacket(PacketSequenceState*,
                                    size_t sequence_state_generation,
diff --git a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
index d19edae..23a1f68 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
@@ -25,7 +25,6 @@
 #include "src/trace_processor/importers/ftrace/ftrace_module.h"
 #include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
 #include "src/trace_processor/importers/proto/android_probes_module.h"
-#include "src/trace_processor/importers/proto/graphics_event_module.h"
 #include "src/trace_processor/importers/proto/heap_graph_module.h"
 #include "src/trace_processor/importers/proto/proto_importer_module.h"
 #include "src/trace_processor/importers/proto/proto_trace_parser.h"
@@ -34,12 +33,12 @@
 #include "src/trace_processor/importers/systrace/systrace_parser.h"
 #include "src/trace_processor/metadata.h"
 #include "src/trace_processor/process_tracker.h"
+#include "src/trace_processor/register_additional_modules.h"
 #include "src/trace_processor/slice_tracker.h"
 #include "src/trace_processor/stack_profile_tracker.h"
 #include "src/trace_processor/trace_sorter.h"
 #include "src/trace_processor/trace_storage.h"
 #include "src/trace_processor/track_tracker.h"
-#include "src/trace_processor/vulkan_memory_tracker.h"
 #include "test/gtest_and_gmock.h"
 
 #include "protos/perfetto/common/sys_stats_counters.pbzero.h"
@@ -257,24 +256,25 @@
     context_.parser.reset(new ProtoTraceParser(&context_));
 #if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
     context_.systrace_parser.reset(new SystraceParser(&context_));
+    context_.modules.emplace_back(new FtraceModuleImpl(&context_));
+#else
+    context_.modules.emplace_back(new FtraceModule());
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
-    context_.vulkan_memory_tracker.reset(new VulkanMemoryTracker(&context_));
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
-    context_.ftrace_module.reset(
-        new ProtoImporterModule<FtraceModule>(&context_));
-    context_.track_event_module.reset(
-        new ProtoImporterModule<TrackEventModule>(&context_));
-    context_.system_probes_module.reset(
-        new ProtoImporterModule<SystemProbesModule>(&context_));
-    context_.android_probes_module.reset(
-        new ProtoImporterModule<AndroidProbesModule>(&context_));
-    context_.heap_graph_module.reset(
-        new ProtoImporterModule<HeapGraphModule>(&context_));
+    context_.ftrace_module =
+        static_cast<FtraceModule*>(context_.modules.back().get());
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
-    context_.modules.emplace_back(new GraphicsEventModule(&context_));
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
+#if PERFETTO_BUILDFLAG(PERFETTO_TP_HEAP_GRAPHS)
+    context_.modules.emplace_back(new HeapGraphModule(&context_));
+#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_HEAP_GRAPHS)
+#if PERFETTO_BUILDFLAG(PERFETTO_TP_ANDROID_PROBES)
+    context_.modules.emplace_back(new AndroidProbesModule(&context_));
+#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_ANDROID_PROBES)
+#if PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
+    context_.modules.emplace_back(new SystemProbesModule(&context_));
+#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
+    context_.modules.emplace_back(new TrackEventModule(&context_));
+
+    RegisterAdditionalModules(&context_);
   }
 
   void ResetTraceBuffers() {
diff --git a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
index b75ccf4..97d7689 100644
--- a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
+++ b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
@@ -32,7 +32,6 @@
 #include "src/trace_processor/importers/ftrace/ftrace_module.h"
 #include "src/trace_processor/importers/proto/packet_sequence_state.h"
 #include "src/trace_processor/importers/proto/proto_incremental_state.h"
-#include "src/trace_processor/importers/proto/track_event_module.h"
 #include "src/trace_processor/stats.h"
 #include "src/trace_processor/trace_sorter.h"
 #include "src/trace_processor/trace_storage.h"
@@ -283,22 +282,11 @@
     ParseInternedData(decoder, packet.slice(offset, field.size));
   }
 
-  ModuleResult res = ModuleResult::Ignored();
-  res = context_->ftrace_module->TokenizePacket(decoder, &packet, timestamp,
-                                                state);
-  if (!res.ignored())
-    return res.ToStatus();
-
-  res = context_->track_event_module->TokenizePacket(decoder, &packet,
-                                                     timestamp, state);
-  if (!res.ignored())
-    return res.ToStatus();
-
   auto& modules = context_->modules_by_field;
   for (uint32_t field_id = 1; field_id < modules.size(); ++field_id) {
     if (modules[field_id] && decoder.Get(field_id).valid()) {
-      modules[field_id]->TokenizePacket(decoder, &packet, timestamp, state,
-                                        field_id);
+      ModuleResult res = modules[field_id]->TokenizePacket(
+          decoder, &packet, timestamp, state, field_id);
       if (!res.ignored())
         return res.ToStatus();
     }
diff --git a/src/trace_processor/importers/proto/system_probes_module.cc b/src/trace_processor/importers/proto/system_probes_module.cc
new file mode 100644
index 0000000..7d5f254
--- /dev/null
+++ b/src/trace_processor/importers/proto/system_probes_module.cc
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 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
+ *
+ *      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.
+ */
+
+#include "src/trace_processor/importers/proto/system_probes_module.h"
+#include "perfetto/base/build_config.h"
+#include "src/trace_processor/importers/proto/system_probes_parser.h"
+#include "src/trace_processor/timestamped_trace_piece.h"
+
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+using perfetto::protos::pbzero::TracePacket;
+
+SystemProbesModule::SystemProbesModule(TraceProcessorContext* context)
+    : parser_(context) {
+  RegisterForField(TracePacket::kProcessTreeFieldNumber, context);
+  RegisterForField(TracePacket::kProcessStatsFieldNumber, context);
+  RegisterForField(TracePacket::kSysStatsFieldNumber, context);
+  RegisterForField(TracePacket::kSystemInfoFieldNumber, context);
+}
+
+void SystemProbesModule::ParsePacket(const TracePacket::Decoder& decoder,
+                                     const TimestampedTracePiece& ttp,
+                                     uint32_t field_id) {
+  switch (field_id) {
+    case TracePacket::kProcessTreeFieldNumber:
+      parser_.ParseProcessTree(decoder.process_tree());
+      return;
+    case TracePacket::kProcessStatsFieldNumber:
+      parser_.ParseProcessStats(ttp.timestamp, decoder.process_stats());
+      return;
+    case TracePacket::kSysStatsFieldNumber:
+      parser_.ParseSysStats(ttp.timestamp, decoder.sys_stats());
+      return;
+    case TracePacket::kSystemInfoFieldNumber:
+      parser_.ParseSystemInfo(decoder.system_info());
+      return;
+  }
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/system_probes_module.h b/src/trace_processor/importers/proto/system_probes_module.h
index 53db890..438eabe 100644
--- a/src/trace_processor/importers/proto/system_probes_module.h
+++ b/src/trace_processor/importers/proto/system_probes_module.h
@@ -20,43 +20,19 @@
 #include "perfetto/base/build_config.h"
 #include "src/trace_processor/importers/proto/proto_importer_module.h"
 #include "src/trace_processor/importers/proto/system_probes_parser.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
 
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 namespace trace_processor {
 
-class SystemProbesModule : public ProtoImporterModuleBase<PERFETTO_BUILDFLAG(
-                               PERFETTO_TP_SYSTEM_PROBES)> {
+class SystemProbesModule : public ProtoImporterModule {
  public:
-  explicit SystemProbesModule(TraceProcessorContext* context)
-      : ProtoImporterModuleBase(context), parser_(context) {}
+  explicit SystemProbesModule(TraceProcessorContext* context);
 
-  ModuleResult ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
-                           const TimestampedTracePiece& ttp) {
-    if (decoder.has_process_tree()) {
-      parser_.ParseProcessTree(decoder.process_tree());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_process_stats()) {
-      parser_.ParseProcessStats(ttp.timestamp, decoder.process_stats());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_sys_stats()) {
-      parser_.ParseSysStats(ttp.timestamp, decoder.sys_stats());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_system_info()) {
-      parser_.ParseSystemInfo(decoder.system_info());
-      return ModuleResult::Handled();
-    }
-
-    return ModuleResult::Ignored();
-  }
+  void ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
+                   const TimestampedTracePiece& ttp,
+                   uint32_t field_id) override;
 
  private:
   SystemProbesParser parser_;
diff --git a/src/trace_processor/importers/proto/track_event.descriptor.h b/src/trace_processor/importers/proto/track_event.descriptor.h
new file mode 100644
index 0000000..bcd2810
--- /dev/null
+++ b/src/trace_processor/importers/proto/track_event.descriptor.h
@@ -0,0 +1,1387 @@
+/*
+ * Copyright (C) 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
+ *
+ *      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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_DESCRIPTOR_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_DESCRIPTOR_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <array>
+
+// This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
+
+// SHA1(tools/gen_binary_descriptors)
+// f242f1ac484bbe7ba4c45e77b56ab588f8015196
+// SHA1(protos/perfetto/trace/track_event/track_event.proto)
+// 512ce808546cf8e65e77de8ccf4f3fe74419dde4
+
+// This is the proto TrackEvent encoded as a ProtoFileDescriptor to allow
+// for reflection without libprotobuf full/non-lite protos.
+
+namespace perfetto {
+
+constexpr std::array<uint8_t, 16147> kTrackEventDescriptor{
+    {0x0a, 0x9a, 0x08, 0x0a, 0x38, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61,
+     0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65,
+     0x6e, 0x74, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x61, 0x6e, 0x6e,
+     0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x8b, 0x07, 0x0a, 0x0f, 0x44,
+     0x65, 0x62, 0x75, 0x67, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69,
+     0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x69,
+     0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x07,
+     0x6e, 0x61, 0x6d, 0x65, 0x49, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x04, 0x6e,
+     0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0a, 0x62, 0x6f, 0x6f,
+     0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+     0x08, 0x48, 0x01, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c,
+     0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x5f, 0x76,
+     0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x48, 0x01,
+     0x52, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
+     0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
+     0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x48, 0x01, 0x52, 0x08, 0x69, 0x6e,
+     0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x64, 0x6f,
+     0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05,
+     0x20, 0x01, 0x28, 0x01, 0x48, 0x01, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62,
+     0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73,
+     0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+     0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0b, 0x73, 0x74, 0x72,
+     0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x25, 0x0a, 0x0d,
+     0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75,
+     0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x48, 0x01, 0x52, 0x0c, 0x70,
+     0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
+     0x51, 0x0a, 0x0c, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x76, 0x61,
+     0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x41, 0x6e, 0x6e,
+     0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4e, 0x65, 0x73, 0x74,
+     0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x01, 0x52, 0x0b, 0x6e,
+     0x65, 0x73, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c,
+     0x0a, 0x11, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x6a, 0x73, 0x6f,
+     0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28,
+     0x09, 0x48, 0x01, 0x52, 0x0f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4a,
+     0x73, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0xda, 0x03, 0x0a,
+     0x0b, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65,
+     0x12, 0x58, 0x0a, 0x0b, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x74,
+     0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x37, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x41, 0x6e, 0x6e,
+     0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4e, 0x65, 0x73, 0x74,
+     0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x4e, 0x65, 0x73, 0x74,
+     0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x6e, 0x65, 0x73, 0x74,
+     0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x69,
+     0x63, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
+     0x09, 0x52, 0x08, 0x64, 0x69, 0x63, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x12,
+     0x4d, 0x0a, 0x0b, 0x64, 0x69, 0x63, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75,
+     0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x41, 0x6e, 0x6e, 0x6f,
+     0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65,
+     0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x64, 0x69, 0x63, 0x74,
+     0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x4f, 0x0a, 0x0c, 0x61, 0x72,
+     0x72, 0x61, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04,
+     0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x44,
+     0x65, 0x62, 0x75, 0x67, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69,
+     0x6f, 0x6e, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c,
+     0x75, 0x65, 0x52, 0x0b, 0x61, 0x72, 0x72, 0x61, 0x79, 0x56, 0x61, 0x6c,
+     0x75, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76,
+     0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08,
+     0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c,
+     0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
+     0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62,
+     0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62,
+     0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20,
+     0x01, 0x28, 0x08, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c,
+     0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+     0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09,
+     0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75,
+     0x65, 0x22, 0x32, 0x0a, 0x0a, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54,
+     0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45,
+     0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04,
+     0x44, 0x49, 0x43, 0x54, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x52,
+     0x52, 0x41, 0x59, 0x10, 0x02, 0x42, 0x0c, 0x0a, 0x0a, 0x6e, 0x61, 0x6d,
+     0x65, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x76,
+     0x61, 0x6c, 0x75, 0x65, 0x22, 0x3b, 0x0a, 0x13, 0x44, 0x65, 0x62, 0x75,
+     0x67, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e,
+     0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x69, 0x64, 0x18, 0x01,
+     0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x69, 0x69, 0x64, 0x12, 0x12, 0x0a,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xdb, 0x01,
+     0x0a, 0x33, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f,
+     0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f,
+     0x6c, 0x6f, 0x67, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x57,
+     0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+     0x12, 0x2e, 0x0a, 0x13, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c,
+     0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x69, 0x64, 0x18,
+     0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63,
+     0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x69, 0x64,
+     0x12, 0x19, 0x0a, 0x08, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x69, 0x69, 0x64,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x62, 0x6f, 0x64, 0x79,
+     0x49, 0x69, 0x64, 0x22, 0x36, 0x0a, 0x0e, 0x4c, 0x6f, 0x67, 0x4d, 0x65,
+     0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a,
+     0x03, 0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03,
+     0x69, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18,
+     0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x42,
+     0x02, 0x48, 0x03, 0x0a, 0x86, 0x01, 0x0a, 0x36, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
+     0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
+     0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65,
+     0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x37, 0x0a, 0x0d, 0x54,
+     0x61, 0x73, 0x6b, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+     0x12, 0x26, 0x0a, 0x0f, 0x70, 0x6f, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x66,
+     0x72, 0x6f, 0x6d, 0x5f, 0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x04, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x74, 0x65, 0x64, 0x46, 0x72, 0x6f,
+     0x6d, 0x49, 0x69, 0x64, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xd6, 0x01, 0x0a,
+     0x37, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74,
+     0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x73,
+     0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
+     0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x22, 0x85, 0x01, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
+     0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03,
+     0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x69,
+     0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6e,
+     0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66,
+     0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x66,
+     0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+     0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x75, 0x6e, 0x63,
+     0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b,
+     0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18,
+     0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x69, 0x6e, 0x65, 0x4e,
+     0x75, 0x6d, 0x62, 0x65, 0x72, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xb9, 0x4d,
+     0x0a, 0x49, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f,
+     0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f,
+     0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f,
+     0x73, 0x69, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75,
+     0x6c, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x37, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63,
+     0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x73, 0x6f, 0x75, 0x72,
+     0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe6, 0x0b, 0x0a, 0x1e, 0x43, 0x68,
+     0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74,
+     0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x53,
+     0x74, 0x61, 0x74, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x74,
+     0x65, 0x5f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68,
+     0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74,
+     0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69,
+     0x6e, 0x65, 0x52, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63,
+     0x68, 0x69, 0x6e, 0x65, 0x12, 0x3f, 0x0a, 0x1c, 0x6f, 0x62, 0x73, 0x65,
+     0x72, 0x76, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
+     0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x6f, 0x62, 0x73, 0x65,
+     0x72, 0x76, 0x69, 0x6e, 0x67, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72,
+     0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x42, 0x0a,
+     0x1e, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f,
+     0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69,
+     0x6e, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x1a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e,
+     0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x37, 0x0a, 0x18, 0x70, 0x65, 0x6e,
+     0x64, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66,
+     0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x18, 0x04, 0x20,
+     0x01, 0x28, 0x08, 0x52, 0x15, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
+     0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x61,
+     0x73, 0x6b, 0x12, 0x5b, 0x0a, 0x2b, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65,
+     0x64, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+     0x5f, 0x6d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x63, 0x65,
+     0x65, 0x64, 0x65, 0x64, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e,
+     0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x26, 0x73, 0x6b, 0x69,
+     0x70, 0x70, 0x65, 0x64, 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x4d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x45, 0x78, 0x63, 0x65, 0x65,
+     0x64, 0x65, 0x64, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12,
+     0x4d, 0x0a, 0x24, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6c,
+     0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f,
+     0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65,
+     0x6e, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x73,
+     0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72,
+     0x61, 0x6d, 0x65, 0x54, 0x6f, 0x52, 0x65, 0x64, 0x75, 0x63, 0x65, 0x4c,
+     0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x55, 0x0a, 0x0d, 0x69, 0x6e,
+     0x73, 0x69, 0x64, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+     0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73,
+     0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
+     0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x69, 0x6e, 0x73,
+     0x69, 0x64, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6f, 0x0a,
+     0x0d, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6d, 0x6f,
+     0x64, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4a, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d,
+     0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64,
+     0x75, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x65,
+     0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65,
+     0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65,
+     0x52, 0x0c, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f,
+     0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69,
+     0x6e, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x0a, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x12,
+     0x37, 0x0a, 0x18, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f,
+     0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x74,
+     0x5f, 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x64,
+     0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x63, 0x68, 0x65, 0x64,
+     0x75, 0x6c, 0x65, 0x64, 0x41, 0x74, 0x55, 0x73, 0x12, 0x15, 0x0a, 0x06,
+     0x6e, 0x6f, 0x77, 0x5f, 0x75, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x05, 0x6e, 0x6f, 0x77, 0x55, 0x73, 0x12, 0x36, 0x0a, 0x18, 0x6e,
+     0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69,
+     0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18,
+     0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x6e, 0x6f, 0x77, 0x54, 0x6f,
+     0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c, 0x74,
+     0x61, 0x55, 0x73, 0x12, 0x4e, 0x0a, 0x25, 0x6e, 0x6f, 0x77, 0x5f, 0x74,
+     0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x73,
+     0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f,
+     0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x0d, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x1f, 0x6e, 0x6f, 0x77, 0x54, 0x6f, 0x44, 0x65, 0x61,
+     0x64, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c,
+     0x65, 0x64, 0x41, 0x74, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12,
+     0x56, 0x0a, 0x15, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70,
+     0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73,
+     0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72,
+     0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x52, 0x12, 0x62, 0x65, 0x67,
+     0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41,
+     0x72, 0x67, 0x73, 0x12, 0x65, 0x0a, 0x1a, 0x62, 0x65, 0x67, 0x69, 0x6e,
+     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72,
+     0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x0f, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65,
+     0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73, 0x65,
+     0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x17, 0x62,
+     0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73,
+     0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x5f,
+     0x0a, 0x18, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d,
+     0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61,
+     0x74, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65,
+     0x52, 0x15, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
+     0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
+     0x64, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
+     0x72, 0x5f, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x69, 0x73,
+     0x74, 0x6f, 0x72, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28,
+     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
+     0x74, 0x6f, 0x72, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73,
+     0x74, 0x6f, 0x72, 0x79, 0x52, 0x17, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73,
+     0x69, 0x74, 0x6f, 0x72, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x48, 0x69,
+     0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, 0xbe, 0x01, 0x0a, 0x1a, 0x42, 0x65,
+     0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65,
+     0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65,
+     0x12, 0x1d, 0x0a, 0x19, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45,
+     0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
+     0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x44,
+     0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45,
+     0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44,
+     0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45,
+     0x5f, 0x49, 0x4d, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x54, 0x45, 0x10, 0x02,
+     0x12, 0x19, 0x0a, 0x15, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45,
+     0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x52, 0x45, 0x47, 0x55, 0x4c, 0x41,
+     0x52, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x41, 0x44, 0x4c,
+     0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4c, 0x41, 0x54,
+     0x45, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x45, 0x41, 0x44, 0x4c,
+     0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x42, 0x4c, 0x4f,
+     0x43, 0x4b, 0x45, 0x44, 0x10, 0x05, 0x22, 0x86, 0x28, 0x0a, 0x1c, 0x43,
+     0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
+     0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68,
+     0x69, 0x6e, 0x65, 0x12, 0x59, 0x0a, 0x0b, 0x6d, 0x61, 0x6a, 0x6f, 0x72,
+     0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
+     0x32, 0x38, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d,
+     0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53,
+     0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e,
+     0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a,
+     0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x59,
+     0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74,
+     0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70,
+     0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d,
+     0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x69, 0x6e, 0x6f, 0x72,
+     0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x6f, 0x72,
+     0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0xf9, 0x0a, 0x0a, 0x0a, 0x4d, 0x61,
+     0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x51, 0x0a, 0x0b,
+     0x6e, 0x65, 0x78, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+     0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73,
+     0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
+     0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6e, 0x65, 0x78,
+     0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x81, 0x01, 0x0a, 0x16,
+     0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66,
+     0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02,
+     0x20, 0x01, 0x28, 0x0e, 0x32, 0x4c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43,
+     0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
+     0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68,
+     0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61,
+     0x74, 0x65, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x13,
+     0x62, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61,
+     0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x16,
+     0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66,
+     0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03,
+     0x20, 0x01, 0x28, 0x0e, 0x32, 0x4c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43,
+     0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
+     0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68,
+     0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61,
+     0x74, 0x65, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x13,
+     0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61,
+     0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x8e, 0x01, 0x0a, 0x1b,
+     0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66,
+     0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x5f, 0x73, 0x74,
+     0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x50, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f,
+     0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74,
+     0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a,
+     0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x61, 0x79, 0x65,
+     0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69,
+     0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x17, 0x6c, 0x61, 0x79,
+     0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53,
+     0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x83, 0x01, 0x0a,
+     0x13, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x64, 0x72,
+     0x61, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01,
+     0x28, 0x0e, 0x32, 0x53, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72,
+     0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
+     0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
+     0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65,
+     0x2e, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x52, 0x65, 0x64, 0x72, 0x61,
+     0x77, 0x4f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x74,
+     0x61, 0x74, 0x65, 0x52, 0x11, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x52,
+     0x65, 0x64, 0x72, 0x61, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0xa1,
+     0x01, 0x0a, 0x13, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20,
+     0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c,
+     0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
+     0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15,
+     0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46,
+     0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12,
+     0x27, 0x0a, 0x23, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50,
+     0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x4e, 0x53, 0x49,
+     0x44, 0x45, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41,
+     0x4d, 0x45, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x42, 0x45, 0x47, 0x49,
+     0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+     0x5f, 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x44, 0x45, 0x41, 0x44,
+     0x4c, 0x49, 0x4e, 0x45, 0x10, 0x03, 0x22, 0x93, 0x01, 0x0a, 0x13, 0x42,
+     0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45,
+     0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41,
+     0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
+     0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x42, 0x45, 0x47, 0x49,
+     0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+     0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x42,
+     0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52,
+     0x41, 0x4d, 0x45, 0x5f, 0x53, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x24,
+     0x0a, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e,
+     0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59,
+     0x5f, 0x54, 0x4f, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x03,
+     0x22, 0xf4, 0x01, 0x0a, 0x17, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72,
+     0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x53,
+     0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x4c, 0x41, 0x59, 0x45,
+     0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+     0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
+     0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f,
+     0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x4e,
+     0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x4c, 0x41, 0x59,
+     0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d,
+     0x45, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x02, 0x12, 0x1d,
+     0x0a, 0x19, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45,
+     0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54,
+     0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x2d, 0x0a, 0x29, 0x4c, 0x41, 0x59,
+     0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d,
+     0x45, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f,
+     0x52, 0x5f, 0x46, 0x49, 0x52, 0x53, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x4d,
+     0x49, 0x54, 0x10, 0x04, 0x12, 0x31, 0x0a, 0x2d, 0x4c, 0x41, 0x59, 0x45,
+     0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+     0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52,
+     0x5f, 0x46, 0x49, 0x52, 0x53, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56,
+     0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x05, 0x22, 0xc7, 0x01, 0x0a, 0x1a,
+     0x46, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x52, 0x65, 0x64, 0x72, 0x61, 0x77,
+     0x4f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x61,
+     0x74, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44,
+     0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x50,
+     0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a,
+     0x12, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52,
+     0x41, 0x57, 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x24, 0x0a,
+     0x20, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52,
+     0x41, 0x57, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46,
+     0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x02, 0x12,
+     0x28, 0x0a, 0x24, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45,
+     0x44, 0x52, 0x41, 0x57, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47,
+     0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54,
+     0x49, 0x4f, 0x4e, 0x10, 0x03, 0x12, 0x22, 0x0a, 0x1e, 0x46, 0x4f, 0x52,
+     0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x57,
+     0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x44,
+     0x52, 0x41, 0x57, 0x10, 0x04, 0x1a, 0xb3, 0x1b, 0x0a, 0x0a, 0x4d, 0x69,
+     0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c,
+     0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
+     0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d,
+     0x69, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x63,
+     0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+     0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28,
+     0x05, 0x52, 0x12, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x72,
+     0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x4a, 0x0a,
+     0x22, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
+     0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69,
+     0x74, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x18,
+     0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1e, 0x6c, 0x61, 0x73, 0x74, 0x46,
+     0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x53, 0x75,
+     0x62, 0x6d, 0x69, 0x74, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65,
+     0x64, 0x12, 0x46, 0x0a, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x64,
+     0x72, 0x61, 0x77, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65,
+     0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1c, 0x6c, 0x61, 0x73,
+     0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72,
+     0x44, 0x72, 0x61, 0x77, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65,
+     0x64, 0x12, 0x52, 0x0a, 0x27, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x62,
+     0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01,
+     0x28, 0x05, 0x52, 0x21, 0x6c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x42, 0x65, 0x67, 0x69, 0x6e,
+     0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x6e,
+     0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x69, 0x64, 0x5f, 0x64, 0x72, 0x61,
+     0x77, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x69, 0x64,
+     0x44, 0x72, 0x61, 0x77, 0x12, 0x59, 0x0a, 0x2b, 0x64, 0x69, 0x64, 0x5f,
+     0x73, 0x65, 0x6e, 0x64, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d,
+     0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f,
+     0x72, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x24, 0x64,
+     0x69, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d,
+     0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x43,
+     0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12,
+     0x5f, 0x0a, 0x2e, 0x64, 0x69, 0x64, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66,
+     0x79, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
+     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65,
+     0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69,
+     0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x27, 0x64, 0x69, 0x64,
+     0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d,
+     0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45,
+     0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c,
+     0x12, 0x5d, 0x0a, 0x2d, 0x64, 0x69, 0x64, 0x5f, 0x6e, 0x6f, 0x74, 0x69,
+     0x66, 0x79, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69,
+     0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f,
+     0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x6f,
+     0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x26, 0x64, 0x69, 0x64,
+     0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d,
+     0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45,
+     0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x53, 0x6f, 0x6f, 0x6e, 0x12,
+     0x4b, 0x0a, 0x23, 0x77, 0x61, 0x6e, 0x74, 0x73, 0x5f, 0x62, 0x65, 0x67,
+     0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d,
+     0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,
+     0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1e, 0x77, 0x61,
+     0x6e, 0x74, 0x73, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x70, 0x65,
+     0x63, 0x74, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x17, 0x64, 0x69, 0x64, 0x5f,
+     0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x64, 0x75, 0x72, 0x69, 0x6e,
+     0x67, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x14, 0x64, 0x69, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
+     0x44, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12,
+     0x4d, 0x0a, 0x24, 0x64, 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c,
+     0x69, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f,
+     0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73,
+     0x69, 0x6e, 0x6b, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x64,
+     0x69, 0x64, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65,
+     0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61,
+     0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x12, 0x48, 0x0a, 0x21, 0x64, 0x69,
+     0x64, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x69, 0x6d,
+     0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x76, 0x61,
+     0x6c, 0x69, 0x64, 0x61, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x1d, 0x64, 0x69, 0x64, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72,
+     0x6d, 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x49, 0x6e, 0x76,
+     0x61, 0x6c, 0x69, 0x64, 0x61, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11,
+     0x64, 0x69, 0x64, 0x5f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f,
+     0x74, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52,
+     0x0f, 0x64, 0x69, 0x64, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54,
+     0x69, 0x6c, 0x65, 0x73, 0x12, 0x4e, 0x0a, 0x23, 0x63, 0x6f, 0x6e, 0x73,
+     0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x68, 0x65, 0x63,
+     0x6b, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x6e, 0x69,
+     0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28,
+     0x05, 0x52, 0x21, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69,
+     0x76, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x62, 0x6f, 0x61,
+     0x72, 0x64, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+     0x12, 0x32, 0x0a, 0x15, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f,
+     0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+     0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x70, 0x65, 0x6e,
+     0x64, 0x69, 0x6e, 0x67, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x72,
+     0x61, 0x6d, 0x65, 0x73, 0x12, 0x63, 0x0a, 0x30, 0x73, 0x75, 0x62, 0x6d,
+     0x69, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x5f, 0x77, 0x69,
+     0x74, 0x68, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6c,
+     0x61, 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x18, 0x11, 0x20, 0x01,
+     0x28, 0x05, 0x52, 0x29, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x72,
+     0x61, 0x6d, 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x43, 0x75, 0x72, 0x72,
+     0x65, 0x6e, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x12, 0x21, 0x0a,
+     0x0c, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x72, 0x65, 0x64, 0x72, 0x61,
+     0x77, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x65, 0x65,
+     0x64, 0x73, 0x52, 0x65, 0x64, 0x72, 0x61, 0x77, 0x12, 0x2e, 0x0a, 0x13,
+     0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72,
+     0x65, 0x5f, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x11, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x50, 0x72, 0x65, 0x70,
+     0x61, 0x72, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x16,
+     0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
+     0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x14,
+     0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x42,
+     0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x6f,
+     0x6e, 0x65, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70,
+     0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x16, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x4f, 0x6e, 0x65, 0x42,
+     0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65,
+     0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x76, 0x69, 0x73, 0x69,
+     0x62, 0x6c, 0x65, 0x12, 0x39, 0x0a, 0x19, 0x62, 0x65, 0x67, 0x69, 0x6e,
+     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63,
+     0x65, 0x5f, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01,
+     0x28, 0x08, 0x52, 0x16, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
+     0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x61, 0x75, 0x73,
+     0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x61, 0x6e, 0x5f, 0x64, 0x72,
+     0x61, 0x77, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x61,
+     0x6e, 0x44, 0x72, 0x61, 0x77, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x73,
+     0x6f, 0x75, 0x72, 0x63, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x64, 0x72,
+     0x61, 0x77, 0x18, 0x19, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x65,
+     0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x44, 0x72,
+     0x61, 0x77, 0x12, 0x28, 0x0a, 0x10, 0x68, 0x61, 0x73, 0x5f, 0x70, 0x65,
+     0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x1a,
+     0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x68, 0x61, 0x73, 0x50, 0x65, 0x6e,
+     0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x12, 0x4d, 0x0a, 0x24,
+     0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65,
+     0x5f, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x66, 0x6f,
+     0x72, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+     0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x70, 0x65, 0x6e, 0x64,
+     0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x49, 0x73, 0x52, 0x65, 0x61,
+     0x64, 0x79, 0x46, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
+     0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x1c, 0x61, 0x63, 0x74, 0x69, 0x76,
+     0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x65, 0x65, 0x64, 0x73,
+     0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18,
+     0x1c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x61, 0x63, 0x74, 0x69, 0x76,
+     0x65, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x65, 0x65, 0x64, 0x73, 0x46, 0x69,
+     0x72, 0x73, 0x74, 0x44, 0x72, 0x61, 0x77, 0x12, 0x3d, 0x0a, 0x1c, 0x61,
+     0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69,
+     0x73, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x64,
+     0x72, 0x61, 0x77, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x61,
+     0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x72, 0x65, 0x65, 0x49, 0x73, 0x52,
+     0x65, 0x61, 0x64, 0x79, 0x54, 0x6f, 0x44, 0x72, 0x61, 0x77, 0x12, 0x6c,
+     0x0a, 0x35, 0x64, 0x69, 0x64, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
+     0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c,
+     0x69, 0x7a, 0x65, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x6c, 0x61,
+     0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61,
+     0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x18, 0x1e, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x2d, 0x64, 0x69, 0x64, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
+     0x41, 0x6e, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a,
+     0x65, 0x46, 0x69, 0x72, 0x73, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54,
+     0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b,
+     0x12, 0x6a, 0x0a, 0x0d, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x70, 0x72, 0x69,
+     0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0e, 0x32,
+     0x45, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65,
+     0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74,
+     0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d,
+     0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72,
+     0x65, 0x65, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x0c,
+     0x74, 0x72, 0x65, 0x65, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79,
+     0x12, 0x7d, 0x0a, 0x14, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x68,
+     0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65,
+     0x18, 0x20, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4b, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
+     0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61,
+     0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53,
+     0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48,
+     0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
+     0x12, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c,
+     0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x5d, 0x0a, 0x2d, 0x63,
+     0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x62, 0x65, 0x67, 0x69,
+     0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+     0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
+     0x5f, 0x69, 0x73, 0x5f, 0x66, 0x61, 0x73, 0x74, 0x18, 0x21, 0x20, 0x01,
+     0x28, 0x08, 0x52, 0x26, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
+     0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61,
+     0x6d, 0x65, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
+     0x49, 0x73, 0x46, 0x61, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x20, 0x6d, 0x61,
+     0x69, 0x6e, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6d, 0x69,
+     0x73, 0x73, 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x64, 0x65,
+     0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x22, 0x20, 0x01, 0x28, 0x08,
+     0x52, 0x1c, 0x6d, 0x61, 0x69, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64,
+     0x4d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x4c, 0x61, 0x73, 0x74, 0x44, 0x65,
+     0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x5b, 0x0a, 0x2c, 0x73, 0x6b,
+     0x69, 0x70, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69,
+     0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+     0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6c,
+     0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x23, 0x20, 0x01, 0x28, 0x08,
+     0x52, 0x25, 0x73, 0x6b, 0x69, 0x70, 0x4e, 0x65, 0x78, 0x74, 0x42, 0x65,
+     0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
+     0x54, 0x6f, 0x52, 0x65, 0x64, 0x75, 0x63, 0x65, 0x4c, 0x61, 0x74, 0x65,
+     0x6e, 0x63, 0x79, 0x12, 0x37, 0x0a, 0x18, 0x76, 0x69, 0x64, 0x65, 0x6f,
+     0x5f, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e,
+     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x24, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x15, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x4e, 0x65, 0x65, 0x64,
+     0x73, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
+     0x12, 0x33, 0x0a, 0x16, 0x64, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x62, 0x65,
+     0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
+     0x6d, 0x65, 0x18, 0x25, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, 0x65,
+     0x66, 0x65, 0x72, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x6c, 0x61, 0x73,
+     0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x68, 0x61, 0x64,
+     0x5f, 0x6e, 0x6f, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18,
+     0x26, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x6c, 0x61, 0x73, 0x74, 0x43,
+     0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x48, 0x61, 0x64, 0x4e, 0x6f, 0x55, 0x70,
+     0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x16, 0x64, 0x69, 0x64,
+     0x5f, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x73,
+     0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x27, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x12, 0x64, 0x69, 0x64, 0x44, 0x72, 0x61, 0x77, 0x49, 0x6e,
+     0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a,
+     0x18, 0x64, 0x69, 0x64, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f,
+     0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d,
+     0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x64, 0x69, 0x64,
+     0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x4c, 0x61, 0x73, 0x74,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x1c, 0x6e, 0x65, 0x65,
+     0x64, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65,
+     0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f,
+     0x6e, 0x18, 0x29, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x6e, 0x65, 0x65,
+     0x64, 0x73, 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x49, 0x6e,
+     0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47,
+     0x0a, 0x21, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x65,
+     0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69,
+     0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x18,
+     0x2a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x63, 0x75, 0x72, 0x72, 0x65,
+     0x6e, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65,
+     0x65, 0x49, 0x73, 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x12,
+     0x4b, 0x0a, 0x23, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f,
+     0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65,
+     0x5f, 0x77, 0x61, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69,
+     0x64, 0x65, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1e, 0x70, 0x72,
+     0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e,
+     0x67, 0x54, 0x72, 0x65, 0x65, 0x57, 0x61, 0x73, 0x49, 0x6d, 0x70, 0x6c,
+     0x53, 0x69, 0x64, 0x65, 0x12, 0x5f, 0x0a, 0x2d, 0x70, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61,
+     0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74,
+     0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65,
+     0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x08, 0x52,
+     0x28, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x41,
+     0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b,
+     0x6c, 0x65, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76,
+     0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x61, 0x0a, 0x2e, 0x70, 0x72, 0x6f,
+     0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6e, 0x69, 0x6d,
+     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65,
+     0x74, 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69,
+     0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x29, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e,
+     0x67, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f,
+     0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x50, 0x65, 0x6e,
+     0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x12, 0x59, 0x0a, 0x2a,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x70,
+     0x61, 0x69, 0x6e, 0x74, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74,
+     0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e,
+     0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x2e, 0x20, 0x01, 0x28, 0x08,
+     0x52, 0x25, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67,
+     0x50, 0x61, 0x69, 0x6e, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74,
+     0x73, 0x46, 0x6f, 0x72, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54,
+     0x72, 0x65, 0x65, 0x22, 0xb8, 0x01, 0x0a, 0x0c, 0x54, 0x72, 0x65, 0x65,
+     0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x19,
+     0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54,
+     0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
+     0x44, 0x10, 0x00, 0x12, 0x2e, 0x0a, 0x2a, 0x54, 0x52, 0x45, 0x45, 0x5f,
+     0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x53, 0x41, 0x4d,
+     0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x46,
+     0x4f, 0x52, 0x5f, 0x42, 0x4f, 0x54, 0x48, 0x5f, 0x54, 0x52, 0x45, 0x45,
+     0x53, 0x10, 0x01, 0x12, 0x2b, 0x0a, 0x27, 0x54, 0x52, 0x45, 0x45, 0x5f,
+     0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x53, 0x4d, 0x4f,
+     0x4f, 0x54, 0x48, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x41, 0x4b, 0x45,
+     0x53, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x10, 0x02,
+     0x12, 0x2c, 0x0a, 0x28, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49,
+     0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x4e, 0x45, 0x57, 0x5f, 0x43, 0x4f,
+     0x4e, 0x54, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x41, 0x4b, 0x45, 0x53, 0x5f,
+     0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x10, 0x03, 0x22, 0x82,
+     0x01, 0x0a, 0x12, 0x53, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e,
+     0x64, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a,
+     0x1a, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44,
+     0x4c, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
+     0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x43, 0x52,
+     0x4f, 0x4c, 0x4c, 0x5f, 0x41, 0x46, 0x46, 0x45, 0x43, 0x54, 0x53, 0x5f,
+     0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c,
+     0x45, 0x52, 0x10, 0x01, 0x12, 0x29, 0x0a, 0x25, 0x53, 0x43, 0x52, 0x4f,
+     0x4c, 0x4c, 0x5f, 0x44, 0x4f, 0x45, 0x53, 0x5f, 0x4e, 0x4f, 0x54, 0x5f,
+     0x41, 0x46, 0x46, 0x45, 0x43, 0x54, 0x5f, 0x53, 0x43, 0x52, 0x4f, 0x4c,
+     0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x52, 0x10, 0x02, 0x22,
+     0x8f, 0x05, 0x0a, 0x0e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
+     0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x46, 0x0a, 0x04, 0x74, 0x79,
+     0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x41, 0x72, 0x67, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46,
+     0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x54, 0x79, 0x70, 0x65,
+     0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f,
+     0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+     0x04, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12,
+     0x27, 0x0a, 0x0f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f,
+     0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04,
+     0x52, 0x0e, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x4e, 0x75,
+     0x6d, 0x62, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x66, 0x72, 0x61, 0x6d,
+     0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x04, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x0b, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69,
+     0x6d, 0x65, 0x55, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x61, 0x64,
+     0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28,
+     0x03, 0x52, 0x0a, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x55,
+     0x73, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
+     0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x06,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
+     0x61, 0x6c, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x28, 0x0a,
+     0x10, 0x6f, 0x6e, 0x5f, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
+     0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52,
+     0x0e, 0x6f, 0x6e, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50,
+     0x61, 0x74, 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6e, 0x69, 0x6d, 0x61,
+     0x74, 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x0b, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x4f, 0x6e,
+     0x6c, 0x79, 0x12, 0x30, 0x0a, 0x13, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+     0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x69,
+     0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x11, 0x73,
+     0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
+     0x6e, 0x49, 0x69, 0x64, 0x12, 0x4a, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72,
+     0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+     0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69,
+     0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+     0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa2, 0x01, 0x0a,
+     0x12, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41,
+     0x72, 0x67, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x21, 0x42,
+     0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41,
+     0x52, 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53,
+     0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21,
+     0x0a, 0x1d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d,
+     0x45, 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
+     0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x01, 0x12, 0x20, 0x0a,
+     0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+     0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e,
+     0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x20, 0x0a, 0x1c, 0x42,
+     0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41,
+     0x52, 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x49, 0x53,
+     0x53, 0x45, 0x44, 0x10, 0x03, 0x42, 0x0e, 0x0a, 0x0c, 0x63, 0x72, 0x65,
+     0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x22, 0xf5, 0x05,
+     0x0a, 0x12, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46,
+     0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x22, 0x0a, 0x0d,
+     0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75,
+     0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64,
+     0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x55, 0x73, 0x12, 0x24, 0x0a, 0x0e,
+     0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f,
+     0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x66, 0x69,
+     0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x41, 0x74, 0x55, 0x73, 0x12, 0x3f,
+     0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
+     0x0e, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69,
+     0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
+     0x67, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74,
+     0x61, 0x74, 0x65, 0x12, 0x44, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65,
+     0x6e, 0x74, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
+     0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69,
+     0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x48, 0x00,
+     0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x41, 0x72, 0x67,
+     0x73, 0x12, 0x3e, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x61, 0x72,
+     0x67, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x41, 0x72, 0x67, 0x73, 0x48, 0x00, 0x52, 0x08, 0x6c, 0x61, 0x73,
+     0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x5c, 0x0a, 0x10, 0x74, 0x69, 0x6d,
+     0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x75,
+     0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46,
+     0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x2e, 0x54, 0x69, 0x6d,
+     0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x49, 0x6e, 0x55, 0x73, 0x52,
+     0x0e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x49,
+     0x6e, 0x55, 0x73, 0x1a, 0xad, 0x02, 0x0a, 0x0e, 0x54, 0x69, 0x6d, 0x65,
+     0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x49, 0x6e, 0x55, 0x73, 0x12, 0x25,
+     0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x64,
+     0x65, 0x6c, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d,
+     0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x74,
+     0x61, 0x12, 0x31, 0x0a, 0x15, 0x6e, 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f,
+     0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c,
+     0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x6e, 0x6f,
+     0x77, 0x54, 0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x44,
+     0x65, 0x6c, 0x74, 0x61, 0x12, 0x34, 0x0a, 0x17, 0x66, 0x72, 0x61, 0x6d,
+     0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6e, 0x6f,
+     0x77, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28,
+     0x03, 0x52, 0x13, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65,
+     0x54, 0x6f, 0x4e, 0x6f, 0x77, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x3e,
+     0x0a, 0x1c, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65,
+     0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65,
+     0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x18, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x54,
+     0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c,
+     0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6e, 0x6f, 0x77, 0x18, 0x05, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x03, 0x6e, 0x6f, 0x77, 0x12, 0x1d, 0x0a, 0x0a,
+     0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54,
+     0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c,
+     0x69, 0x6e, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x64,
+     0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x38, 0x0a, 0x05, 0x53,
+     0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x42, 0x45, 0x47, 0x49,
+     0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x49,
+     0x53, 0x48, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x42, 0x45,
+     0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55, 0x53,
+     0x49, 0x4e, 0x47, 0x10, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x61, 0x72, 0x67,
+     0x73, 0x22, 0xa6, 0x01, 0x0a, 0x17, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46,
+     0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
+     0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x72, 0x6f,
+     0x70, 0x70, 0x65, 0x64, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66,
+     0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x15, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64,
+     0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
+     0x67, 0x73, 0x12, 0x52, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x62,
+     0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61,
+     0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
+     0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74,
+     0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
+     0x67, 0x73, 0x22, 0xc5, 0x01, 0x0a, 0x15, 0x42, 0x65, 0x67, 0x69, 0x6e,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53,
+     0x74, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72,
+     0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52,
+     0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a,
+     0x06, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x06, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x12, 0x23, 0x0a,
+     0x0d, 0x6e, 0x75, 0x6d, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65,
+     0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75,
+     0x6d, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x52,
+     0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e,
+     0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18,
+     0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
+     0x67, 0x73, 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x42, 0x65, 0x67, 0x69,
+     0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x22, 0xfd,
+     0x04, 0x0a, 0x17, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
+     0x72, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f,
+     0x72, 0x79, 0x12, 0x65, 0x0a, 0x31, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
+     0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x71,
+     0x75, 0x65, 0x75, 0x65, 0x5f, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61,
+     0x6c, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64,
+     0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x03, 0x52, 0x2a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x43, 0x72,
+     0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61,
+     0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x6c, 0x0a,
+     0x35, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f,
+     0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f,
+     0x6e, 0x6f, 0x74, 0x5f, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
+     0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65,
+     0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x2d, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46,
+     0x72, 0x61, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x4e, 0x6f, 0x74,
+     0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x45, 0x73, 0x74, 0x69,
+     0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12,
+     0x76, 0x0a, 0x3b, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69,
+     0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x72,
+     0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x74,
+     0x6f, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x65, 0x73, 0x74,
+     0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f,
+     0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x31, 0x62, 0x65,
+     0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
+     0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x6f, 0x52, 0x65, 0x61, 0x64, 0x79,
+     0x54, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x45, 0x73, 0x74, 0x69,
+     0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12,
+     0x5d, 0x0a, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x6f,
+     0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63,
+     0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d,
+     0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73,
+     0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x26, 0x63, 0x6f, 0x6d, 0x6d,
+     0x69, 0x74, 0x54, 0x6f, 0x52, 0x65, 0x61, 0x64, 0x79, 0x54, 0x6f, 0x41,
+     0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x45, 0x73, 0x74, 0x69, 0x6d,
+     0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x44,
+     0x0a, 0x1f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69,
+     0x6c, 0x65, 0x73, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65,
+     0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x05, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x1b, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65,
+     0x54, 0x69, 0x6c, 0x65, 0x73, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74,
+     0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x3b, 0x0a, 0x1a,
+     0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x73, 0x74,
+     0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f,
+     0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x61, 0x63,
+     0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61,
+     0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x33, 0x0a,
+     0x16, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61,
+     0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18,
+     0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x64, 0x72, 0x61, 0x77, 0x45,
+     0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61,
+     0x55, 0x73, 0x2a, 0xb0, 0x05, 0x0a, 0x1f, 0x43, 0x68, 0x72, 0x6f, 0x6d,
+     0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53,
+     0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69,
+     0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x1f, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48,
+     0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f,
+     0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
+     0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x43, 0x5f, 0x53, 0x43,
+     0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49,
+     0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x2d, 0x0a,
+     0x29, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45,
+     0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x45, 0x4e,
+     0x44, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e,
+     0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x1e, 0x0a, 0x1a,
+     0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52,
+     0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d,
+     0x49, 0x54, 0x10, 0x03, 0x12, 0x2a, 0x0a, 0x26, 0x43, 0x43, 0x5f, 0x53,
+     0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54,
+     0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45,
+     0x5f, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, 0x04,
+     0x12, 0x28, 0x0a, 0x24, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44,
+     0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
+     0x44, 0x52, 0x41, 0x57, 0x5f, 0x49, 0x46, 0x5f, 0x50, 0x4f, 0x53, 0x53,
+     0x49, 0x42, 0x4c, 0x45, 0x10, 0x05, 0x12, 0x23, 0x0a, 0x1f, 0x43, 0x43,
+     0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41,
+     0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x46,
+     0x4f, 0x52, 0x43, 0x45, 0x44, 0x10, 0x06, 0x12, 0x22, 0x0a, 0x1e, 0x43,
+     0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f,
+     0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x5f,
+     0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x07, 0x12, 0x3c, 0x0a, 0x38, 0x43,
+     0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f,
+     0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e,
+     0x5f, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f,
+     0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x43,
+     0x52, 0x45, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x08, 0x12, 0x25, 0x0a,
+     0x21, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45,
+     0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x45,
+     0x50, 0x41, 0x52, 0x45, 0x5f, 0x54, 0x49, 0x4c, 0x45, 0x53, 0x10, 0x09,
+     0x12, 0x38, 0x0a, 0x34, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44,
+     0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
+     0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4c,
+     0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52,
+     0x41, 0x4d, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x10, 0x0a, 0x12, 0x36,
+     0x0a, 0x32, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c,
+     0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x45,
+     0x52, 0x46, 0x4f, 0x52, 0x4d, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x53,
+     0x49, 0x44, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41,
+     0x54, 0x49, 0x4f, 0x4e, 0x10, 0x0b, 0x12, 0x42, 0x0a, 0x3e, 0x43, 0x43,
+     0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41,
+     0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x54, 0x49, 0x46, 0x59,
+     0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f,
+     0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x58,
+     0x50, 0x45, 0x43, 0x54, 0x45, 0x44, 0x5f, 0x55, 0x4e, 0x54, 0x49, 0x4c,
+     0x10, 0x0c, 0x12, 0x41, 0x0a, 0x3d, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48,
+     0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f,
+     0x4e, 0x5f, 0x4e, 0x4f, 0x54, 0x49, 0x46, 0x59, 0x5f, 0x42, 0x45, 0x47,
+     0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d,
+     0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x58, 0x50, 0x45, 0x43, 0x54,
+     0x45, 0x44, 0x5f, 0x53, 0x4f, 0x4f, 0x4e, 0x10, 0x0d, 0x42, 0x02, 0x48,
+     0x03, 0x0a, 0xb8, 0x01, 0x0a, 0x3f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72,
+     0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76,
+     0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x68,
+     0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x61, 0x6d,
+     0x70, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x22, 0x60, 0x0a, 0x15, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65,
+     0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x53, 0x61, 0x6d,
+     0x70, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f,
+     0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08,
+     0x6e, 0x61, 0x6d, 0x65, 0x48, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04,
+     0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
+     0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x61, 0x6d, 0x70,
+     0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x73, 0x61,
+     0x6d, 0x70, 0x6c, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x7d, 0x0a, 0x3c,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72,
+     0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68,
+     0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x65, 0x64, 0x5f, 0x73,
+     0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x28, 0x0a, 0x12, 0x43, 0x68, 0x72,
+     0x6f, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76,
+     0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+     0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x42,
+     0x02, 0x48, 0x03, 0x0a, 0xbc, 0x08, 0x0a, 0x39, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
+     0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
+     0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65,
+     0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x69, 0x70, 0x63, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xe9,
+     0x07, 0x0a, 0x0f, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x65, 0x67,
+     0x61, 0x63, 0x79, 0x49, 0x70, 0x63, 0x12, 0x52, 0x0a, 0x0d, 0x6d, 0x65,
+     0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x18,
+     0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79,
+     0x49, 0x70, 0x63, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43,
+     0x6c, 0x61, 0x73, 0x73, 0x52, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+     0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x65,
+     0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02,
+     0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+     0x65, 0x4c, 0x69, 0x6e, 0x65, 0x22, 0xde, 0x06, 0x0a, 0x0c, 0x4d, 0x65,
+     0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x15,
+     0x0a, 0x11, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50,
+     0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a,
+     0x10, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x41, 0x55, 0x54, 0x4f, 0x4d,
+     0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x43,
+     0x4c, 0x41, 0x53, 0x53, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02,
+     0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x50, 0x41,
+     0x47, 0x45, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53,
+     0x53, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c,
+     0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x57, 0x49, 0x44, 0x47, 0x45, 0x54,
+     0x10, 0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f,
+     0x49, 0x4e, 0x50, 0x55, 0x54, 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x43,
+     0x4c, 0x41, 0x53, 0x53, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x10, 0x07, 0x12,
+     0x10, 0x0a, 0x0c, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x57, 0x4f, 0x52,
+     0x4b, 0x45, 0x52, 0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41,
+     0x53, 0x53, 0x5f, 0x4e, 0x41, 0x43, 0x4c, 0x10, 0x09, 0x12, 0x15, 0x0a,
+     0x11, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x47, 0x50, 0x55, 0x5f, 0x43,
+     0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x10, 0x0a, 0x12, 0x0f, 0x0a, 0x0b,
+     0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x10,
+     0x0b, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x50,
+     0x50, 0x41, 0x50, 0x49, 0x10, 0x0c, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x4c,
+     0x41, 0x53, 0x53, 0x5f, 0x43, 0x48, 0x52, 0x4f, 0x4d, 0x45, 0x10, 0x0d,
+     0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x44, 0x52,
+     0x41, 0x47, 0x10, 0x0e, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53,
+     0x53, 0x5f, 0x50, 0x52, 0x49, 0x4e, 0x54, 0x10, 0x0f, 0x12, 0x13, 0x0a,
+     0x0f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e,
+     0x53, 0x49, 0x4f, 0x4e, 0x10, 0x10, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4c,
+     0x41, 0x53, 0x53, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x5f, 0x49, 0x4e, 0x50,
+     0x55, 0x54, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x11, 0x12,
+     0x14, 0x0a, 0x10, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x42, 0x4c, 0x49,
+     0x4e, 0x4b, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x10, 0x12, 0x12, 0x17, 0x0a,
+     0x13, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x53,
+     0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x10, 0x13, 0x12, 0x13,
+     0x0a, 0x0f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x45, 0x52,
+     0x45, 0x4e, 0x44, 0x45, 0x52, 0x10, 0x14, 0x12, 0x14, 0x0a, 0x10, 0x43,
+     0x4c, 0x41, 0x53, 0x53, 0x5f, 0x43, 0x48, 0x52, 0x4f, 0x4d, 0x4f, 0x54,
+     0x49, 0x4e, 0x47, 0x10, 0x15, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4c, 0x41,
+     0x53, 0x53, 0x5f, 0x42, 0x52, 0x4f, 0x57, 0x53, 0x45, 0x52, 0x5f, 0x50,
+     0x4c, 0x55, 0x47, 0x49, 0x4e, 0x10, 0x16, 0x12, 0x1a, 0x0a, 0x16, 0x43,
+     0x4c, 0x41, 0x53, 0x53, 0x5f, 0x41, 0x4e, 0x44, 0x52, 0x4f, 0x49, 0x44,
+     0x5f, 0x57, 0x45, 0x42, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x17, 0x12,
+     0x13, 0x0a, 0x0f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4e, 0x41, 0x43,
+     0x4c, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x18, 0x12, 0x19, 0x0a, 0x15,
+     0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x45, 0x4e, 0x43, 0x52, 0x59, 0x50,
+     0x54, 0x45, 0x44, 0x5f, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x10, 0x19, 0x12,
+     0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x43, 0x41, 0x53,
+     0x54, 0x10, 0x1a, 0x12, 0x19, 0x0a, 0x15, 0x43, 0x4c, 0x41, 0x53, 0x53,
+     0x5f, 0x47, 0x49, 0x4e, 0x5f, 0x4a, 0x41, 0x56, 0x41, 0x5f, 0x42, 0x52,
+     0x49, 0x44, 0x47, 0x45, 0x10, 0x1b, 0x12, 0x21, 0x0a, 0x1d, 0x43, 0x4c,
+     0x41, 0x53, 0x53, 0x5f, 0x43, 0x48, 0x52, 0x4f, 0x4d, 0x45, 0x5f, 0x55,
+     0x54, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, 0x52, 0x49, 0x4e, 0x54,
+     0x49, 0x4e, 0x47, 0x10, 0x1c, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x4c, 0x41,
+     0x53, 0x53, 0x5f, 0x4f, 0x5a, 0x4f, 0x4e, 0x45, 0x5f, 0x47, 0x50, 0x55,
+     0x10, 0x1d, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f,
+     0x57, 0x45, 0x42, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x10, 0x1e, 0x12, 0x17,
+     0x0a, 0x13, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4e, 0x45, 0x54, 0x57,
+     0x4f, 0x52, 0x4b, 0x5f, 0x48, 0x49, 0x4e, 0x54, 0x53, 0x10, 0x1f, 0x12,
+     0x1f, 0x0a, 0x1b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x45, 0x58, 0x54,
+     0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x47, 0x55, 0x45, 0x53,
+     0x54, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x20, 0x12, 0x14, 0x0a, 0x10,
+     0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x47, 0x55, 0x45, 0x53, 0x54, 0x5f,
+     0x56, 0x49, 0x45, 0x57, 0x10, 0x21, 0x12, 0x1f, 0x0a, 0x1b, 0x43, 0x4c,
+     0x41, 0x53, 0x53, 0x5f, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x5f, 0x50, 0x4c,
+     0x41, 0x59, 0x45, 0x52, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x47, 0x41, 0x54,
+     0x45, 0x10, 0x22, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x4c, 0x41, 0x53, 0x53,
+     0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x57,
+     0x4f, 0x52, 0x4b, 0x45, 0x52, 0x10, 0x23, 0x12, 0x1c, 0x0a, 0x18, 0x43,
+     0x4c, 0x41, 0x53, 0x53, 0x5f, 0x53, 0x55, 0x42, 0x52, 0x45, 0x53, 0x4f,
+     0x55, 0x52, 0x43, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x54, 0x45, 0x52, 0x10,
+     0x24, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x55,
+     0x4e, 0x46, 0x52, 0x45, 0x45, 0x5a, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x46,
+     0x52, 0x41, 0x4d, 0x45, 0x10, 0x25, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x7b,
+     0x0a, 0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f,
+     0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f,
+     0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f,
+     0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+     0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x22, 0x29, 0x0a, 0x0f, 0x43, 0x68, 0x72, 0x6f,
+     0x6d, 0x65, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12,
+     0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42,
+     0x02, 0x48, 0x03, 0x0a, 0x81, 0x18, 0x0a, 0x33, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
+     0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
+     0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
+     0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+     0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x38, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72,
+     0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76,
+     0x65, 0x6e, 0x74, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x61, 0x6e,
+     0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x1a, 0x33, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63,
+     0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e,
+     0x74, 0x2f, 0x6c, 0x6f, 0x67, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+     0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b,
+     0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x74, 0x61, 0x73, 0x6b, 0x5f,
+     0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x1a, 0x49, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61,
+     0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65,
+     0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x63, 0x6f,
+     0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x63, 0x68,
+     0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3f, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
+     0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
+     0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65,
+     0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, 0x73,
+     0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
+     0x3c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74,
+     0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63,
+     0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x65, 0x64, 0x5f,
+     0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x1a, 0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65,
+     0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74,
+     0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x67, 0x61,
+     0x63, 0x79, 0x5f, 0x69, 0x70, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x1a, 0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f,
+     0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f,
+     0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f,
+     0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
+     0xae, 0x12, 0x0a, 0x0a, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x45, 0x76, 0x65,
+     0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f,
+     0x72, 0x79, 0x5f, 0x69, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
+     0x04, 0x52, 0x0c, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49,
+     0x69, 0x64, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x65, 0x67,
+     0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x16, 0x20, 0x03, 0x28, 0x09, 0x52,
+     0x0a, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12,
+     0x1b, 0x0a, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x69, 0x64, 0x18,
+     0x0a, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x07, 0x6e, 0x61, 0x6d,
+     0x65, 0x49, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+     0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61,
+     0x6d, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09,
+     0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54,
+     0x72, 0x61, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x54, 0x79,
+     0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a,
+     0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x0b,
+     0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x55,
+     0x75, 0x69, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x74, 0x68, 0x72, 0x65, 0x61,
+     0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
+     0x5f, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48, 0x01, 0x52,
+     0x11, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x44,
+     0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x37, 0x0a, 0x17, 0x74, 0x68,
+     0x72, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x62,
+     0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x11, 0x20,
+     0x01, 0x28, 0x03, 0x48, 0x01, 0x52, 0x14, 0x74, 0x68, 0x72, 0x65, 0x61,
+     0x64, 0x54, 0x69, 0x6d, 0x65, 0x41, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74,
+     0x65, 0x55, 0x73, 0x12, 0x45, 0x0a, 0x1e, 0x74, 0x68, 0x72, 0x65, 0x61,
+     0x64, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f,
+     0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74,
+     0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x48, 0x02, 0x52, 0x1b, 0x74,
+     0x68, 0x72, 0x65, 0x61, 0x64, 0x49, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63,
+     0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x44, 0x65, 0x6c,
+     0x74, 0x61, 0x12, 0x4b, 0x0a, 0x21, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64,
+     0x5f, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+     0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x62, 0x73, 0x6f, 0x6c,
+     0x75, 0x74, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x48, 0x02, 0x52,
+     0x1e, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x49, 0x6e, 0x73, 0x74, 0x72,
+     0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x41,
+     0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x12, 0x4d, 0x0a, 0x11, 0x64,
+     0x65, 0x62, 0x75, 0x67, 0x5f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74,
+     0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20,
+     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x41, 0x6e,
+     0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x64, 0x65,
+     0x62, 0x75, 0x67, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f,
+     0x6e, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65,
+     0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x61, 0x73,
+     0x6b, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d,
+     0x74, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f,
+     0x6e, 0x12, 0x3c, 0x0a, 0x0b, 0x6c, 0x6f, 0x67, 0x5f, 0x6d, 0x65, 0x73,
+     0x73, 0x61, 0x67, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
+     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4c, 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73,
+     0x61, 0x67, 0x65, 0x52, 0x0a, 0x6c, 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73,
+     0x61, 0x67, 0x65, 0x12, 0x5d, 0x0a, 0x12, 0x63, 0x63, 0x5f, 0x73, 0x63,
+     0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74,
+     0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70,
+     0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75,
+     0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x10, 0x63, 0x63,
+     0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61,
+     0x74, 0x65, 0x12, 0x4c, 0x0a, 0x11, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65,
+     0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18,
+     0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76,
+     0x65, 0x6e, 0x74, 0x52, 0x0f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x55,
+     0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x55, 0x0a, 0x14,
+     0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x65, 0x64,
+     0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x1a, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72,
+     0x6f, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76,
+     0x69, 0x63, 0x65, 0x52, 0x12, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4b,
+     0x65, 0x79, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
+     0x4c, 0x0a, 0x11, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6c, 0x65,
+     0x67, 0x61, 0x63, 0x79, 0x5f, 0x69, 0x70, 0x63, 0x18, 0x1b, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72,
+     0x6f, 0x6d, 0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, 0x70, 0x63,
+     0x52, 0x0f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x65, 0x67, 0x61,
+     0x63, 0x79, 0x49, 0x70, 0x63, 0x12, 0x5e, 0x0a, 0x17, 0x63, 0x68, 0x72,
+     0x6f, 0x6d, 0x65, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61,
+     0x6d, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x18, 0x1c, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72,
+     0x6f, 0x6d, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d,
+     0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x15, 0x63, 0x68, 0x72, 0x6f,
+     0x6d, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x53,
+     0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x2e, 0x0a, 0x12, 0x74, 0x69, 0x6d,
+     0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
+     0x5f, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x48, 0x03, 0x52,
+     0x10, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x44, 0x65,
+     0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x74, 0x69, 0x6d,
+     0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x61, 0x62, 0x73, 0x6f, 0x6c,
+     0x75, 0x74, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x03,
+     0x48, 0x03, 0x52, 0x13, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+     0x70, 0x41, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x55, 0x73, 0x12,
+     0x4a, 0x0a, 0x0c, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x65, 0x76,
+     0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x45, 0x76, 0x65,
+     0x6e, 0x74, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x45, 0x76, 0x65,
+     0x6e, 0x74, 0x52, 0x0b, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x45, 0x76,
+     0x65, 0x6e, 0x74, 0x1a, 0xfa, 0x06, 0x0a, 0x0b, 0x4c, 0x65, 0x67, 0x61,
+     0x63, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6e,
+     0x61, 0x6d, 0x65, 0x5f, 0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x04, 0x52, 0x07, 0x6e, 0x61, 0x6d, 0x65, 0x49, 0x69, 0x64, 0x12, 0x14,
+     0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+     0x05, 0x52, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b,
+     0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x73, 0x18,
+     0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74,
+     0x69, 0x6f, 0x6e, 0x55, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x68, 0x72,
+     0x65, 0x61, 0x64, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+     0x5f, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x74,
+     0x68, 0x72, 0x65, 0x61, 0x64, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
+     0x6e, 0x55, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x74, 0x68, 0x72, 0x65, 0x61,
+     0x64, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f,
+     0x6e, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x0f, 0x20, 0x01, 0x28,
+     0x03, 0x52, 0x16, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x49, 0x6e, 0x73,
+     0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x6c, 0x74,
+     0x61, 0x12, 0x21, 0x0a, 0x0b, 0x75, 0x6e, 0x73, 0x63, 0x6f, 0x70, 0x65,
+     0x64, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00,
+     0x52, 0x0a, 0x75, 0x6e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x64, 0x49, 0x64,
+     0x12, 0x1b, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64,
+     0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x07, 0x6c, 0x6f,
+     0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x09, 0x67, 0x6c, 0x6f,
+     0x62, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04,
+     0x48, 0x00, 0x52, 0x08, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x64,
+     0x12, 0x19, 0x0a, 0x08, 0x69, 0x64, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65,
+     0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x64, 0x53, 0x63,
+     0x6f, 0x70, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x5f, 0x61,
+     0x73, 0x79, 0x6e, 0x63, 0x5f, 0x74, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01,
+     0x28, 0x08, 0x52, 0x0b, 0x75, 0x73, 0x65, 0x41, 0x73, 0x79, 0x6e, 0x63,
+     0x54, 0x74, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x62, 0x69, 0x6e, 0x64, 0x5f,
+     0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x62, 0x69,
+     0x6e, 0x64, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x62, 0x69, 0x6e, 0x64,
+     0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x73, 0x69, 0x6e,
+     0x67, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x62, 0x69, 0x6e,
+     0x64, 0x54, 0x6f, 0x45, 0x6e, 0x63, 0x6c, 0x6f, 0x73, 0x69, 0x6e, 0x67,
+     0x12, 0x5c, 0x0a, 0x0e, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x64, 0x69, 0x72,
+     0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e,
+     0x32, 0x35, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b,
+     0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79,
+     0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x46, 0x6c, 0x6f, 0x77, 0x44, 0x69,
+     0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x66, 0x6c, 0x6f,
+     0x77, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x69,
+     0x0a, 0x13, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x5f, 0x65, 0x76,
+     0x65, 0x6e, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x0e, 0x20,
+     0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72,
+     0x61, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x65, 0x67,
+     0x61, 0x63, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x49, 0x6e, 0x73,
+     0x74, 0x61, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x6f,
+     0x70, 0x65, 0x52, 0x11, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x45,
+     0x76, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x21, 0x0a,
+     0x0c, 0x70, 0x69, 0x64, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
+     0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x70, 0x69, 0x64,
+     0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x21, 0x0a, 0x0c,
+     0x74, 0x69, 0x64, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65,
+     0x18, 0x13, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x74, 0x69, 0x64, 0x4f,
+     0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x22, 0x50, 0x0a, 0x0d, 0x46,
+     0x6c, 0x6f, 0x77, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+     0x12, 0x14, 0x0a, 0x10, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x53,
+     0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b,
+     0x0a, 0x07, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x4e, 0x10, 0x01, 0x12,
+     0x0c, 0x0a, 0x08, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x4f, 0x55, 0x54, 0x10,
+     0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x4e,
+     0x4f, 0x55, 0x54, 0x10, 0x03, 0x22, 0x61, 0x0a, 0x11, 0x49, 0x6e, 0x73,
+     0x74, 0x61, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x6f,
+     0x70, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x43, 0x4f, 0x50, 0x45, 0x5f,
+     0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
+     0x00, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x43, 0x4f, 0x50, 0x45, 0x5f, 0x47,
+     0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x53,
+     0x43, 0x4f, 0x50, 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x43, 0x45, 0x53, 0x53,
+     0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x43, 0x4f, 0x50, 0x45, 0x5f,
+     0x54, 0x48, 0x52, 0x45, 0x41, 0x44, 0x10, 0x03, 0x42, 0x04, 0x0a, 0x02,
+     0x69, 0x64, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x58, 0x0a, 0x04,
+     0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45,
+     0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
+     0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53,
+     0x4c, 0x49, 0x43, 0x45, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x10, 0x01,
+     0x12, 0x12, 0x0a, 0x0e, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x4c, 0x49,
+     0x43, 0x45, 0x5f, 0x45, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c,
+     0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x54,
+     0x10, 0x03, 0x42, 0x0c, 0x0a, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66,
+     0x69, 0x65, 0x6c, 0x64, 0x42, 0x0d, 0x0a, 0x0b, 0x74, 0x68, 0x72, 0x65,
+     0x61, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x42, 0x1a, 0x0a, 0x18, 0x74,
+     0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75,
+     0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42,
+     0x0b, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+     0x22, 0x33, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x45, 0x76, 0x65,
+     0x6e, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1d,
+     0x0a, 0x0a, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x75, 0x75, 0x69, 0x64,
+     0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x72, 0x61, 0x63,
+     0x6b, 0x55, 0x75, 0x69, 0x64, 0x22, 0x35, 0x0a, 0x0d, 0x45, 0x76, 0x65,
+     0x6e, 0x74, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x10,
+     0x0a, 0x03, 0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
+     0x03, 0x69, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+     0x22, 0x31, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d,
+     0x65, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x04, 0x52, 0x03, 0x69, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e,
+     0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
+     0x61, 0x6d, 0x65, 0x42, 0x02, 0x48, 0x03}};
+
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_DESCRIPTOR_H_
diff --git a/src/trace_processor/importers/proto/track_event_module.cc b/src/trace_processor/importers/proto/track_event_module.cc
new file mode 100644
index 0000000..8e80a80
--- /dev/null
+++ b/src/trace_processor/importers/proto/track_event_module.cc
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 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
+ *
+ *      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.
+ */
+#include "src/trace_processor/importers/proto/track_event_module.h"
+#include "perfetto/base/build_config.h"
+#include "src/trace_processor/timestamped_trace_piece.h"
+
+#include "protos/perfetto/config/trace_config.pbzero.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+using perfetto::protos::pbzero::TracePacket;
+
+TrackEventModule::TrackEventModule(TraceProcessorContext* context)
+    : tokenizer_(context), parser_(context) {
+  RegisterForField(TracePacket::kTrackEventFieldNumber, context);
+  RegisterForField(TracePacket::kTrackDescriptorFieldNumber, context);
+  RegisterForField(TracePacket::kThreadDescriptorFieldNumber, context);
+  RegisterForField(TracePacket::kProcessDescriptorFieldNumber, context);
+}
+
+TrackEventModule::~TrackEventModule() = default;
+
+ModuleResult TrackEventModule::TokenizePacket(
+    const TracePacket::Decoder& decoder,
+    TraceBlobView* packet,
+    int64_t packet_timestamp,
+    PacketSequenceState* state,
+    uint32_t field_id) {
+  switch (field_id) {
+    case TracePacket::kTrackDescriptorFieldNumber:
+      tokenizer_.TokenizeTrackDescriptorPacket(decoder);
+      return ModuleResult::Handled();
+    case TracePacket::kTrackEventFieldNumber:
+      tokenizer_.TokenizeTrackEventPacket(state, decoder, packet,
+                                          packet_timestamp);
+      return ModuleResult::Handled();
+    case TracePacket::kThreadDescriptorFieldNumber:
+      // TODO(eseckler): Remove these once Chrome has switched fully over to
+      // TrackDescriptors.
+      tokenizer_.TokenizeThreadDescriptorPacket(state, decoder);
+      return ModuleResult::Handled();
+    case TracePacket::kProcessDescriptorFieldNumber:
+      tokenizer_.TokenizeProcessDescriptorPacket(decoder);
+      return ModuleResult::Handled();
+  }
+  return ModuleResult::Ignored();
+}
+
+void TrackEventModule::ParsePacket(const TracePacket::Decoder& decoder,
+                                   const TimestampedTracePiece& ttp,
+                                   uint32_t field_id) {
+  if (field_id == TracePacket::kTrackEventFieldNumber) {
+    parser_.ParseTrackEvent(
+        ttp.timestamp, ttp.thread_timestamp, ttp.thread_instruction_count,
+        ttp.packet_sequence_state, ttp.packet_sequence_state_generation,
+        decoder.track_event());
+  }
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/track_event_module.h b/src/trace_processor/importers/proto/track_event_module.h
index b58b8bc..de31d47 100644
--- a/src/trace_processor/importers/proto/track_event_module.h
+++ b/src/trace_processor/importers/proto/track_event_module.h
@@ -17,66 +17,31 @@
 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_MODULE_H_
 #define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_MODULE_H_
 
-#include "perfetto/base/build_config.h"
 #include "src/trace_processor/importers/proto/proto_importer_module.h"
 #include "src/trace_processor/importers/proto/track_event_parser.h"
 #include "src/trace_processor/importers/proto/track_event_tokenizer.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
 
-#include "protos/perfetto/config/trace_config.pbzero.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 namespace trace_processor {
 
-class TrackEventModule : public ProtoImporterModuleBase</*IsEnabled=*/1> {
+class TrackEventModule : public ProtoImporterModule {
  public:
-  explicit TrackEventModule(TraceProcessorContext* context)
-      : ProtoImporterModuleBase(context),
-        tokenizer_(context),
-        parser_(context) {}
+  explicit TrackEventModule(TraceProcessorContext* context);
+
+  ~TrackEventModule() override;
 
   ModuleResult TokenizePacket(
       const protos::pbzero::TracePacket::Decoder& decoder,
       TraceBlobView* packet,
       int64_t packet_timestamp,
-      PacketSequenceState* state) {
-    if (decoder.has_track_descriptor()) {
-      tokenizer_.TokenizeTrackDescriptorPacket(decoder);
-      return ModuleResult::Handled();
-    }
+      PacketSequenceState* state,
+      uint32_t field_id) override;
 
-    if (decoder.has_track_event()) {
-      tokenizer_.TokenizeTrackEventPacket(state, decoder, packet,
-                                          packet_timestamp);
-      return ModuleResult::Handled();
-    }
-
-    // TODO(eseckler): Remove these once Chrome has switched fully over to
-    // TrackDescriptors.
-    if (decoder.has_thread_descriptor()) {
-      tokenizer_.TokenizeThreadDescriptorPacket(state, decoder);
-      return ModuleResult::Handled();
-    }
-    if (decoder.has_process_descriptor()) {
-      tokenizer_.TokenizeProcessDescriptorPacket(decoder);
-      return ModuleResult::Handled();
-    }
-
-    return ModuleResult::Ignored();
-  }
-
-  ModuleResult ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
-                           const TimestampedTracePiece& ttp) {
-    if (decoder.has_track_event()) {
-      parser_.ParseTrackEvent(
-          ttp.timestamp, ttp.thread_timestamp, ttp.thread_instruction_count,
-          ttp.packet_sequence_state, ttp.packet_sequence_state_generation,
-          decoder.track_event());
-      return ModuleResult::Handled();
-    }
-    return ModuleResult::Ignored();
-  }
+  void ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
+                   const TimestampedTracePiece& ttp,
+                   uint32_t field_id) override;
 
  private:
   TrackEventTokenizer tokenizer_;
diff --git a/src/trace_processor/vulkan_memory_tracker.cc b/src/trace_processor/importers/proto/vulkan_memory_tracker.cc
similarity index 98%
rename from src/trace_processor/vulkan_memory_tracker.cc
rename to src/trace_processor/importers/proto/vulkan_memory_tracker.cc
index 310f73e..03d1776 100644
--- a/src/trace_processor/vulkan_memory_tracker.cc
+++ b/src/trace_processor/importers/proto/vulkan_memory_tracker.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "src/trace_processor/vulkan_memory_tracker.h"
+#include "src/trace_processor/importers/proto/vulkan_memory_tracker.h"
 
 #include <string>
 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
diff --git a/src/trace_processor/vulkan_memory_tracker.h b/src/trace_processor/importers/proto/vulkan_memory_tracker.h
similarity index 92%
rename from src/trace_processor/vulkan_memory_tracker.h
rename to src/trace_processor/importers/proto/vulkan_memory_tracker.h
index f7cc9b8..f3b8e16 100644
--- a/src/trace_processor/vulkan_memory_tracker.h
+++ b/src/trace_processor/importers/proto/vulkan_memory_tracker.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef SRC_TRACE_PROCESSOR_VULKAN_MEMORY_TRACKER_H_
-#define SRC_TRACE_PROCESSOR_VULKAN_MEMORY_TRACKER_H_
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_VULKAN_MEMORY_TRACKER_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_VULKAN_MEMORY_TRACKER_H_
 
 #include "src/trace_processor/importers/proto/proto_incremental_state.h"
 #include "src/trace_processor/trace_storage.h"
@@ -80,4 +80,4 @@
 }  // namespace trace_processor
 }  // namespace perfetto
 
-#endif  // SRC_TRACE_PROCESSOR_VULKAN_MEMORY_TRACKER_H_
+#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_VULKAN_MEMORY_TRACKER_H_
diff --git a/src/trace_processor/importers/systrace/systrace_parser.cc b/src/trace_processor/importers/systrace/systrace_parser.cc
index 66dc3e7..abdf9b7 100644
--- a/src/trace_processor/importers/systrace/systrace_parser.cc
+++ b/src/trace_processor/importers/systrace/systrace_parser.cc
@@ -77,6 +77,7 @@
 void SystraceParser::ParseSdeTracingMarkWrite(int64_t ts,
                                               uint32_t pid,
                                               char trace_type,
+                                              bool trace_begin,
                                               base::StringView trace_name,
                                               uint32_t tgid,
                                               int64_t value) {
@@ -84,9 +85,12 @@
   point.name = trace_name;
   point.tgid = tgid;
   point.value = value;
-  point.phase = trace_type;
 
-  if (trace_type != 'B' && trace_type != 'E' && trace_type != 'C') {
+  if (trace_type == 0) {
+    point.phase = trace_begin ? 'B' : 'E';
+  } else if (trace_type == 'B' && trace_type == 'E' && trace_type == 'C') {
+    point.phase = trace_type;
+  } else {
     context_->storage->IncrementStats(stats::systrace_parse_failure);
     return;
   }
diff --git a/src/trace_processor/importers/systrace/systrace_parser.h b/src/trace_processor/importers/systrace/systrace_parser.h
index 2dc7ea9..ef39bd3 100644
--- a/src/trace_processor/importers/systrace/systrace_parser.h
+++ b/src/trace_processor/importers/systrace/systrace_parser.h
@@ -196,6 +196,7 @@
   void ParseSdeTracingMarkWrite(int64_t ts,
                                 uint32_t pid,
                                 char trace_type,
+                                bool trace_begin,
                                 base::StringView trace_name,
                                 uint32_t tgid,
                                 int64_t value);
diff --git a/src/trace_processor/metrics/android/process_metadata.sql b/src/trace_processor/metrics/android/process_metadata.sql
index 6630bd2..92b7bfe 100644
--- a/src/trace_processor/metrics/android/process_metadata.sql
+++ b/src/trace_processor/metrics/android/process_metadata.sql
@@ -16,6 +16,13 @@
 
 SELECT RUN_METRIC('android/android_package_list.sql');
 
+-- Create a view of the process with the app ID as defined in
+-- //frameworks/base/core/java/android/os/UserHandle.java
+-- TODO: move this to the trace processor once the table migration is complete.
+CREATE VIEW IF NOT EXISTS proc_uid AS
+SELECT upid, name, uid % 100000 AS uid
+FROM process;
+
 DROP TABLE IF EXISTS uid_package_count;
 
 CREATE TABLE uid_package_count AS
@@ -27,24 +34,24 @@
 
 CREATE TABLE process_metadata_table AS
 SELECT
-  process.upid,
-  process.name AS process_name,
-  process.uid,
+  proc_uid.upid,
+  proc_uid.name AS process_name,
+  proc_uid.uid,
   CASE WHEN uid_package_count.cnt > 1 THEN TRUE ELSE NULL END AS shared_uid,
   plist.package_name,
   plist.version_code,
   plist.debuggable
-FROM process
+FROM proc_uid
 LEFT JOIN uid_package_count USING (uid)
 LEFT JOIN package_list plist
 ON (
-  process.uid = plist.uid
+  proc_uid.uid = plist.uid
   AND uid_package_count.uid = plist.uid
   AND (
     -- unique match
     uid_package_count.cnt = 1
     -- or process name starts with the package name
-    OR process.name LIKE plist.package_name || '%')
+    OR proc_uid.name LIKE plist.package_name || '%')
   );
 
 DROP VIEW IF EXISTS process_metadata;
@@ -58,7 +65,7 @@
     'apk_version_code', package_list.version_code,
     'debuggable', package_list.debuggable
   )) packages_for_uid
-  FROM process
+  FROM proc_uid
   JOIN package_list USING (uid)
   GROUP BY upid
 )
diff --git a/src/trace_processor/metrics/metrics.descriptor.h b/src/trace_processor/metrics/metrics.descriptor.h
index 8dfe867..e5a0eb9 100644
--- a/src/trace_processor/metrics/metrics.descriptor.h
+++ b/src/trace_processor/metrics/metrics.descriptor.h
@@ -25,7 +25,7 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// 0f193cc67cb890463dcc9ce4ab236c0bb16bed98
+// f242f1ac484bbe7ba4c45e77b56ab588f8015196
 // SHA1(protos/perfetto/metrics/metrics.proto)
 // e1fea13f5853cbb276ae800c5fee91c46704565d
 
diff --git a/src/trace_processor/protozero_to_text.cc b/src/trace_processor/protozero_to_text.cc
new file mode 100644
index 0000000..c33abf8
--- /dev/null
+++ b/src/trace_processor/protozero_to_text.cc
@@ -0,0 +1,230 @@
+#include "src/trace_processor/protozero_to_text.h"
+
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/protozero/proto_decoder.h"
+#include "perfetto/protozero/proto_utils.h"
+#include "protos/perfetto/common/descriptor.pbzero.h"
+#include "src/trace_processor/descriptors.h"
+
+// This is the highest level that this protozero to text supports.
+#include "src/trace_processor/importers/proto/track_event.descriptor.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+// Recursively determine the size of all the string like things passed in the
+// parameter pack |rest|.
+size_t SizeOfStr() {
+  return 0;
+}
+template <typename T, typename... Rest>
+size_t SizeOfStr(const T& first, Rest... rest) {
+  return base::StringView(first).size() + SizeOfStr(rest...);
+}
+
+// Append |to_add| which is something string like to |out|.
+template <typename T>
+void StrAppendInternal(std::string* out, const T& to_add) {
+  out->append(to_add);
+}
+
+template <typename T, typename... strings>
+void StrAppendInternal(std::string* out, const T& first, strings... values) {
+  StrAppendInternal(out, first);
+  StrAppendInternal(out, values...);
+}
+
+// Append |to_add| which is something string like to |out|.
+template <typename T>
+void StrAppend(std::string* out, const T& to_add) {
+  out->reserve(out->size() + base::StringView(to_add).size());
+  out->append(to_add);
+}
+
+template <typename T, typename... strings>
+void StrAppend(std::string* out, const T& first, strings... values) {
+  out->reserve(out->size() + SizeOfStr(values...));
+  StrAppendInternal(out, first);
+  StrAppendInternal(out, values...);
+}
+
+void ConvertProtoTypeToFieldAndValueString(const FieldDescriptor& fd,
+                                           const protozero::Field& field,
+                                           const std::string& separator,
+                                           const std::string& indent,
+                                           DescriptorPool* pool,
+                                           std::string* out) {
+  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
+  switch (fd.type()) {
+    case FieldDescriptorProto::TYPE_INT32:
+    case FieldDescriptorProto::TYPE_SFIXED32:
+    case FieldDescriptorProto::TYPE_FIXED32:
+      StrAppend(out, separator, indent, fd.name(), ": ",
+                std::to_string(field.as_int32()));
+      return;
+    case FieldDescriptorProto::TYPE_SINT32:
+      StrAppend(out, separator, indent, fd.name(), ": ",
+                std::to_string(field.as_sint32()));
+      return;
+    case FieldDescriptorProto::TYPE_INT64:
+    case FieldDescriptorProto::TYPE_SFIXED64:
+    case FieldDescriptorProto::TYPE_FIXED64:
+      StrAppend(out, separator, indent, fd.name(), ": ",
+                std::to_string(field.as_int64()));
+      return;
+    case FieldDescriptorProto::TYPE_SINT64:
+      StrAppend(out, separator, indent, fd.name(), ": ",
+                std::to_string(field.as_sint64()));
+      return;
+    case FieldDescriptorProto::TYPE_UINT32:
+      StrAppend(out, separator, indent, fd.name(), ": ",
+                std::to_string(field.as_uint32()));
+      return;
+    case FieldDescriptorProto::TYPE_UINT64:
+      StrAppend(out, separator, indent, fd.name(), ": ",
+                std::to_string(field.as_uint64()));
+      return;
+    case FieldDescriptorProto::TYPE_BOOL:
+      StrAppend(out, separator, indent, fd.name(), ": ",
+                field.as_bool() ? "true" : "false");
+      return;
+    case FieldDescriptorProto::TYPE_DOUBLE:
+      StrAppend(out, separator, indent, fd.name(), ": ",
+                std::to_string(field.as_double()));
+      return;
+    case FieldDescriptorProto::TYPE_FLOAT:
+      StrAppend(out, separator, indent, fd.name(), ": ",
+                std::to_string(field.as_float()));
+      return;
+    case FieldDescriptorProto::TYPE_STRING:
+      StrAppend(out, separator, indent, fd.name(), ": ", field.as_std_string());
+      return;
+    case FieldDescriptorProto::TYPE_ENUM: {
+      auto opt_enum_descriptor_idx =
+          pool->FindDescriptorIdx(fd.resolved_type_name());
+      PERFETTO_DCHECK(opt_enum_descriptor_idx);
+      auto opt_enum_string =
+          pool->descriptors()[*opt_enum_descriptor_idx].FindEnumString(
+              field.as_int32());
+      PERFETTO_DCHECK(opt_enum_string);
+      StrAppend(out, separator, indent, fd.name(), ": ", *opt_enum_string);
+      return;
+    }
+    default: {
+      PERFETTO_FATAL(
+          "Tried to write value of type field %s (in proto type "
+          "%s) which has type enum %d",
+          fd.name().c_str(), fd.resolved_type_name().c_str(), fd.type());
+    }
+  }
+  return;
+}
+
+void IncreaseIndents(std::string* out) {
+  StrAppend(out, "  ");
+}
+
+void DecreaseIndents(std::string* out) {
+  PERFETTO_DCHECK(out->size() >= 2);
+  out->erase(out->size() - 2);
+}
+
+// Recursive case function, Will parse |protobytes| assuming it is a proto of
+// |type| and will use |pool| to look up the |type|. All output will be placed
+// in |output| and between fields |separator| will be placed. When called for
+// |indents| will be increased by 2 spaces to improve readability.
+void ProtozeroToText(const std::string& type,
+                     protozero::ConstBytes protobytes,
+                     bool include_new_lines,
+                     DescriptorPool* pool,
+                     std::string* indents,
+                     std::string* output) {
+  auto opt_proto_descriptor_idx = pool->FindDescriptorIdx(type);
+  PERFETTO_DCHECK(opt_proto_descriptor_idx);
+  auto& proto_descriptor = pool->descriptors()[*opt_proto_descriptor_idx];
+
+  protozero::ProtoDecoder decoder(protobytes.data, protobytes.size);
+  for (auto field = decoder.ReadField(); field.valid();
+       field = decoder.ReadField()) {
+    // Since this is only used in debugging or tests we should always have a
+    // valid compiled in binary descriptor.
+    auto opt_field_descriptor_idx =
+        proto_descriptor.FindFieldIdxByTag(field.id());
+    PERFETTO_DCHECK(opt_field_descriptor_idx);
+    const auto& field_descriptor =
+        proto_descriptor.fields()[*opt_field_descriptor_idx];
+
+    if (field_descriptor.type() ==
+        protos::pbzero::FieldDescriptorProto::TYPE_MESSAGE) {
+      if (include_new_lines) {
+        StrAppend(output, output->empty() ? "" : "\n", *indents,
+                  field_descriptor.name(), ": {");
+        IncreaseIndents(indents);
+      } else {
+        StrAppend(output, output->empty() ? "" : " ", field_descriptor.name(),
+                  ": {");
+      }
+      ProtozeroToText(field_descriptor.resolved_type_name(), field.as_bytes(),
+                      include_new_lines, pool, indents, output);
+      if (include_new_lines) {
+        DecreaseIndents(indents);
+        StrAppend(output, "\n", *indents, "}");
+      } else {
+        StrAppend(output, " }");
+      }
+    } else {
+      ConvertProtoTypeToFieldAndValueString(
+          field_descriptor, field,
+          output->empty() ? "" : include_new_lines ? "\n" : " ", *indents, pool,
+          output);
+    }
+  }
+  PERFETTO_DCHECK(decoder.bytes_left() == 0);
+}
+
+std::string ProtozeroToText(const std::string& type,
+                            protozero::ConstBytes protobytes,
+                            bool include_new_lines) {
+  std::string indent = "";
+  std::string final_result;
+  DescriptorPool pool;
+  auto status = pool.AddFromFileDescriptorSet(kTrackEventDescriptor.data(),
+                                              kTrackEventDescriptor.size());
+  PERFETTO_DCHECK(status.ok());
+  ProtozeroToText(type, protobytes, include_new_lines, &pool, &indent,
+                  &final_result);
+  return final_result;
+}
+}  // namespace
+
+std::string DebugProtozeroToText(const std::string& type,
+                                 protozero::ConstBytes protobytes) {
+  return ProtozeroToText(type, protobytes, /* include_new_lines = */ true);
+}
+std::string ShortDebugProtozeroToText(const std::string& type,
+                                      protozero::ConstBytes protobytes) {
+  return ProtozeroToText(type, protobytes, /* include_new_lines = */ false);
+}
+
+std::string ProtozeroEnumToText(const std::string& type, int32_t enum_value) {
+  DescriptorPool pool;
+  auto status = pool.AddFromFileDescriptorSet(kTrackEventDescriptor.data(),
+                                              kTrackEventDescriptor.size());
+  PERFETTO_DCHECK(status.ok());
+  auto opt_enum_descriptor_idx = pool.FindDescriptorIdx(type);
+  if (!opt_enum_descriptor_idx) {
+    // Fall back to the integer representation of the field.
+    return std::to_string(enum_value);
+  }
+  auto opt_enum_string =
+      pool.descriptors()[*opt_enum_descriptor_idx].FindEnumString(enum_value);
+  if (!opt_enum_string) {
+    // Fall back to the integer representation of the field.
+    return std::to_string(enum_value);
+  }
+  return *opt_enum_string;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/protozero_to_text.h b/src/trace_processor/protozero_to_text.h
new file mode 100644
index 0000000..054434a
--- /dev/null
+++ b/src/trace_processor/protozero_to_text.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 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
+ *
+ *      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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_PROTOZERO_TO_TEXT_H_
+#define SRC_TRACE_PROCESSOR_PROTOZERO_TO_TEXT_H_
+
+#include <string>
+
+#include "perfetto/protozero/field.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// Given a protozero message |protobytes| which is of fully qualified name
+// |type|. We will convert this into a text proto format string.
+//
+// DebugProtozeroToText will use new lines between fields, and
+// ShortDebugProtozeroToText will use only a single space.
+std::string DebugProtozeroToText(const std::string& type,
+                                 protozero::ConstBytes protobytes);
+std::string ShortDebugProtozeroToText(const std::string& type,
+                                      protozero::ConstBytes protobytes);
+
+// Allow the conversion from a protozero enum to a string. The template is just
+// to allow easy enum passing since we will do the explicit cast to a int32_t
+// for the user.
+std::string ProtozeroEnumToText(const std::string& type, int32_t enum_value);
+template <typename Enum>
+std::string ProtozeroEnumToText(const std::string& type, Enum enum_value) {
+  return ProtozeroEnumToText(type, static_cast<int32_t>(enum_value));
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_PROTOZERO_TO_TEXT_H_
diff --git a/src/trace_processor/protozero_to_text_unittests.cc b/src/trace_processor/protozero_to_text_unittests.cc
new file mode 100644
index 0000000..fe795ed
--- /dev/null
+++ b/src/trace_processor/protozero_to_text_unittests.cc
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 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
+ *
+ *      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.
+ */
+
+#include "src/trace_processor/protozero_to_text.h"
+
+#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h"
+#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+constexpr size_t kChunkSize = 42;
+
+using ::testing::_;
+using ::testing::Eq;
+
+TEST(ProtozeroToTextTest, TrackEventBasic) {
+  using perfetto::protos::pbzero::TrackEvent;
+  protozero::HeapBuffered<TrackEvent> msg{kChunkSize, kChunkSize};
+  msg->set_track_uuid(4);
+  msg->set_timestamp_delta_us(3);
+  auto binary_proto = msg.SerializeAsArray();
+  EXPECT_EQ("track_uuid: 4\ntimestamp_delta_us: 3",
+            DebugProtozeroToText(".perfetto.protos.TrackEvent",
+                                 protozero::ConstBytes{binary_proto.data(),
+                                                       binary_proto.size()}));
+  EXPECT_EQ(
+      "track_uuid: 4 timestamp_delta_us: 3",
+      ShortDebugProtozeroToText(
+          ".perfetto.protos.TrackEvent",
+          protozero::ConstBytes{binary_proto.data(), binary_proto.size()}));
+}
+
+TEST(ProtozeroToTextTest, TrackEventNestedMsg) {
+  using perfetto::protos::pbzero::TrackEvent;
+  protozero::HeapBuffered<TrackEvent> msg{kChunkSize, kChunkSize};
+  msg->set_track_uuid(4);
+  auto* state = msg->set_cc_scheduler_state();
+  state->set_deadline_us(7);
+  auto* machine = state->set_state_machine();
+  auto* minor_state = machine->set_minor_state();
+  minor_state->set_commit_count(8);
+  state->set_observing_begin_frame_source(true);
+  msg->set_timestamp_delta_us(3);
+  auto binary_proto = msg.SerializeAsArray();
+
+  EXPECT_EQ(R"(track_uuid: 4
+cc_scheduler_state: {
+  deadline_us: 7
+  state_machine: {
+    minor_state: {
+      commit_count: 8
+    }
+  }
+  observing_begin_frame_source: true
+}
+timestamp_delta_us: 3)",
+            DebugProtozeroToText(".perfetto.protos.TrackEvent",
+                                 protozero::ConstBytes{binary_proto.data(),
+                                                       binary_proto.size()}));
+
+  EXPECT_EQ(
+      "track_uuid: 4 cc_scheduler_state: { deadline_us: 7 state_machine: { "
+      "minor_state: { commit_count: 8 } } observing_begin_frame_source: true } "
+      "timestamp_delta_us: 3",
+      ShortDebugProtozeroToText(
+          ".perfetto.protos.TrackEvent",
+          protozero::ConstBytes{binary_proto.data(), binary_proto.size()}));
+}
+
+TEST(ProtozeroToTextTest, TrackEventEnumNames) {
+  using perfetto::protos::pbzero::TrackEvent;
+  protozero::HeapBuffered<TrackEvent> msg{kChunkSize, kChunkSize};
+  msg->set_type(TrackEvent::TYPE_SLICE_BEGIN);
+  auto binary_proto = msg.SerializeAsArray();
+  EXPECT_EQ("type: TYPE_SLICE_BEGIN",
+            DebugProtozeroToText(".perfetto.protos.TrackEvent",
+                                 protozero::ConstBytes{binary_proto.data(),
+                                                       binary_proto.size()}));
+  EXPECT_EQ("type: TYPE_SLICE_BEGIN",
+            DebugProtozeroToText(".perfetto.protos.TrackEvent",
+                                 protozero::ConstBytes{binary_proto.data(),
+                                                       binary_proto.size()}));
+}
+
+TEST(ProtozeroToTextTest, EnumToString) {
+  using perfetto::protos::pbzero::TrackEvent;
+  EXPECT_EQ("TYPE_SLICE_END",
+            ProtozeroEnumToText(".perfetto.protos.TrackEvent.Type",
+                                TrackEvent::TYPE_SLICE_END));
+}
+}  // namespace
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/register_additional_modules.cc b/src/trace_processor/register_additional_modules.cc
new file mode 100644
index 0000000..cb2b68b
--- /dev/null
+++ b/src/trace_processor/register_additional_modules.cc
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 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
+ *
+ *      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.
+ */
+
+#include "src/trace_processor/register_additional_modules.h"
+#include "src/trace_processor/importers/proto/graphics_event_module.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+void RegisterAdditionalModules(TraceProcessorContext* context) {
+  context->modules.emplace_back(new GraphicsEventModule(context));
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/register_additional_modules.h b/src/trace_processor/register_additional_modules.h
new file mode 100644
index 0000000..3b888d5
--- /dev/null
+++ b/src/trace_processor/register_additional_modules.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 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
+ *
+ *      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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_REGISTER_ADDITIONAL_MODULES_H_
+#define SRC_TRACE_PROCESSOR_REGISTER_ADDITIONAL_MODULES_H_
+
+#include "src/trace_processor/trace_processor_context.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+void RegisterAdditionalModules(TraceProcessorContext*);
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_REGISTER_ADDITIONAL_MODULES_H_
diff --git a/src/trace_processor/sqlite/sqlite_table.cc b/src/trace_processor/sqlite/sqlite_table.cc
index d42e34d..da6f553 100644
--- a/src/trace_processor/sqlite/sqlite_table.cc
+++ b/src/trace_processor/sqlite/sqlite_table.cc
@@ -80,6 +80,8 @@
     return ret;
 
   BestIndexInfo info;
+  info.estimated_cost = idx->estimatedCost;
+  info.estimated_rows = idx->estimatedRows;
   info.sqlite_omit_constraint.resize(qc.constraints().size());
 
   ret = BestIndex(qc, &info);
diff --git a/src/trace_processor/sqlite/sqlite_table.h b/src/trace_processor/sqlite/sqlite_table.h
index a1a831e..a5f95e1 100644
--- a/src/trace_processor/sqlite/sqlite_table.h
+++ b/src/trace_processor/sqlite/sqlite_table.h
@@ -169,9 +169,8 @@
     // Stores the estimated cost of this query.
     double estimated_cost = 0;
 
-    // Estimated row count. The default is set to 25 to match the SQLite
-    // default.
-    uint32_t estimated_rows = 25;
+    // Estimated row count.
+    int64_t estimated_rows = 0;
   };
 
   template <typename Context>
diff --git a/src/trace_processor/storage_columns.h b/src/trace_processor/storage_columns.h
index a10f4ba..20678cd 100644
--- a/src/trace_processor/storage_columns.h
+++ b/src/trace_processor/storage_columns.h
@@ -327,7 +327,7 @@
 class StringVectorAccessor : public Accessor<NullTermStringView> {
  public:
   StringVectorAccessor(const std::deque<Id>* deque,
-                       const std::vector<const char*>* string_map)
+                       const std::vector<NullTermStringView>* string_map)
       : deque_(deque), string_map_(string_map) {}
   ~StringVectorAccessor() override = default;
 
@@ -336,13 +336,12 @@
   }
 
   NullTermStringView Get(uint32_t idx) const override {
-    const char* ptr = (*string_map_)[static_cast<size_t>((*deque_)[idx])];
-    return ptr ? NullTermStringView(ptr) : NullTermStringView();
+    return (*string_map_)[static_cast<size_t>((*deque_)[idx])];
   }
 
  private:
   const std::deque<Id>* deque_;
-  const std::vector<const char*>* string_map_;
+  const std::vector<NullTermStringView>* string_map_;
 };
 
 // An accessor implementation for numeric columns which uses a deque as the
diff --git a/src/trace_processor/storage_schema.h b/src/trace_processor/storage_schema.h
index fe7955c..db032bc 100644
--- a/src/trace_processor/storage_schema.h
+++ b/src/trace_processor/storage_schema.h
@@ -76,9 +76,10 @@
     }
 
     template <class Id>
-    Builder& AddStringColumn(std::string column_name,
-                             const std::deque<Id>* ids,
-                             const std::vector<const char*>* string_map) {
+    Builder& AddStringColumn(
+        std::string column_name,
+        const std::deque<Id>* ids,
+        const std::vector<NullTermStringView>* string_map) {
       StringVectorAccessor<Id> accessor(ids, string_map);
       columns_.emplace_back(
           new StringColumn<decltype(accessor)>(column_name, accessor));
diff --git a/src/trace_processor/tables/macros_benchmark.cc b/src/trace_processor/tables/macros_benchmark.cc
index 2a466f1..008bcab 100644
--- a/src/trace_processor/tables/macros_benchmark.cc
+++ b/src/trace_processor/tables/macros_benchmark.cc
@@ -320,6 +320,25 @@
 }
 BENCHMARK(BM_TableFilterChildSortedEqInParent)->Apply(TableFilterArgs);
 
+static void BM_TableFilterIdAndOtherParent(benchmark::State& state) {
+  StringPool pool;
+  RootTestTable root(&pool, nullptr);
+
+  uint32_t size = static_cast<uint32_t>(state.range(0));
+
+  for (uint32_t i = 0; i < size; ++i) {
+    RootTestTable::Row root_row;
+    root_row.root_non_null = i * 4;
+    root.Insert(root_row);
+  }
+
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(root.Filter(
+        {root.id().eq(root.size() - 1), root.root_non_null().gt(100)}));
+  }
+}
+BENCHMARK(BM_TableFilterIdAndOtherParent)->Apply(TableFilterArgs);
+
 static void BM_TableSortRootNonNull(benchmark::State& state) {
   StringPool pool;
   RootTestTable root(&pool, nullptr);
diff --git a/src/trace_processor/tables/macros_unittest.cc b/src/trace_processor/tables/macros_unittest.cc
index e1e06b8..46e03da 100644
--- a/src/trace_processor/tables/macros_unittest.cc
+++ b/src/trace_processor/tables/macros_unittest.cc
@@ -189,6 +189,42 @@
   ASSERT_EQ(dur->Get(1).long_value, 200);
 }
 
+TEST_F(TableMacrosUnittest, NullableLongCompareWithDouble) {
+  slice_.Insert({});
+
+  TestSliceTable::Row row;
+  row.dur = 100;
+  slice_.Insert(row);
+
+  row.dur = std::numeric_limits<int64_t>::max();
+  slice_.Insert(row);
+
+  row.dur = std::numeric_limits<int64_t>::min();
+  slice_.Insert(row);
+
+  Table out = slice_.Filter({slice_.dur().eq_value(SqlValue::Double(100.0))});
+  const Column* dur = out.GetColumnByName("dur");
+  ASSERT_EQ(out.size(), 1u);
+  ASSERT_EQ(dur->Get(0).long_value, 100);
+
+  out = slice_.Filter({slice_.dur().le_value(SqlValue::Double(99.9999))});
+  dur = out.GetColumnByName("dur");
+  ASSERT_EQ(out.size(), 1u);
+  ASSERT_EQ(dur->Get(0).long_value, std::numeric_limits<int64_t>::min());
+
+  out = slice_.Filter({slice_.dur().ge_value(SqlValue::Double(99.9999))});
+  dur = out.GetColumnByName("dur");
+  ASSERT_EQ(out.size(), 2u);
+  ASSERT_EQ(dur->Get(0).long_value, 100);
+  ASSERT_EQ(dur->Get(1).long_value, std::numeric_limits<int64_t>::max());
+
+  out = slice_.Filter({slice_.dur().eq_value(
+      SqlValue::Double(std::numeric_limits<int64_t>::min()))});
+  dur = out.GetColumnByName("dur");
+  ASSERT_EQ(out.size(), 1u);
+  ASSERT_EQ(dur->Get(0).long_value, std::numeric_limits<int64_t>::min());
+}
+
 TEST_F(TableMacrosUnittest, NullableLongCompareWrongType) {
   slice_.Insert({});
 
@@ -209,9 +245,101 @@
 
   out = slice_.Filter({slice_.dur().eq_value(SqlValue::String("100"))});
   ASSERT_EQ(out.size(), 0u);
+}
 
-  out = slice_.Filter({slice_.dur().eq_value(SqlValue::Double(100.0))});
-  ASSERT_EQ(out.size(), 0u);
+TEST_F(TableMacrosUnittest, NullableDoubleComparision) {
+  counter_.Insert({});
+
+  TestCounterTable::Row row;
+  row.value = 100.0;
+  counter_.Insert(row);
+
+  row.value = 101.0;
+  counter_.Insert(row);
+
+  row.value = 200.0;
+  counter_.Insert(row);
+
+  counter_.Insert({});
+
+  Table out = counter_.Filter({counter_.value().is_null()});
+  const auto* value = out.GetColumnByName("value");
+  ASSERT_EQ(out.size(), 2u);
+  ASSERT_EQ(value->Get(0).type, SqlValue::kNull);
+  ASSERT_EQ(value->Get(1).type, SqlValue::kNull);
+
+  out = counter_.Filter({counter_.value().is_not_null()});
+  value = out.GetColumnByName("value");
+  ASSERT_EQ(out.size(), 3u);
+  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
+  ASSERT_DOUBLE_EQ(value->Get(1).double_value, 101);
+  ASSERT_DOUBLE_EQ(value->Get(2).double_value, 200);
+
+  out = counter_.Filter({counter_.value().lt(101)});
+  value = out.GetColumnByName("value");
+  ASSERT_EQ(out.size(), 1u);
+  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
+
+  out = counter_.Filter({counter_.value().eq(101)});
+  value = out.GetColumnByName("value");
+  ASSERT_EQ(out.size(), 1u);
+  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
+
+  out = counter_.Filter({counter_.value().gt(101)});
+  value = out.GetColumnByName("value");
+  ASSERT_EQ(out.size(), 1u);
+  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 200);
+
+  out = counter_.Filter({counter_.value().ne(100)});
+  value = out.GetColumnByName("value");
+  ASSERT_EQ(out.size(), 2u);
+  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
+  ASSERT_DOUBLE_EQ(value->Get(1).double_value, 200);
+
+  out = counter_.Filter({counter_.value().le(101)});
+  value = out.GetColumnByName("value");
+  ASSERT_EQ(out.size(), 2u);
+  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
+  ASSERT_DOUBLE_EQ(value->Get(1).double_value, 101);
+
+  out = counter_.Filter({counter_.value().ge(101)});
+  value = out.GetColumnByName("value");
+  ASSERT_EQ(out.size(), 2u);
+  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
+  ASSERT_DOUBLE_EQ(value->Get(1).double_value, 200);
+}
+
+TEST_F(TableMacrosUnittest, NullableDoubleCompareWithLong) {
+  counter_.Insert({});
+
+  TestCounterTable::Row row;
+  row.value = 100.0;
+  counter_.Insert(row);
+
+  row.value = 99.9999;
+  counter_.Insert(row);
+
+  row.value = std::numeric_limits<int64_t>::min();
+  counter_.Insert(row);
+
+  Table out = counter_.Filter({counter_.value().eq_value(SqlValue::Long(100))});
+  const Column* value = out.GetColumnByName("value");
+  ASSERT_EQ(out.size(), 1u);
+  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100.0);
+
+  out = counter_.Filter({counter_.value().lt_value(SqlValue::Long(100))});
+  value = out.GetColumnByName("value");
+  ASSERT_EQ(out.size(), 2u);
+  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 99.9999);
+  ASSERT_DOUBLE_EQ(value->Get(1).double_value,
+                   std::numeric_limits<int64_t>::min());
+
+  out = counter_.Filter({counter_.value().eq_value(
+      SqlValue::Long(std::numeric_limits<int64_t>::min()))});
+  value = out.GetColumnByName("value");
+  ASSERT_EQ(out.size(), 1u);
+  ASSERT_DOUBLE_EQ(value->Get(0).double_value,
+                   std::numeric_limits<int64_t>::min());
 }
 
 TEST_F(TableMacrosUnittest, StringComparision) {
@@ -291,68 +419,6 @@
   ASSERT_STREQ(end_state->Get(0).string_value, "D");
 }
 
-TEST_F(TableMacrosUnittest, NullableDoubleComparision) {
-  counter_.Insert({});
-
-  TestCounterTable::Row row;
-  row.value = 100.0;
-  counter_.Insert(row);
-
-  row.value = 101.0;
-  counter_.Insert(row);
-
-  row.value = 200.0;
-  counter_.Insert(row);
-
-  counter_.Insert({});
-
-  Table out = counter_.Filter({counter_.value().is_null()});
-  const auto* value = out.GetColumnByName("value");
-  ASSERT_EQ(out.size(), 2u);
-  ASSERT_EQ(value->Get(0).type, SqlValue::kNull);
-  ASSERT_EQ(value->Get(1).type, SqlValue::kNull);
-
-  out = counter_.Filter({counter_.value().is_not_null()});
-  value = out.GetColumnByName("value");
-  ASSERT_EQ(out.size(), 3u);
-  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
-  ASSERT_DOUBLE_EQ(value->Get(1).double_value, 101);
-  ASSERT_DOUBLE_EQ(value->Get(2).double_value, 200);
-
-  out = counter_.Filter({counter_.value().lt(101)});
-  value = out.GetColumnByName("value");
-  ASSERT_EQ(out.size(), 1u);
-  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
-
-  out = counter_.Filter({counter_.value().eq(101)});
-  value = out.GetColumnByName("value");
-  ASSERT_EQ(out.size(), 1u);
-  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
-
-  out = counter_.Filter({counter_.value().gt(101)});
-  value = out.GetColumnByName("value");
-  ASSERT_EQ(out.size(), 1u);
-  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 200);
-
-  out = counter_.Filter({counter_.value().ne(100)});
-  value = out.GetColumnByName("value");
-  ASSERT_EQ(out.size(), 2u);
-  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
-  ASSERT_DOUBLE_EQ(value->Get(1).double_value, 200);
-
-  out = counter_.Filter({counter_.value().le(101)});
-  value = out.GetColumnByName("value");
-  ASSERT_EQ(out.size(), 2u);
-  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
-  ASSERT_DOUBLE_EQ(value->Get(1).double_value, 101);
-
-  out = counter_.Filter({counter_.value().ge(101)});
-  value = out.GetColumnByName("value");
-  ASSERT_EQ(out.size(), 2u);
-  ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
-  ASSERT_DOUBLE_EQ(value->Get(1).double_value, 200);
-}
-
 TEST_F(TableMacrosUnittest, Sort) {
   ASSERT_TRUE(event_.ts().IsSorted());
 
diff --git a/src/trace_processor/tables/track_tables.h b/src/trace_processor/tables/track_tables.h
index 403b520..9147b0a 100644
--- a/src/trace_processor/tables/track_tables.h
+++ b/src/trace_processor/tables/track_tables.h
@@ -50,6 +50,7 @@
   NAME(GpuTrackTable, "gpu_track")                 \
   PARENT(PERFETTO_TP_TRACK_TABLE_DEF, C)           \
   C(StringPool::Id, scope)                         \
+  C(StringPool::Id, description)                   \
   C(base::Optional<int64_t>, context_id)
 
 PERFETTO_TP_TABLE(PERFETTO_TP_GPU_TRACK_DEF);
diff --git a/src/trace_processor/trace_processor_context.cc b/src/trace_processor/trace_processor_context.cc
index 6576e6d..a6b1c03 100644
--- a/src/trace_processor/trace_processor_context.cc
+++ b/src/trace_processor/trace_processor_context.cc
@@ -26,7 +26,6 @@
 #include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
 #include "src/trace_processor/importers/json/json_trace_parser.h"
 #include "src/trace_processor/importers/proto/android_probes_module.h"
-#include "src/trace_processor/importers/proto/graphics_event_module.h"
 #include "src/trace_processor/importers/proto/heap_graph_module.h"
 #include "src/trace_processor/importers/proto/heap_graph_tracker.h"
 #include "src/trace_processor/importers/proto/proto_trace_parser.h"
@@ -39,7 +38,6 @@
 #include "src/trace_processor/syscall_tracker.h"
 #include "src/trace_processor/trace_sorter.h"
 #include "src/trace_processor/track_tracker.h"
-#include "src/trace_processor/vulkan_memory_tracker.h"
 
 namespace perfetto {
 namespace trace_processor {
diff --git a/src/trace_processor/trace_processor_context.h b/src/trace_processor/trace_processor_context.h
index 784b130..3eab980 100644
--- a/src/trace_processor/trace_processor_context.h
+++ b/src/trace_processor/trace_processor_context.h
@@ -26,29 +26,23 @@
 namespace perfetto {
 namespace trace_processor {
 
-class AndroidProbesModule;
 class ArgsTracker;
 class BinderTracker;
 class ChunkedTraceReader;
 class ClockTracker;
 class EventTracker;
 class FtraceModule;
-class GraphicsEventModule;
-class HeapGraphModule;
 class HeapGraphTracker;
 class HeapProfileTracker;
 class ProcessTracker;
 class SchedEventTracker;
 class SliceTracker;
 class SyscallTracker;
-class SystemProbesModule;
 class SystraceParser;
 class TraceParser;
 class TraceSorter;
 class TraceStorage;
-class TrackEventModule;
 class TrackTracker;
-class VulkanMemoryTracker;
 
 class TraceProcessorContext {
  public:
@@ -72,20 +66,13 @@
   std::unique_ptr<HeapProfileTracker> heap_profile_tracker;
   std::unique_ptr<SystraceParser> systrace_parser;
   std::unique_ptr<HeapGraphTracker> heap_graph_tracker;
-  std::unique_ptr<VulkanMemoryTracker> vulkan_memory_tracker;
   std::unique_ptr<BinderTracker> binder_tracker;
 
-  std::unique_ptr<ProtoImporterModule<FtraceModule>> ftrace_module;
-  std::unique_ptr<ProtoImporterModule<TrackEventModule>> track_event_module;
-  std::unique_ptr<ProtoImporterModule<SystemProbesModule>> system_probes_module;
-  std::unique_ptr<ProtoImporterModule<AndroidProbesModule>>
-      android_probes_module;
-  std::unique_ptr<ProtoImporterModule<HeapGraphModule>> heap_graph_module;
-
   // The module at the index N is registered to handle field id N in
   // TracePacket.
-  std::vector<NewProtoImporterModule*> modules_by_field;
-  std::vector<std::unique_ptr<NewProtoImporterModule>> modules;
+  std::vector<ProtoImporterModule*> modules_by_field;
+  std::vector<std::unique_ptr<ProtoImporterModule>> modules;
+  FtraceModule* ftrace_module;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index c1b3873..b0fe758 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -31,6 +31,7 @@
 #include "src/trace_processor/metadata_table.h"
 #include "src/trace_processor/process_table.h"
 #include "src/trace_processor/raw_table.h"
+#include "src/trace_processor/register_additional_modules.h"
 #include "src/trace_processor/sched_slice_table.h"
 #include "src/trace_processor/span_join_operator_table.h"
 #include "src/trace_processor/sql_stats_table.h"
@@ -349,11 +350,11 @@
   }
 }
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
-
 }  // namespace
 
 TraceProcessorImpl::TraceProcessorImpl(const Config& cfg)
     : TraceProcessorStorageImpl(cfg) {
+  RegisterAdditionalModules(&context_);
   sqlite3* db = nullptr;
   PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
   PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc
index da5521b..2ceb370 100644
--- a/src/trace_processor/trace_processor_storage_impl.cc
+++ b/src/trace_processor/trace_processor_storage_impl.cc
@@ -26,7 +26,6 @@
 #include "src/trace_processor/importers/ftrace/ftrace_module.h"
 #include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
 #include "src/trace_processor/importers/proto/android_probes_module.h"
-#include "src/trace_processor/importers/proto/graphics_event_module.h"
 #include "src/trace_processor/importers/proto/heap_graph_module.h"
 #include "src/trace_processor/importers/proto/heap_graph_tracker.h"
 #include "src/trace_processor/importers/proto/proto_importer_module.h"
@@ -42,7 +41,6 @@
 #include "src/trace_processor/trace_blob_view.h"
 #include "src/trace_processor/trace_sorter.h"
 #include "src/trace_processor/track_tracker.h"
-#include "src/trace_processor/vulkan_memory_tracker.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -65,23 +63,27 @@
   context_.systrace_parser.reset(new SystraceParser(&context_));
   context_.binder_tracker.reset(new BinderTracker(&context_));
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
-  context_.vulkan_memory_tracker.reset(new VulkanMemoryTracker(&context_));
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
-  context_.ftrace_module.reset(
-      new ProtoImporterModule<FtraceModule>(&context_));
-  context_.track_event_module.reset(
-      new ProtoImporterModule<TrackEventModule>(&context_));
-  context_.system_probes_module.reset(
-      new ProtoImporterModule<SystemProbesModule>(&context_));
-  context_.android_probes_module.reset(
-      new ProtoImporterModule<AndroidProbesModule>(&context_));
-  context_.heap_graph_module.reset(
-      new ProtoImporterModule<HeapGraphModule>(&context_));
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
-  context_.modules.emplace_back(new GraphicsEventModule(&context_));
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
+#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
+  context_.modules.emplace_back(new FtraceModuleImpl(&context_));
+#else
+  context_.modules.emplace_back(new FtraceModule());
+#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
+  // Ftrace module is special, because it has one extra method for parsing
+  // ftrace packets. So we need to store a pointer to it separately.
+  context_.ftrace_module =
+      static_cast<FtraceModule*>(context_.modules.back().get());
+
+#if PERFETTO_BUILDFLAG(PERFETTO_TP_HEAP_GRAPHS)
+  context_.modules.emplace_back(new HeapGraphModule(&context_));
+#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_HEAP_GRAPHS)
+#if PERFETTO_BUILDFLAG(PERFETTO_TP_ANDROID_PROBES)
+  context_.modules.emplace_back(new AndroidProbesModule(&context_));
+#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_ANDROID_PROBES)
+#if PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
+  context_.modules.emplace_back(new SystemProbesModule(&context_));
+#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
+  context_.modules.emplace_back(new TrackEventModule(&context_));
 }
 
 TraceProcessorStorageImpl::~TraceProcessorStorageImpl() {}
diff --git a/src/trace_processor/trace_storage.cc b/src/trace_processor/trace_storage.cc
index 65afab8..2f4e872 100644
--- a/src/trace_processor/trace_storage.cc
+++ b/src/trace_processor/trace_storage.cc
@@ -51,9 +51,9 @@
   *max_value = std::max(*max_value, column[column.row_map().size() - 1]);
 }
 
-std::vector<const char*> CreateRefTypeStringMap() {
-  std::vector<const char*> map(static_cast<size_t>(RefType::kRefMax));
-  map[static_cast<size_t>(RefType::kRefNoRef)] = nullptr;
+std::vector<NullTermStringView> CreateRefTypeStringMap() {
+  std::vector<NullTermStringView> map(static_cast<size_t>(RefType::kRefMax));
+  map[static_cast<size_t>(RefType::kRefNoRef)] = NullTermStringView();
   map[static_cast<size_t>(RefType::kRefUtid)] = "utid";
   map[static_cast<size_t>(RefType::kRefCpuId)] = "cpu";
   map[static_cast<size_t>(RefType::kRefGpuId)] = "gpu";
@@ -66,8 +66,8 @@
 
 }  // namespace
 
-const std::vector<const char*>& GetRefTypeStringMap() {
-  static const base::NoDestructor<std::vector<const char*>> map(
+const std::vector<NullTermStringView>& GetRefTypeStringMap() {
+  static const base::NoDestructor<std::vector<NullTermStringView>> map(
       CreateRefTypeStringMap());
   return map.ref();
 }
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 0cb7cc0..56c92a0 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -98,7 +98,7 @@
   kRefMax
 };
 
-const std::vector<const char*>& GetRefTypeStringMap();
+const std::vector<NullTermStringView>& GetRefTypeStringMap();
 
 // Stores a data inside a trace file in a columnar form. This makes it efficient
 // to read or search across a single field of the trace (e.g. all the thread
diff --git a/src/traced/probes/android_log/BUILD.gn b/src/traced/probes/android_log/BUILD.gn
index eac5fd3..cc25cd4 100644
--- a/src/traced/probes/android_log/BUILD.gn
+++ b/src/traced/probes/android_log/BUILD.gn
@@ -39,8 +39,9 @@
     ":android_log",
     "../../../../gn:default_deps",
     "../../../../gn:gtest_and_gmock",
-    "../../../../protos/perfetto/common:zero",
-    "../../../../protos/perfetto/config/android:zero",
+    "../../../../protos/perfetto/common:cpp",
+    "../../../../protos/perfetto/config/android:cpp",
+    "../../../../protos/perfetto/trace/android:cpp",
     "../../../../src/base:test_support",
     "../../../../src/tracing:test_support",
   ]
diff --git a/src/traced/probes/android_log/android_log_data_source_unittest.cc b/src/traced/probes/android_log/android_log_data_source_unittest.cc
index 1c90204..c7753f1 100644
--- a/src/traced/probes/android_log/android_log_data_source_unittest.cc
+++ b/src/traced/probes/android_log/android_log_data_source_unittest.cc
@@ -16,16 +16,17 @@
 
 #include "src/traced/probes/android_log/android_log_data_source.h"
 
-#include "perfetto/protozero/scattered_heap_buffer.h"
 #include "perfetto/tracing/core/data_source_config.h"
-#include "protos/perfetto/common/android_log_constants.pbzero.h"
-#include "protos/perfetto/config/android/android_log_config.pbzero.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/tracing/core/trace_writer_for_testing.h"
 #include "test/gtest_and_gmock.h"
 
-using ::perfetto::protos::pbzero::AndroidLogConfig;
-using ::perfetto::protos::pbzero::AndroidLogId;
+#include "protos/perfetto/common/android_log_constants.gen.h"
+#include "protos/perfetto/config/android/android_log_config.gen.h"
+#include "protos/perfetto/trace/android/android_log.gen.h"
+
+using ::perfetto::protos::gen::AndroidLogConfig;
+using ::perfetto::protos::gen::AndroidLogId;
 using ::testing::Invoke;
 using ::testing::Return;
 
@@ -221,44 +222,43 @@
   EXPECT_EQ(event_packet.android_log().events_size(), 3);
   const auto& decoded = event_packet.android_log().events();
 
-  EXPECT_EQ(decoded.Get(0).log_id(), protos::AndroidLogId::LID_SYSTEM);
-  EXPECT_EQ(decoded.Get(0).pid(), 7546);
-  EXPECT_EQ(decoded.Get(0).tid(), 8991);
-  EXPECT_EQ(decoded.Get(0).uid(), 1000);
-  EXPECT_EQ(decoded.Get(0).prio(), protos::AndroidLogPriority::PRIO_INFO);
-  EXPECT_EQ(decoded.Get(0).timestamp(), 1546125239679172326ULL);
-  EXPECT_EQ(decoded.Get(0).tag(), "ActivityManager");
+  EXPECT_EQ(decoded[0].log_id(), protos::gen::AndroidLogId::LID_SYSTEM);
+  EXPECT_EQ(decoded[0].pid(), 7546);
+  EXPECT_EQ(decoded[0].tid(), 8991);
+  EXPECT_EQ(decoded[0].uid(), 1000);
+  EXPECT_EQ(decoded[0].prio(), protos::gen::AndroidLogPriority::PRIO_INFO);
+  EXPECT_EQ(decoded[0].timestamp(), 1546125239679172326ULL);
+  EXPECT_EQ(decoded[0].tag(), "ActivityManager");
   EXPECT_EQ(
-      decoded.Get(0).message(),
+      decoded[0].message(),
       "Killing 11660:com.google.android.videos/u0a168 (adj 985): empty #17");
 
-  EXPECT_EQ(decoded.Get(1).log_id(), protos::AndroidLogId::LID_DEFAULT);
-  EXPECT_EQ(decoded.Get(1).pid(), 7546);
-  EXPECT_EQ(decoded.Get(1).tid(), 7570);
-  EXPECT_EQ(decoded.Get(1).uid(), 1000);
-  EXPECT_EQ(decoded.Get(1).prio(), protos::AndroidLogPriority::PRIO_WARN);
-  EXPECT_EQ(decoded.Get(1).timestamp(), 1546125239683537170ULL);
-  EXPECT_EQ(decoded.Get(1).tag(), "libprocessgroup");
-  EXPECT_EQ(decoded.Get(1).message(),
-            "kill(-11660, 9) failed: No such process");
+  EXPECT_EQ(decoded[1].log_id(), protos::gen::AndroidLogId::LID_DEFAULT);
+  EXPECT_EQ(decoded[1].pid(), 7546);
+  EXPECT_EQ(decoded[1].tid(), 7570);
+  EXPECT_EQ(decoded[1].uid(), 1000);
+  EXPECT_EQ(decoded[1].prio(), protos::gen::AndroidLogPriority::PRIO_WARN);
+  EXPECT_EQ(decoded[1].timestamp(), 1546125239683537170ULL);
+  EXPECT_EQ(decoded[1].tag(), "libprocessgroup");
+  EXPECT_EQ(decoded[1].message(), "kill(-11660, 9) failed: No such process");
 
-  EXPECT_EQ(decoded.Get(2).log_id(), protos::AndroidLogId::LID_DEFAULT);
-  EXPECT_EQ(decoded.Get(2).pid(), 7415);
-  EXPECT_EQ(decoded.Get(2).tid(), 7415);
-  EXPECT_EQ(decoded.Get(2).uid(), 0);
-  EXPECT_EQ(decoded.Get(2).prio(), protos::AndroidLogPriority::PRIO_INFO);
-  EXPECT_EQ(decoded.Get(2).timestamp(), 1546125239719458684ULL);
-  EXPECT_EQ(decoded.Get(2).tag(), "Zygote");
-  EXPECT_EQ(decoded.Get(2).message(), "Process 11660 exited due to signal (9)");
+  EXPECT_EQ(decoded[2].log_id(), protos::gen::AndroidLogId::LID_DEFAULT);
+  EXPECT_EQ(decoded[2].pid(), 7415);
+  EXPECT_EQ(decoded[2].tid(), 7415);
+  EXPECT_EQ(decoded[2].uid(), 0);
+  EXPECT_EQ(decoded[2].prio(), protos::gen::AndroidLogPriority::PRIO_INFO);
+  EXPECT_EQ(decoded[2].timestamp(), 1546125239719458684ULL);
+  EXPECT_EQ(decoded[2].tag(), "Zygote");
+  EXPECT_EQ(decoded[2].message(), "Process 11660 exited due to signal (9)");
 }
 
 TEST_F(AndroidLogDataSourceTest, TextEventsWithTagFiltering) {
   DataSourceConfig cfg;
-  protozero::HeapBuffered<AndroidLogConfig> acfg;
-  acfg->add_filter_tags("Zygote");
-  acfg->add_filter_tags("ActivityManager");
-  acfg->add_filter_tags("Unmatched");
-  acfg->add_filter_tags("libprocessgroupZZ");
+  AndroidLogConfig acfg;
+  acfg.add_filter_tags("Zygote");
+  acfg.add_filter_tags("ActivityManager");
+  acfg.add_filter_tags("Unmatched");
+  acfg.add_filter_tags("libprocessgroupZZ");
   cfg.set_android_log_config_raw(acfg.SerializeAsString());
 
   CreateInstance(cfg);
@@ -273,14 +273,14 @@
 
   EXPECT_EQ(event_packet.android_log().events_size(), 2);
   const auto& decoded = event_packet.android_log().events();
-  EXPECT_EQ(decoded.Get(0).tag(), "ActivityManager");
-  EXPECT_EQ(decoded.Get(1).tag(), "Zygote");
+  EXPECT_EQ(decoded[0].tag(), "ActivityManager");
+  EXPECT_EQ(decoded[1].tag(), "Zygote");
 }
 
 TEST_F(AndroidLogDataSourceTest, TextEventsWithPrioFiltering) {
   DataSourceConfig cfg;
-  protozero::HeapBuffered<AndroidLogConfig> acfg;
-  acfg->set_min_prio(protos::pbzero::AndroidLogPriority::PRIO_WARN);
+  AndroidLogConfig acfg;
+  acfg.set_min_prio(protos::gen::AndroidLogPriority::PRIO_WARN);
   cfg.set_android_log_config_raw(acfg.SerializeAsString());
 
   CreateInstance(cfg);
@@ -295,7 +295,7 @@
 
   EXPECT_EQ(event_packet.android_log().events_size(), 1);
   const auto& decoded = event_packet.android_log().events();
-  EXPECT_EQ(decoded.Get(0).tag(), "libprocessgroup");
+  EXPECT_EQ(decoded[0].tag(), "libprocessgroup");
 }
 
 TEST_F(AndroidLogDataSourceTest, BinaryEvents) {
@@ -320,69 +320,69 @@
   EXPECT_EQ(event_packet.android_log().events_size(), 3);
   const auto& decoded = event_packet.android_log().events();
 
-  EXPECT_EQ(decoded.Get(0).log_id(), protos::AndroidLogId::LID_EVENTS);
-  EXPECT_EQ(decoded.Get(0).pid(), 29981);
-  EXPECT_EQ(decoded.Get(0).tid(), 30962);
-  EXPECT_EQ(decoded.Get(0).uid(), 1000);
-  EXPECT_EQ(decoded.Get(0).timestamp(), 1546165328914257883ULL);
-  EXPECT_EQ(decoded.Get(0).tag(), "am_kill");
-  ASSERT_EQ(decoded.Get(0).args_size(), 5);
-  EXPECT_EQ(decoded.Get(0).args(0).name(), "User");
-  EXPECT_EQ(decoded.Get(0).args(0).int_value(), 0);
-  EXPECT_EQ(decoded.Get(0).args(1).name(), "PID");
-  EXPECT_EQ(decoded.Get(0).args(1).int_value(), 31730);
-  EXPECT_EQ(decoded.Get(0).args(2).name(), "Process Name");
-  EXPECT_EQ(decoded.Get(0).args(2).string_value(), "android.process.acore");
-  EXPECT_EQ(decoded.Get(0).args(3).name(), "OomAdj");
-  EXPECT_EQ(decoded.Get(0).args(3).int_value(), 985);
-  EXPECT_EQ(decoded.Get(0).args(4).name(), "Reason");
-  EXPECT_EQ(decoded.Get(0).args(4).string_value(), "empty #17");
+  EXPECT_EQ(decoded[0].log_id(), protos::gen::AndroidLogId::LID_EVENTS);
+  EXPECT_EQ(decoded[0].pid(), 29981);
+  EXPECT_EQ(decoded[0].tid(), 30962);
+  EXPECT_EQ(decoded[0].uid(), 1000);
+  EXPECT_EQ(decoded[0].timestamp(), 1546165328914257883ULL);
+  EXPECT_EQ(decoded[0].tag(), "am_kill");
+  ASSERT_EQ(decoded[0].args_size(), 5);
+  EXPECT_EQ(decoded[0].args()[0].name(), "User");
+  EXPECT_EQ(decoded[0].args()[0].int_value(), 0);
+  EXPECT_EQ(decoded[0].args()[1].name(), "PID");
+  EXPECT_EQ(decoded[0].args()[1].int_value(), 31730);
+  EXPECT_EQ(decoded[0].args()[2].name(), "Process Name");
+  EXPECT_EQ(decoded[0].args()[2].string_value(), "android.process.acore");
+  EXPECT_EQ(decoded[0].args()[3].name(), "OomAdj");
+  EXPECT_EQ(decoded[0].args()[3].int_value(), 985);
+  EXPECT_EQ(decoded[0].args()[4].name(), "Reason");
+  EXPECT_EQ(decoded[0].args()[4].string_value(), "empty #17");
 
-  EXPECT_EQ(decoded.Get(1).log_id(), protos::AndroidLogId::LID_EVENTS);
-  EXPECT_EQ(decoded.Get(1).pid(), 29981);
-  EXPECT_EQ(decoded.Get(1).tid(), 30962);
-  EXPECT_EQ(decoded.Get(1).uid(), 1000);
-  EXPECT_EQ(decoded.Get(1).timestamp(), 1546165328946231844ULL);
-  EXPECT_EQ(decoded.Get(1).tag(), "am_uid_stopped");
-  ASSERT_EQ(decoded.Get(1).args_size(), 1);
-  EXPECT_EQ(decoded.Get(1).args(0).name(), "UID");
-  EXPECT_EQ(decoded.Get(1).args(0).int_value(), 10018);
+  EXPECT_EQ(decoded[1].log_id(), protos::gen::AndroidLogId::LID_EVENTS);
+  EXPECT_EQ(decoded[1].pid(), 29981);
+  EXPECT_EQ(decoded[1].tid(), 30962);
+  EXPECT_EQ(decoded[1].uid(), 1000);
+  EXPECT_EQ(decoded[1].timestamp(), 1546165328946231844ULL);
+  EXPECT_EQ(decoded[1].tag(), "am_uid_stopped");
+  ASSERT_EQ(decoded[1].args_size(), 1);
+  EXPECT_EQ(decoded[1].args()[0].name(), "UID");
+  EXPECT_EQ(decoded[1].args()[0].int_value(), 10018);
 
-  EXPECT_EQ(decoded.Get(2).log_id(), protos::AndroidLogId::LID_EVENTS);
-  EXPECT_EQ(decoded.Get(2).pid(), 29981);
-  EXPECT_EQ(decoded.Get(2).tid(), 29998);
-  EXPECT_EQ(decoded.Get(2).uid(), 1000);
-  EXPECT_EQ(decoded.Get(2).timestamp(), 1546165328960813044ULL);
-  EXPECT_EQ(decoded.Get(2).tag(), "am_pss");
-  ASSERT_EQ(decoded.Get(2).args_size(), 10);
-  EXPECT_EQ(decoded.Get(2).args(0).name(), "Pid");
-  EXPECT_EQ(decoded.Get(2).args(0).int_value(), 1417);
-  EXPECT_EQ(decoded.Get(2).args(1).name(), "UID");
-  EXPECT_EQ(decoded.Get(2).args(1).int_value(), 10098);
-  EXPECT_EQ(decoded.Get(2).args(2).name(), "Process Name");
-  EXPECT_EQ(decoded.Get(2).args(2).string_value(),
+  EXPECT_EQ(decoded[2].log_id(), protos::gen::AndroidLogId::LID_EVENTS);
+  EXPECT_EQ(decoded[2].pid(), 29981);
+  EXPECT_EQ(decoded[2].tid(), 29998);
+  EXPECT_EQ(decoded[2].uid(), 1000);
+  EXPECT_EQ(decoded[2].timestamp(), 1546165328960813044ULL);
+  EXPECT_EQ(decoded[2].tag(), "am_pss");
+  ASSERT_EQ(decoded[2].args_size(), 10);
+  EXPECT_EQ(decoded[2].args()[0].name(), "Pid");
+  EXPECT_EQ(decoded[2].args()[0].int_value(), 1417);
+  EXPECT_EQ(decoded[2].args()[1].name(), "UID");
+  EXPECT_EQ(decoded[2].args()[1].int_value(), 10098);
+  EXPECT_EQ(decoded[2].args()[2].name(), "Process Name");
+  EXPECT_EQ(decoded[2].args()[2].string_value(),
             "com.google.android.connectivitymonitor");
-  EXPECT_EQ(decoded.Get(2).args(3).name(), "Pss");
-  EXPECT_EQ(decoded.Get(2).args(3).int_value(), 4831232);
-  EXPECT_EQ(decoded.Get(2).args(4).name(), "Uss");
-  EXPECT_EQ(decoded.Get(2).args(4).int_value(), 3723264);
-  EXPECT_EQ(decoded.Get(2).args(5).name(), "SwapPss");
-  EXPECT_EQ(decoded.Get(2).args(5).int_value(), 0);
-  EXPECT_EQ(decoded.Get(2).args(6).name(), "Rss");
-  EXPECT_EQ(decoded.Get(2).args(6).int_value(), 56053760);
-  EXPECT_EQ(decoded.Get(2).args(7).name(), "StatType");
-  EXPECT_EQ(decoded.Get(2).args(7).int_value(), 0);
-  EXPECT_EQ(decoded.Get(2).args(8).name(), "ProcState");
-  EXPECT_EQ(decoded.Get(2).args(8).int_value(), 9);
-  EXPECT_EQ(decoded.Get(2).args(9).name(), "TimeToCollect");
-  EXPECT_EQ(decoded.Get(2).args(9).int_value(), 39);
+  EXPECT_EQ(decoded[2].args()[3].name(), "Pss");
+  EXPECT_EQ(decoded[2].args()[3].int_value(), 4831232);
+  EXPECT_EQ(decoded[2].args()[4].name(), "Uss");
+  EXPECT_EQ(decoded[2].args()[4].int_value(), 3723264);
+  EXPECT_EQ(decoded[2].args()[5].name(), "SwapPss");
+  EXPECT_EQ(decoded[2].args()[5].int_value(), 0);
+  EXPECT_EQ(decoded[2].args()[6].name(), "Rss");
+  EXPECT_EQ(decoded[2].args()[6].int_value(), 56053760);
+  EXPECT_EQ(decoded[2].args()[7].name(), "StatType");
+  EXPECT_EQ(decoded[2].args()[7].int_value(), 0);
+  EXPECT_EQ(decoded[2].args()[8].name(), "ProcState");
+  EXPECT_EQ(decoded[2].args()[8].int_value(), 9);
+  EXPECT_EQ(decoded[2].args()[9].name(), "TimeToCollect");
+  EXPECT_EQ(decoded[2].args()[9].int_value(), 39);
 }
 
 TEST_F(AndroidLogDataSourceTest, BinaryEventsWithTagFiltering) {
   DataSourceConfig cfg;
-  protozero::HeapBuffered<AndroidLogConfig> acfg;
-  acfg->add_filter_tags("not mached");
-  acfg->add_filter_tags("am_uid_stopped");
+  AndroidLogConfig acfg;
+  acfg.add_filter_tags("not mached");
+  acfg.add_filter_tags("am_uid_stopped");
   cfg.set_android_log_config_raw(acfg.SerializeAsString());
   CreateInstance(cfg);
   static const char kDefs[] = R"(
@@ -403,8 +403,8 @@
 
   EXPECT_EQ(event_packet.android_log().events_size(), 1);
   const auto& decoded = event_packet.android_log().events();
-  EXPECT_EQ(decoded.Get(0).timestamp(), 1546165328946231844ULL);
-  EXPECT_EQ(decoded.Get(0).tag(), "am_uid_stopped");
+  EXPECT_EQ(decoded[0].timestamp(), 1546165328946231844ULL);
+  EXPECT_EQ(decoded[0].tag(), "am_uid_stopped");
 }
 
 }  // namespace
diff --git a/src/traced/probes/ftrace/BUILD.gn b/src/traced/probes/ftrace/BUILD.gn
index e53e7b6..02ef384 100644
--- a/src/traced/probes/ftrace/BUILD.gn
+++ b/src/traced/probes/ftrace/BUILD.gn
@@ -47,12 +47,15 @@
   deps = [
     ":format_parser",
     ":ftrace",
+    ":test_messages_cpp",
     ":test_messages_lite",
     ":test_messages_zero",
     ":test_support",
     "../../../../gn:default_deps",
     "../../../../gn:gtest_and_gmock",
-    "../../../../protos/perfetto/trace/ftrace:lite",
+    "../../../../protos/perfetto/trace:cpp",
+    "../../../../protos/perfetto/trace/ftrace:cpp",
+    "../../../../protos/perfetto/trace/ftrace:zero",
     "../../../base:test_support",
     "../../../tracing:test_support",
   ]
@@ -71,6 +74,7 @@
 
 perfetto_proto_library("test_messages_@TYPE@") {
   proto_generators = [
+    "cpp",
     "lite",
     "zero",
   ]
@@ -89,7 +93,6 @@
     ":test_support",
     "../../../../gn:default_deps",
     "../../../../gn:gtest_and_gmock",
-    "../../../../protos/perfetto/trace/ftrace:lite",
     "../../../base",
     "../../../tracing",
   ]
diff --git a/src/traced/probes/ftrace/cpu_reader_unittest.cc b/src/traced/probes/ftrace/cpu_reader_unittest.cc
index f8b58cf..61cdc23 100644
--- a/src/traced/probes/ftrace/cpu_reader_unittest.cc
+++ b/src/traced/probes/ftrace/cpu_reader_unittest.cc
@@ -24,20 +24,24 @@
 #include "perfetto/protozero/proto_utils.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
 #include "perfetto/protozero/scattered_stream_writer.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event.pb.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pb.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
 #include "src/traced/probes/ftrace/event_info.h"
 #include "src/traced/probes/ftrace/ftrace_config_muxer.h"
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
 #include "src/traced/probes/ftrace/proto_translation_table.h"
 #include "src/traced/probes/ftrace/test/cpu_reader_support.h"
-#include "src/traced/probes/ftrace/test/test_messages.pb.h"
-#include "src/traced/probes/ftrace/test/test_messages.pbzero.h"
 #include "src/tracing/core/trace_writer_for_testing.h"
 #include "test/gtest_and_gmock.h"
 
+#include "protos/perfetto/trace/ftrace/ftrace.gen.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "protos/perfetto/trace/ftrace/sched.gen.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
+#include "src/traced/probes/ftrace/test/test_messages.gen.h"
+#include "src/traced/probes/ftrace/test/test_messages.pbzero.h"
+
 using protozero::proto_utils::ProtoSchemaType;
 using testing::_;
 using testing::AnyNumber;
@@ -118,8 +122,7 @@
   std::unique_ptr<ProtoT> ParseProto() {
     auto bundle = std::unique_ptr<ProtoT>(new ProtoT());
     std::vector<uint8_t> buffer = delegate_.StitchSlices();
-    if (!bundle->ParseFromArray(buffer.data(),
-                                static_cast<int>(buffer.size()))) {
+    if (!bundle->ParseFromArray(buffer.data(), buffer.size())) {
       return nullptr;
     }
     return bundle;
@@ -135,8 +138,8 @@
   ZeroT writer_;
 };
 
-using BundleProvider =
-    ProtoProvider<protos::pbzero::FtraceEventBundle, protos::FtraceEventBundle>;
+using BundleProvider = ProtoProvider<protos::pbzero::FtraceEventBundle,
+                                     protos::gen::FtraceEventBundle>;
 
 class BinaryWriter {
  public:
@@ -401,8 +404,8 @@
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
-  ASSERT_EQ(bundle->event().size(), 1);
-  const protos::FtraceEvent& event = bundle->event().Get(0);
+  ASSERT_EQ(bundle->event().size(), 1u);
+  const protos::gen::FtraceEvent& event = bundle->event()[0];
   EXPECT_EQ(event.pid(), 28712ul);
   EXPECT_TRUE(WithinOneMicrosecond(event.timestamp(), 608934, 535199));
   EXPECT_EQ(event.print().buf(), "Hello, world!\n");
@@ -527,10 +530,10 @@
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
-  const protos::FtraceEvent& long_print = bundle->event().Get(0);
+  const protos::gen::FtraceEvent& long_print = bundle->event()[0];
   EXPECT_THAT(long_print.print().buf(), StartsWith("qwerty"));
   EXPECT_THAT(long_print.print().buf(), EndsWith("ppp\n"));
-  const protos::FtraceEvent& newline = bundle->event().Get(1);
+  const protos::gen::FtraceEvent& newline = bundle->event()[1];
   EXPECT_EQ(newline.print().buf(), "\n");
 }
 
@@ -579,10 +582,10 @@
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
-  ASSERT_EQ(bundle->event().size(), 1);
+  ASSERT_EQ(bundle->event().size(), 1u);
   // Although one field is malformed we still see data for the rest
   // since we write the fields as we parse them for speed.
-  const protos::FtraceEvent& event = bundle->event().Get(0);
+  const protos::gen::FtraceEvent& event = bundle->event()[0];
   EXPECT_EQ(event.pid(), 28712ul);
   EXPECT_TRUE(WithinOneMicrosecond(event.timestamp(), 608934, 535199));
   EXPECT_EQ(event.print().buf(), "");
@@ -615,7 +618,7 @@
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
-  ASSERT_EQ(bundle->event().size(), 0);
+  ASSERT_EQ(bundle->event().size(), 0u);
 }
 
 // clang-format off
@@ -684,24 +687,24 @@
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
-  ASSERT_EQ(bundle->event().size(), 3);
+  ASSERT_EQ(bundle->event().size(), 3u);
 
   {
-    const protos::FtraceEvent& event = bundle->event().Get(0);
+    const protos::gen::FtraceEvent& event = bundle->event()[0];
     EXPECT_EQ(event.pid(), 30693ul);
     EXPECT_TRUE(WithinOneMicrosecond(event.timestamp(), 615436, 216806));
     EXPECT_EQ(event.print().buf(), "Hello, world!\n");
   }
 
   {
-    const protos::FtraceEvent& event = bundle->event().Get(1);
+    const protos::gen::FtraceEvent& event = bundle->event()[1];
     EXPECT_EQ(event.pid(), 30693ul);
     EXPECT_TRUE(WithinOneMicrosecond(event.timestamp(), 615486, 377232));
     EXPECT_EQ(event.print().buf(), "Good afternoon, world!\n");
   }
 
   {
-    const protos::FtraceEvent& event = bundle->event().Get(2);
+    const protos::gen::FtraceEvent& event = bundle->event()[2];
     EXPECT_EQ(event.pid(), 30693ul);
     EXPECT_TRUE(WithinOneMicrosecond(event.timestamp(), 615495, 632679));
     EXPECT_EQ(event.print().buf(), "Goodbye, world!\n");
@@ -794,10 +797,10 @@
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
-  ASSERT_EQ(bundle->event().size(), 6);
+  ASSERT_EQ(bundle->event().size(), 6u);
 
   {
-    const protos::FtraceEvent& event = bundle->event().Get(1);
+    const protos::gen::FtraceEvent& event = bundle->event()[1];
     EXPECT_EQ(event.pid(), 3733ul);
     EXPECT_TRUE(WithinOneMicrosecond(event.timestamp(), 1045157, 725035));
     EXPECT_EQ(event.sched_switch().prev_comm(), "sleep");
@@ -842,7 +845,7 @@
   // Nothing written into the proto yet:
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
-  EXPECT_EQ(0, bundle->event().size());
+  EXPECT_EQ(0u, bundle->event().size());
   EXPECT_FALSE(bundle->has_compact_sched());
 
   // Instead, sched switch fields were buffered:
@@ -857,28 +860,28 @@
 
   const auto& compact_sched = bundle->compact_sched();
 
-  EXPECT_EQ(6, compact_sched.switch_timestamp().size());
-  EXPECT_EQ(6, compact_sched.switch_prev_state().size());
-  EXPECT_EQ(6, compact_sched.switch_next_pid().size());
-  EXPECT_EQ(6, compact_sched.switch_next_prio().size());
+  EXPECT_EQ(6u, compact_sched.switch_timestamp().size());
+  EXPECT_EQ(6u, compact_sched.switch_prev_state().size());
+  EXPECT_EQ(6u, compact_sched.switch_next_pid().size());
+  EXPECT_EQ(6u, compact_sched.switch_next_prio().size());
   // 4 unique interned next_comm strings:
-  EXPECT_EQ(4, compact_sched.intern_table().size());
-  EXPECT_EQ(6, compact_sched.switch_next_comm_index().size());
+  EXPECT_EQ(4u, compact_sched.intern_table().size());
+  EXPECT_EQ(6u, compact_sched.switch_next_comm_index().size());
 
   // First event exactly as expected (absolute timestamp):
-  EXPECT_TRUE(
-      WithinOneMicrosecond(compact_sched.switch_timestamp(0), 1045157, 722134));
-  EXPECT_EQ(1, compact_sched.switch_prev_state(0));
-  EXPECT_EQ(3733, compact_sched.switch_next_pid(0));
-  EXPECT_EQ(120, compact_sched.switch_next_prio(0));
-  std::string next_comm = compact_sched.intern_table(
-      static_cast<int>(compact_sched.switch_next_comm_index(0)));
+  EXPECT_TRUE(WithinOneMicrosecond(compact_sched.switch_timestamp()[0], 1045157,
+                                   722134));
+  EXPECT_EQ(1, compact_sched.switch_prev_state()[0]);
+  EXPECT_EQ(3733, compact_sched.switch_next_pid()[0]);
+  EXPECT_EQ(120, compact_sched.switch_next_prio()[0]);
+  auto comm_intern_idx = compact_sched.switch_next_comm_index()[0];
+  std::string next_comm = compact_sched.intern_table()[comm_intern_idx];
   EXPECT_EQ("sleep", next_comm);
 }
 
 TEST_F(CpuReaderTableTest, ParseAllFields) {
   using FakeEventProvider =
-      ProtoProvider<pbzero::FakeFtraceEvent, FakeFtraceEvent>;
+      ProtoProvider<pbzero::FakeFtraceEvent, gen::FakeFtraceEvent>;
 
   uint16_t ftrace_event_id = 102;
 
@@ -1067,7 +1070,7 @@
   ASSERT_TRUE(event);
   EXPECT_EQ(event->common_field(), 1001ul);
   EXPECT_EQ(event->common_pid(), 9999ul);
-  EXPECT_EQ(event->event_case(), FakeFtraceEvent::kAllFields);
+  EXPECT_TRUE(event->has_all_fields());
   EXPECT_EQ(event->all_fields().field_uint32(), 1003u);
   EXPECT_EQ(event->all_fields().field_pid(), 97);
   EXPECT_EQ(event->all_fields().field_dev_32(),
@@ -1170,17 +1173,17 @@
   // without data loss.
   // So we should get three packets (each page has 1 event):
   //   [3 events] [1 event] [4 events].
-  std::vector<protos::TracePacket> packets = trace_writer.GetAllTracePackets();
+  auto packets = trace_writer.GetAllTracePackets();
 
   ASSERT_EQ(3u, packets.size());
   EXPECT_FALSE(packets[0].ftrace_events().lost_events());
-  EXPECT_EQ(3, packets[0].ftrace_events().event().size());
+  EXPECT_EQ(3u, packets[0].ftrace_events().event().size());
 
   EXPECT_TRUE(packets[1].ftrace_events().lost_events());
-  EXPECT_EQ(1, packets[1].ftrace_events().event().size());
+  EXPECT_EQ(1u, packets[1].ftrace_events().event().size());
 
   EXPECT_TRUE(packets[2].ftrace_events().lost_events());
-  EXPECT_EQ(4, packets[2].ftrace_events().event().size());
+  EXPECT_EQ(4u, packets[2].ftrace_events().event().size());
 }
 
 TEST(CpuReaderTest, TranslateBlockDeviceIDToUserspace) {
@@ -1640,7 +1643,7 @@
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
-  EXPECT_EQ(bundle->event().size(), 59);
+  EXPECT_EQ(bundle->event().size(), 59u);
 }
 
 // clang-format off
diff --git a/src/traced/probes/ftrace/event_info.cc b/src/traced/probes/ftrace/event_info.cc
index d494a1e..a011d7b 100644
--- a/src/traced/probes/ftrace/event_info.cc
+++ b/src/traced/probes/ftrace/event_info.cc
@@ -5927,6 +5927,9 @@
            {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
             "value", 4, ProtoSchemaType::kInt32,
             TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "trace_begin", 5, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
        },
        kUnsetFtraceId,
        333,
diff --git a/src/traced/probes/ftrace/ftrace_controller_unittest.cc b/src/traced/probes/ftrace/ftrace_controller_unittest.cc
index fec3c80..1f40c83 100644
--- a/src/traced/probes/ftrace/ftrace_controller_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_controller_unittest.cc
@@ -30,9 +30,9 @@
 #include "src/tracing/core/trace_writer_for_testing.h"
 #include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "protos/perfetto/trace/ftrace/ftrace_stats.gen.h"
 #include "protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
 using testing::_;
@@ -49,7 +49,6 @@
 using testing::UnorderedElementsAre;
 
 using Table = perfetto::ProtoTranslationTable;
-using FtraceEventBundle = perfetto::protos::pbzero::FtraceEventBundle;
 
 namespace perfetto {
 
@@ -535,8 +534,8 @@
     stats.Write(out);
   }
 
-  protos::TracePacket result_packet = writer->GetOnlyTracePacket();
-  auto result = result_packet.ftrace_stats().cpu_stats(0);
+  protos::gen::TracePacket result_packet = writer->GetOnlyTracePacket();
+  auto result = result_packet.ftrace_stats().cpu_stats()[0];
   EXPECT_EQ(result.cpu(), 0u);
   EXPECT_EQ(result.entries(), 1u);
   EXPECT_EQ(result.overrun(), 2u);
diff --git a/src/traced/probes/ftrace/ftrace_metadata.h b/src/traced/probes/ftrace/ftrace_metadata.h
index c6703cb..de9d89a 100644
--- a/src/traced/probes/ftrace/ftrace_metadata.h
+++ b/src/traced/probes/ftrace/ftrace_metadata.h
@@ -21,6 +21,8 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include <bitset>
+
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/flat_set.h"
 #include "perfetto/ext/traced/data_source_types.h"
diff --git a/src/traced/probes/ftrace/proto_translation_table_unittest.cc b/src/traced/probes/ftrace/proto_translation_table_unittest.cc
index f5dcf29..1ca013a 100644
--- a/src/traced/probes/ftrace/proto_translation_table_unittest.cc
+++ b/src/traced/probes/ftrace/proto_translation_table_unittest.cc
@@ -16,8 +16,6 @@
 
 #include "src/traced/probes/ftrace/proto_translation_table.h"
 
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/generic.pbzero.h"
 #include "src/base/test/gtest_test_suite.h"
 #include "src/base/test/utils.h"
 #include "src/traced/probes/ftrace/compact_sched.h"
@@ -25,6 +23,9 @@
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
 #include "test/gtest_and_gmock.h"
 
+#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "protos/perfetto/trace/ftrace/generic.pbzero.h"
+
 using testing::_;
 using testing::Values;
 using testing::ValuesIn;
diff --git a/src/traced/probes/ftrace/test/data/synthetic_alt/available_events b/src/traced/probes/ftrace/test/data/synthetic_alt/available_events
new file mode 100644
index 0000000..6200090
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/synthetic_alt/available_events
@@ -0,0 +1,2 @@
+sde:tracing_mark_write
+
diff --git a/src/traced/probes/ftrace/test/data/synthetic_alt/events/sde/tracing_mark_write/format b/src/traced/probes/ftrace/test/data/synthetic_alt/events/sde/tracing_mark_write/format
new file mode 100644
index 0000000..be29167
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/synthetic_alt/events/sde/tracing_mark_write/format
@@ -0,0 +1,14 @@
+name: tracing_mark_write
+ID: 595
+format:
+	field:unsigned short common_type;	offset:0;	size:2;	signed:0;
+	field:unsigned char common_flags;	offset:2;	size:1;	signed:0;
+	field:unsigned char common_preempt_count;	offset:3;	size:1;	signed:0;
+	field:int common_pid;	offset:4;	size:4;	signed:1;
+
+	field:int pid;	offset:8;	size:4;	signed:1;
+	field:__data_loc char[] trace_name;	offset:12;	size:4;	signed:0;
+	field:bool trace_begin;	offset:16;	size:1;	signed:0;
+
+print fmt: "%s|%d|%s", REC->trace_begin ? "B" : "E", REC->pid, __get_str(trace_name)
+
diff --git a/src/traced/probes/packages_list/BUILD.gn b/src/traced/probes/packages_list/BUILD.gn
index b1092d1..eaee21d 100644
--- a/src/traced/probes/packages_list/BUILD.gn
+++ b/src/traced/probes/packages_list/BUILD.gn
@@ -39,7 +39,7 @@
     ":packages_list",
     "../../../../gn:default_deps",
     "../../../../gn:gtest_and_gmock",
-    "../../../../protos/perfetto/trace/android:lite",
+    "../../../../protos/perfetto/trace/android:cpp",
     "../../../../protos/perfetto/trace/android:zero",
     "../../../../src/base:test_support",
     "../../../../src/tracing:test_support",
diff --git a/src/traced/probes/packages_list/packages_list_data_source_unittest.cc b/src/traced/probes/packages_list/packages_list_data_source_unittest.cc
index f2f7675..cb311d2 100644
--- a/src/traced/probes/packages_list/packages_list_data_source_unittest.cc
+++ b/src/traced/probes/packages_list/packages_list_data_source_unittest.cc
@@ -23,7 +23,7 @@
 
 #include "perfetto/ext/base/pipe.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/trace/android/packages_list.pb.h"
+#include "protos/perfetto/trace/android/packages_list.gen.h"
 #include "protos/perfetto/trace/android/packages_list.pbzero.h"
 #include "test/gtest_and_gmock.h"
 
@@ -100,19 +100,19 @@
 
   ASSERT_TRUE(ParsePackagesListStream(packages_list.get(), fs, filter));
 
-  protos::PackagesList parsed_list;
+  protos::gen::PackagesList parsed_list;
   parsed_list.ParseFromString(packages_list.SerializeAsString());
 
   EXPECT_FALSE(parsed_list.read_error());
   EXPECT_FALSE(parsed_list.parse_error());
   // all entries
   EXPECT_EQ(parsed_list.packages_size(), 3);
-  EXPECT_EQ(parsed_list.packages(0).name(), "com.test.one");
-  EXPECT_EQ(parsed_list.packages(0).version_code(), 10);
-  EXPECT_EQ(parsed_list.packages(1).name(), "com.test.two");
-  EXPECT_EQ(parsed_list.packages(1).version_code(), 20);
-  EXPECT_EQ(parsed_list.packages(2).name(), "com.test.three");
-  EXPECT_EQ(parsed_list.packages(2).version_code(), 30);
+  EXPECT_EQ(parsed_list.packages()[0].name(), "com.test.one");
+  EXPECT_EQ(parsed_list.packages()[0].version_code(), 10);
+  EXPECT_EQ(parsed_list.packages()[1].name(), "com.test.two");
+  EXPECT_EQ(parsed_list.packages()[1].version_code(), 20);
+  EXPECT_EQ(parsed_list.packages()[2].name(), "com.test.three");
+  EXPECT_EQ(parsed_list.packages()[2].version_code(), 30);
 }
 
 TEST(PackagesListDataSourceTest, NameFilter) {
@@ -137,17 +137,17 @@
 
   ASSERT_TRUE(ParsePackagesListStream(packages_list.get(), fs, filter));
 
-  protos::PackagesList parsed_list;
+  protos::gen::PackagesList parsed_list;
   parsed_list.ParseFromString(packages_list.SerializeAsString());
 
   EXPECT_FALSE(parsed_list.read_error());
   EXPECT_FALSE(parsed_list.parse_error());
   // two named entries
   EXPECT_EQ(parsed_list.packages_size(), 2);
-  EXPECT_EQ(parsed_list.packages(0).name(), "com.test.one");
-  EXPECT_EQ(parsed_list.packages(0).version_code(), 10);
-  EXPECT_EQ(parsed_list.packages(1).name(), "com.test.three");
-  EXPECT_EQ(parsed_list.packages(1).version_code(), 30);
+  EXPECT_EQ(parsed_list.packages()[0].name(), "com.test.one");
+  EXPECT_EQ(parsed_list.packages()[0].version_code(), 10);
+  EXPECT_EQ(parsed_list.packages()[1].name(), "com.test.three");
+  EXPECT_EQ(parsed_list.packages()[1].version_code(), 30);
 }
 
 }  // namespace
diff --git a/src/traced/probes/ps/BUILD.gn b/src/traced/probes/ps/BUILD.gn
index 9918cc3..85c24bc 100644
--- a/src/traced/probes/ps/BUILD.gn
+++ b/src/traced/probes/ps/BUILD.gn
@@ -38,8 +38,8 @@
     ":ps",
     "../../../../gn:default_deps",
     "../../../../gn:gtest_and_gmock",
-    "../../../../protos/perfetto/config/process_stats:zero",
-    "../../../../protos/perfetto/trace/ps:zero",
+    "../../../../protos/perfetto/config/process_stats:cpp",
+    "../../../../protos/perfetto/trace/ps:cpp",
     "../../../../src/base:test_support",
     "../../../../src/tracing:test_support",
   ]
diff --git a/src/traced/probes/ps/process_stats_data_source_unittest.cc b/src/traced/probes/ps/process_stats_data_source_unittest.cc
index c7cbd28..532a27e 100644
--- a/src/traced/probes/ps/process_stats_data_source_unittest.cc
+++ b/src/traced/probes/ps/process_stats_data_source_unittest.cc
@@ -25,10 +25,11 @@
 #include "src/tracing/core/trace_writer_for_testing.h"
 #include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/config/process_stats/process_stats_config.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "protos/perfetto/config/process_stats/process_stats_config.gen.h"
+#include "protos/perfetto/trace/ps/process_stats.gen.h"
+#include "protos/perfetto/trace/ps/process_tree.gen.h"
 
-using ::perfetto::protos::pbzero::ProcessStatsConfig;
+using ::perfetto::protos::gen::ProcessStatsConfig;
 using ::testing::_;
 using ::testing::ElementsAreArray;
 using ::testing::Invoke;
@@ -79,11 +80,11 @@
 
   data_source->OnPids({42});
 
-  std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets();
+  auto trace = writer_raw_->GetAllTracePackets();
   ASSERT_EQ(trace.size(), 1u);
   auto ps_tree = trace[0].process_tree();
   ASSERT_EQ(ps_tree.processes_size(), 1);
-  auto first_process = ps_tree.processes(0);
+  auto first_process = ps_tree.processes()[0];
   ASSERT_EQ(first_process.pid(), 42);
   ASSERT_EQ(first_process.ppid(), 17);
   ASSERT_EQ(first_process.uid(), 43);
@@ -93,21 +94,21 @@
 TEST_F(ProcessStatsDataSourceTest, DontRescanCachedPIDsAndTIDs) {
   // assertion helpers
   auto expected_process = [](int pid) {
-    return [pid](protos::ProcessTree::Process process) {
+    return [pid](protos::gen::ProcessTree::Process process) {
       return process.pid() == pid && process.cmdline_size() > 0 &&
-             process.cmdline(0) == "proc_" + std::to_string(pid);
+             process.cmdline()[0] == "proc_" + std::to_string(pid);
     };
   };
   auto expected_thread = [](int tid) {
-    return [tid](protos::ProcessTree::Thread thread) {
+    return [tid](protos::gen::ProcessTree::Thread thread) {
       return thread.tid() == tid && thread.tgid() == tid / 10 * 10 &&
              thread.name() == "thread_" + std::to_string(tid);
     };
   };
 
   DataSourceConfig ds_config;
-  protozero::HeapBuffered<ProcessStatsConfig> cfg;
-  cfg->set_record_thread_names(true);
+  ProcessStatsConfig cfg;
+  cfg.set_record_thread_names(true);
   ds_config.set_process_stats_config_raw(cfg.SerializeAsString());
   auto data_source = GetProcessStatsDataSource(ds_config);
   for (int p : {10, 11, 12, 20, 21, 22, 30, 31, 32}) {
@@ -131,7 +132,7 @@
   data_source->OnPids({10, 30, 10, 31, 32});
 
   // check written contents
-  std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets();
+  auto trace = writer_raw_->GetAllTracePackets();
   EXPECT_EQ(trace.size(), 3u);
 
   // first packet - two unique processes, four threads
@@ -168,7 +169,7 @@
   data_source->OnPids({42});
 
   {
-    std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets();
+    auto trace = writer_raw_->GetAllTracePackets();
     ASSERT_EQ(trace.size(), 1u);
     auto packet = trace[0];
     // First packet in the trace has no previous state, so the clear marker is
@@ -177,9 +178,9 @@
 
     auto ps_tree = packet.process_tree();
     ASSERT_EQ(ps_tree.processes_size(), 1);
-    ASSERT_EQ(ps_tree.processes(0).pid(), 42);
-    ASSERT_EQ(ps_tree.processes(0).ppid(), 17);
-    ASSERT_THAT(ps_tree.processes(0).cmdline(),
+    ASSERT_EQ(ps_tree.processes()[0].pid(), 42);
+    ASSERT_EQ(ps_tree.processes()[0].ppid(), 17);
+    ASSERT_THAT(ps_tree.processes()[0].cmdline(),
                 ElementsAreArray({"first_cmdline"}));
   }
 
@@ -191,7 +192,7 @@
   data_source->OnPids({42});
 
   {
-    std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets();
+    auto trace = writer_raw_->GetAllTracePackets();
     ASSERT_EQ(trace.size(), 1u);
   }
 
@@ -208,16 +209,16 @@
 
   {
     // Second packet with new proc information.
-    std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets();
+    auto trace = writer_raw_->GetAllTracePackets();
     ASSERT_EQ(trace.size(), 2u);
     auto packet = trace[1];
     ASSERT_TRUE(packet.incremental_state_cleared());
 
     auto ps_tree = packet.process_tree();
     ASSERT_EQ(ps_tree.processes_size(), 1);
-    ASSERT_EQ(ps_tree.processes(0).pid(), 42);
-    ASSERT_EQ(ps_tree.processes(0).ppid(), 18);
-    ASSERT_THAT(ps_tree.processes(0).cmdline(),
+    ASSERT_EQ(ps_tree.processes()[0].pid(), 42);
+    ASSERT_EQ(ps_tree.processes()[0].ppid(), 18);
+    ASSERT_THAT(ps_tree.processes()[0].cmdline(),
                 ElementsAreArray({"second_cmdline"}));
   }
 }
@@ -225,15 +226,15 @@
 TEST_F(ProcessStatsDataSourceTest, RenamePids) {
   // assertion helpers
   auto expected_old_process = [](int pid) {
-    return [pid](protos::ProcessTree::Process process) {
+    return [pid](protos::gen::ProcessTree::Process process) {
       return process.pid() == pid && process.cmdline_size() > 0 &&
-             process.cmdline(0) == "proc_" + std::to_string(pid);
+             process.cmdline()[0] == "proc_" + std::to_string(pid);
     };
   };
   auto expected_new_process = [](int pid) {
-    return [pid](protos::ProcessTree::Process process) {
+    return [pid](protos::gen::ProcessTree::Process process) {
       return process.pid() == pid && process.cmdline_size() > 0 &&
-             process.cmdline(0) == "new_" + std::to_string(pid);
+             process.cmdline()[0] == "new_" + std::to_string(pid);
     };
   };
 
@@ -264,7 +265,7 @@
   data_source->OnPids({10, 20});
 
   // check written contents
-  std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets();
+  auto trace = writer_raw_->GetAllTracePackets();
   EXPECT_EQ(trace.size(), 3u);
 
   // first packet - two unique processes
@@ -289,9 +290,9 @@
 
 TEST_F(ProcessStatsDataSourceTest, ProcessStats) {
   DataSourceConfig ds_config;
-  protozero::HeapBuffered<ProcessStatsConfig> cfg;
-  cfg->set_proc_stats_poll_ms(1);
-  cfg->add_quirks(ProcessStatsConfig::DISABLE_ON_DEMAND);
+  ProcessStatsConfig cfg;
+  cfg.set_proc_stats_poll_ms(1);
+  cfg.add_quirks(ProcessStatsConfig::DISABLE_ON_DEMAND);
   ds_config.set_process_stats_config_raw(cfg.SerializeAsString());
   auto data_source = GetProcessStatsDataSource(ds_config);
 
@@ -340,8 +341,8 @@
   task_runner_.RunUntilCheckpoint("all_done");
   data_source->Flush(1 /* FlushRequestId */, []() {});
 
-  std::vector<protos::ProcessStats::Process> processes;
-  std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets();
+  std::vector<protos::gen::ProcessStats::Process> processes;
+  auto trace = writer_raw_->GetAllTracePackets();
   for (const auto& packet : trace) {
     for (const auto& process : packet.process_stats().processes()) {
       processes.push_back(process);
@@ -368,10 +369,10 @@
 
 TEST_F(ProcessStatsDataSourceTest, CacheProcessStats) {
   DataSourceConfig ds_config;
-  protozero::HeapBuffered<ProcessStatsConfig> cfg;
-  cfg->set_proc_stats_poll_ms(105);
-  cfg->set_proc_stats_cache_ttl_ms(220);
-  cfg->add_quirks(ProcessStatsConfig::DISABLE_ON_DEMAND);
+  ProcessStatsConfig cfg;
+  cfg.set_proc_stats_poll_ms(105);
+  cfg.set_proc_stats_cache_ttl_ms(220);
+  cfg.add_quirks(ProcessStatsConfig::DISABLE_ON_DEMAND);
   ds_config.set_process_stats_config_raw(cfg.SerializeAsString());
   auto data_source = GetProcessStatsDataSource(ds_config);
 
@@ -411,8 +412,8 @@
   task_runner_.RunUntilCheckpoint("all_done");
   data_source->Flush(1 /* FlushRequestId */, []() {});
 
-  std::vector<protos::ProcessStats::Process> processes;
-  std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets();
+  std::vector<protos::gen::ProcessStats::Process> processes;
+  auto trace = writer_raw_->GetAllTracePackets();
   for (const auto& packet : trace) {
     for (const auto& process : packet.process_stats().processes()) {
       processes.push_back(process);
diff --git a/src/traced/probes/sys_stats/BUILD.gn b/src/traced/probes/sys_stats/BUILD.gn
index c7fa58b..efea7a9 100644
--- a/src/traced/probes/sys_stats/BUILD.gn
+++ b/src/traced/probes/sys_stats/BUILD.gn
@@ -40,10 +40,8 @@
     ":sys_stats",
     "../../../../gn:default_deps",
     "../../../../gn:gtest_and_gmock",
-    "../../../../protos/perfetto/common:zero",
-    "../../../../protos/perfetto/config:zero",
-    "../../../../protos/perfetto/config/sys_stats:zero",
-    "../../../../protos/perfetto/trace/sys_stats:zero",
+    "../../../../protos/perfetto/config/sys_stats:cpp",
+    "../../../../protos/perfetto/trace/sys_stats:cpp",
     "../../../../src/base:test_support",
     "../../../../src/tracing:test_support",
   ]
diff --git a/src/traced/probes/sys_stats/sys_stats_data_source_unittest.cc b/src/traced/probes/sys_stats/sys_stats_data_source_unittest.cc
index c760f41..49af8a4 100644
--- a/src/traced/probes/sys_stats/sys_stats_data_source_unittest.cc
+++ b/src/traced/probes/sys_stats/sys_stats_data_source_unittest.cc
@@ -17,16 +17,15 @@
 #include <unistd.h>
 
 #include "perfetto/ext/base/temp_file.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/traced/probes/sys_stats/sys_stats_data_source.h"
 #include "src/tracing/core/trace_writer_for_testing.h"
 #include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/common/sys_stats_counters.pbzero.h"
-#include "protos/perfetto/config/data_source_config.pbzero.h"
-#include "protos/perfetto/config/sys_stats/sys_stats_config.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "protos/perfetto/common/sys_stats_counters.gen.h"
+#include "protos/perfetto/config/data_source_config.gen.h"
+#include "protos/perfetto/config/sys_stats/sys_stats_config.gen.h"
+#include "protos/perfetto/trace/sys_stats/sys_stats.gen.h"
 
 using ::testing::_;
 using ::testing::Invoke;
@@ -233,21 +232,21 @@
 };
 
 TEST_F(SysStatsDataSourceTest, Meminfo) {
-  using C = protos::pbzero::MeminfoCounters;
+  using C = protos::gen::MeminfoCounters;
   DataSourceConfig config;
-  protozero::HeapBuffered<protos::pbzero::SysStatsConfig> sys_cfg;
-  sys_cfg->set_meminfo_period_ms(10);
-  sys_cfg->add_meminfo_counters(C::MEMINFO_MEM_TOTAL);
-  sys_cfg->add_meminfo_counters(C::MEMINFO_MEM_FREE);
-  sys_cfg->add_meminfo_counters(C::MEMINFO_ACTIVE_ANON);
-  sys_cfg->add_meminfo_counters(C::MEMINFO_INACTIVE_FILE);
-  sys_cfg->add_meminfo_counters(C::MEMINFO_CMA_FREE);
+  protos::gen::SysStatsConfig sys_cfg;
+  sys_cfg.set_meminfo_period_ms(10);
+  sys_cfg.add_meminfo_counters(C::MEMINFO_MEM_TOTAL);
+  sys_cfg.add_meminfo_counters(C::MEMINFO_MEM_FREE);
+  sys_cfg.add_meminfo_counters(C::MEMINFO_ACTIVE_ANON);
+  sys_cfg.add_meminfo_counters(C::MEMINFO_INACTIVE_FILE);
+  sys_cfg.add_meminfo_counters(C::MEMINFO_CMA_FREE);
   config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
   auto data_source = GetSysStatsDataSource(config);
 
   WaitTick(data_source.get());
 
-  protos::TracePacket packet = writer_raw_->GetOnlyTracePacket();
+  protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
   ASSERT_TRUE(packet.has_sys_stats());
   const auto& sys_stats = packet.sys_stats();
   EXPECT_EQ(sys_stats.vmstat_size(), 0);
@@ -268,14 +267,14 @@
 
 TEST_F(SysStatsDataSourceTest, MeminfoAll) {
   DataSourceConfig config;
-  protozero::HeapBuffered<protos::pbzero::SysStatsConfig> sys_cfg;
-  sys_cfg->set_meminfo_period_ms(10);
+  protos::gen::SysStatsConfig sys_cfg;
+  sys_cfg.set_meminfo_period_ms(10);
   config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
   auto data_source = GetSysStatsDataSource(config);
 
   WaitTick(data_source.get());
 
-  protos::TracePacket packet = writer_raw_->GetOnlyTracePacket();
+  protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
   ASSERT_TRUE(packet.has_sys_stats());
   const auto& sys_stats = packet.sys_stats();
   EXPECT_EQ(sys_stats.vmstat_size(), 0);
@@ -284,19 +283,19 @@
 }
 
 TEST_F(SysStatsDataSourceTest, Vmstat) {
-  using C = protos::pbzero::VmstatCounters;
+  using C = protos::gen::VmstatCounters;
   DataSourceConfig config;
-  protozero::HeapBuffered<protos::pbzero::SysStatsConfig> sys_cfg;
-  sys_cfg->set_vmstat_period_ms(10);
-  sys_cfg->add_vmstat_counters(C::VMSTAT_NR_FREE_PAGES);
-  sys_cfg->add_vmstat_counters(C::VMSTAT_PGACTIVATE);
-  sys_cfg->add_vmstat_counters(C::VMSTAT_PGMIGRATE_FAIL);
+  protos::gen::SysStatsConfig sys_cfg;
+  sys_cfg.set_vmstat_period_ms(10);
+  sys_cfg.add_vmstat_counters(C::VMSTAT_NR_FREE_PAGES);
+  sys_cfg.add_vmstat_counters(C::VMSTAT_PGACTIVATE);
+  sys_cfg.add_vmstat_counters(C::VMSTAT_PGMIGRATE_FAIL);
   config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
   auto data_source = GetSysStatsDataSource(config);
 
   WaitTick(data_source.get());
 
-  protos::TracePacket packet = writer_raw_->GetOnlyTracePacket();
+  protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
   ASSERT_TRUE(packet.has_sys_stats());
   const auto& sys_stats = packet.sys_stats();
   EXPECT_EQ(sys_stats.meminfo_size(), 0);
@@ -314,14 +313,14 @@
 
 TEST_F(SysStatsDataSourceTest, VmstatAll) {
   DataSourceConfig config;
-  protozero::HeapBuffered<protos::pbzero::SysStatsConfig> sys_cfg;
-  sys_cfg->set_vmstat_period_ms(10);
+  protos::gen::SysStatsConfig sys_cfg;
+  sys_cfg.set_vmstat_period_ms(10);
   config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
   auto data_source = GetSysStatsDataSource(config);
 
   WaitTick(data_source.get());
 
-  protos::TracePacket packet = writer_raw_->GetOnlyTracePacket();
+  protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
   ASSERT_TRUE(packet.has_sys_stats());
   const auto& sys_stats = packet.sys_stats();
   EXPECT_EQ(sys_stats.meminfo_size(), 0);
@@ -331,57 +330,56 @@
 
 TEST_F(SysStatsDataSourceTest, StatAll) {
   DataSourceConfig config;
-  protozero::HeapBuffered<protos::pbzero::SysStatsConfig> sys_cfg;
-  sys_cfg->set_stat_period_ms(10);
+  protos::gen::SysStatsConfig sys_cfg;
+  sys_cfg.set_stat_period_ms(10);
   config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
   auto data_source = GetSysStatsDataSource(config);
 
   WaitTick(data_source.get());
 
-  protos::TracePacket packet = writer_raw_->GetOnlyTracePacket();
+  protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
   ASSERT_TRUE(packet.has_sys_stats());
   const auto& sys_stats = packet.sys_stats();
   EXPECT_EQ(sys_stats.meminfo_size(), 0);
   EXPECT_EQ(sys_stats.vmstat_size(), 0);
 
   ASSERT_EQ(sys_stats.cpu_stat_size(), 8);
-  EXPECT_EQ(sys_stats.cpu_stat(0).user_ns(), 762178 * 10000000ull);
-  EXPECT_EQ(sys_stats.cpu_stat(0).system_mode_ns(), 902284 * 10000000ull);
-  EXPECT_EQ(sys_stats.cpu_stat(0).softirq_ns(), 68262 * 10000000ull);
-  EXPECT_EQ(sys_stats.cpu_stat(7).user_ns(), 180484 * 10000000ull);
-  EXPECT_EQ(sys_stats.cpu_stat(7).system_mode_ns(), 139874 * 10000000ull);
-  EXPECT_EQ(sys_stats.cpu_stat(7).softirq_ns(), 13407 * 10000000ull);
+  EXPECT_EQ(sys_stats.cpu_stat()[0].user_ns(), 762178 * 10000000ull);
+  EXPECT_EQ(sys_stats.cpu_stat()[0].system_mode_ns(), 902284 * 10000000ull);
+  EXPECT_EQ(sys_stats.cpu_stat()[0].softirq_ns(), 68262 * 10000000ull);
+  EXPECT_EQ(sys_stats.cpu_stat()[7].user_ns(), 180484 * 10000000ull);
+  EXPECT_EQ(sys_stats.cpu_stat()[7].system_mode_ns(), 139874 * 10000000ull);
+  EXPECT_EQ(sys_stats.cpu_stat()[7].softirq_ns(), 13407 * 10000000ull);
 
   EXPECT_EQ(sys_stats.num_forks(), 243320u);
 
   EXPECT_EQ(sys_stats.num_irq_total(), 238128517u);
   ASSERT_EQ(sys_stats.num_irq_size(), 102);
-  EXPECT_EQ(sys_stats.num_irq(0).count(), 63500984u);
-  EXPECT_EQ(sys_stats.num_irq(0).irq(), 3);
-  EXPECT_EQ(sys_stats.num_irq(1).count(), 6253792u);
-  EXPECT_EQ(sys_stats.num_irq(1).irq(), 5);
-  EXPECT_EQ(sys_stats.num_irq(101).count(), 680u);
+  EXPECT_EQ(sys_stats.num_irq()[0].count(), 63500984u);
+  EXPECT_EQ(sys_stats.num_irq()[0].irq(), 3);
+  EXPECT_EQ(sys_stats.num_irq()[1].count(), 6253792u);
+  EXPECT_EQ(sys_stats.num_irq()[1].irq(), 5);
+  EXPECT_EQ(sys_stats.num_irq()[101].count(), 680u);
 
   EXPECT_EQ(sys_stats.num_softirq_total(), 84611084u);
   ASSERT_EQ(sys_stats.num_softirq_size(), 10);
-  EXPECT_EQ(sys_stats.num_softirq(0).count(), 10220177u);
-  EXPECT_EQ(sys_stats.num_softirq(9).count(), 16443195u);
+  EXPECT_EQ(sys_stats.num_softirq()[0].count(), 10220177u);
+  EXPECT_EQ(sys_stats.num_softirq()[9].count(), 16443195u);
 
   EXPECT_EQ(sys_stats.num_softirq_total(), 84611084u);
 }
 
 TEST_F(SysStatsDataSourceTest, StatForksOnly) {
-  using C = protos::SysStatsConfig;
-  protos::DataSourceConfig config;
-  config.mutable_sys_stats_config()->set_stat_period_ms(10);
-  config.mutable_sys_stats_config()->add_stat_counters(C::STAT_FORK_COUNT);
+  protos::gen::SysStatsConfig cfg;
+  cfg.set_stat_period_ms(10);
+  cfg.add_stat_counters(protos::gen::SysStatsConfig::STAT_FORK_COUNT);
   DataSourceConfig config_obj;
-  config_obj.FromProto(config);
+  config_obj.set_sys_stats_config_raw(cfg.SerializeAsString());
   auto data_source = GetSysStatsDataSource(config_obj);
 
   WaitTick(data_source.get());
 
-  protos::TracePacket packet = writer_raw_->GetOnlyTracePacket();
+  protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
   ASSERT_TRUE(packet.has_sys_stats());
   const auto& sys_stats = packet.sys_stats();
   EXPECT_EQ(sys_stats.meminfo_size(), 0);
diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn
index 0df9483..8e3f06a 100644
--- a/src/tracing/BUILD.gn
+++ b/src/tracing/BUILD.gn
@@ -69,7 +69,6 @@
   public_deps = [
     "../../include/perfetto/base",
     "../../include/perfetto/ext/tracing/core",
-    "../../protos/perfetto/common:lite",
   ]
   deps = [
     ":tracing",
@@ -89,9 +88,9 @@
     ":tracing",
     "../../gn:default_deps",
     "../../gn:gtest_and_gmock",
-    "../../protos/perfetto/config:lite",
-    "../../protos/perfetto/trace:lite",
+    "../../protos/perfetto/trace:cpp",
     "../../protos/perfetto/trace:zero",
+    "../../protos/perfetto/trace/ftrace:cpp",
     "../base",
     "../base:test_support",
   ]
@@ -141,7 +140,7 @@
   testonly = true
   public_deps = [
     "../../include/perfetto/ext/tracing/core",
-    "../../protos/perfetto/trace:lite",
+    "../../protos/perfetto/trace:cpp",
     "../../protos/perfetto/trace:zero",
     "../protozero",
   ]
@@ -153,12 +152,15 @@
 
 if (perfetto_build_standalone || perfetto_build_with_android) {
   executable("consumer_api_test") {
+    testonly = true
     deps = [
       ":consumer_api_deprecated",
       "../../gn:default_deps",
       "../../include/perfetto/public",
-      "../../protos/perfetto/config:lite",
-      "../../protos/perfetto/trace:lite",
+      "../../protos/perfetto/config:cpp",
+      "../../protos/perfetto/config/ftrace:cpp",
+      "../../protos/perfetto/trace:cpp",
+      "../../protos/perfetto/trace/ftrace:cpp",
       "../base",
     ]
     sources = [
@@ -292,9 +294,12 @@
       "../../gn:default_deps",
       "../../gn:gtest_and_gmock",
       "../../include/perfetto/tracing/core",
-      "../../protos/perfetto/trace:lite",
+      "../../protos/perfetto/trace:cpp",
       "../../protos/perfetto/trace:zero",
+      "../../protos/perfetto/trace/interned_data:cpp",
       "../../protos/perfetto/trace/interned_data:zero",
+      "../../protos/perfetto/trace/profiling:cpp",
+      "../../protos/perfetto/trace/track_event:cpp",
       "../base",
       "test:api_test_support",
     ]
diff --git a/src/tracing/api_impl/consumer_api.cc b/src/tracing/api_impl/consumer_api.cc
index 40b1e2d..8ef2660 100644
--- a/src/tracing/api_impl/consumer_api.cc
+++ b/src/tracing/api_impl/consumer_api.cc
@@ -127,7 +127,7 @@
       callback_(callback),
       callback_arg_(callback_arg) {
   PERFETTO_DETACH_FROM_THREAD(thread_checker_);
-  trace_config_.FromProto(trace_config_proto);
+  trace_config_ = trace_config_proto;
   trace_config_.set_write_into_file(true);
 
   // TODO(primiano): this really doesn't matter because the trace will be
diff --git a/src/tracing/api_impl/consumer_api_test.cc b/src/tracing/api_impl/consumer_api_test.cc
index 220d72d..ebc885a 100644
--- a/src/tracing/api_impl/consumer_api_test.cc
+++ b/src/tracing/api_impl/consumer_api_test.cc
@@ -24,8 +24,13 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/public/consumer_api.h"
 
-#include "protos/perfetto/config/trace_config.pb.h"
-#include "protos/perfetto/trace/trace.pb.h"
+#include "protos/perfetto/config/data_source_config.gen.h"
+#include "protos/perfetto/config/ftrace/ftrace_config.gen.h"
+#include "protos/perfetto/config/trace_config.gen.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
+#include "protos/perfetto/trace/trace.gen.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
 
 using namespace perfetto::consumer;
 
@@ -34,24 +39,25 @@
 int g_pointer = 0;
 
 std::string GetConfig(uint32_t duration_ms) {
-  perfetto::protos::TraceConfig trace_config;
+  perfetto::protos::gen::TraceConfig trace_config;
   trace_config.set_duration_ms(duration_ms);
   trace_config.add_buffers()->set_size_kb(4096);
   trace_config.set_deferred_start(true);
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("linux.ftrace");
-  ds_config->mutable_ftrace_config()->add_ftrace_events("sched_switch");
-  ds_config->mutable_ftrace_config()->add_ftrace_events(
-      "mm_filemap_add_to_page_cache");
-  ds_config->mutable_ftrace_config()->add_ftrace_events(
-      "mm_filemap_delete_from_page_cache");
+
+  perfetto::protos::gen::FtraceConfig ftrace_config;
+  ftrace_config.add_ftrace_events("sched_switch");
+  ftrace_config.add_ftrace_events("mm_filemap_add_to_page_cache");
+  ftrace_config.add_ftrace_events("mm_filemap_delete_from_page_cache");
+  ds_config->set_ftrace_config_raw(ftrace_config.SerializeAsString());
   ds_config->set_target_buffer(0);
   return trace_config.SerializeAsString();
 }
 
 void DumpTrace(TraceBuffer buf) {
-  perfetto::protos::Trace trace;
-  bool parsed = trace.ParseFromArray(buf.begin, static_cast<int>(buf.size));
+  perfetto::protos::gen::Trace trace;
+  bool parsed = trace.ParseFromArray(buf.begin, buf.size);
   if (!parsed) {
     PERFETTO_ELOG("Failed to parse the trace");
     return;
diff --git a/src/tracing/api_integrationtest.cc b/src/tracing/api_integrationtest.cc
index 7840a53..a9f3fbb 100644
--- a/src/tracing/api_integrationtest.cc
+++ b/src/tracing/api_integrationtest.cc
@@ -24,14 +24,6 @@
 #include <vector>
 
 #include "perfetto/tracing.h"
-#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
-#include "protos/perfetto/trace/track_event/log_message.pbzero.h"
-#include "protos/perfetto/trace/track_event/source_location.pbzero.h"
 #include "test/gtest_and_gmock.h"
 
 // Deliberately not pulling any non-public perfetto header to spot accidental
@@ -45,6 +37,29 @@
 #include "perfetto/tracing/core/data_source_descriptor.h"
 #include "perfetto/tracing/core/trace_config.h"
 
+// xxx.pbzero.h includes are for the writing path (the code that pretends to be
+// production code).
+// yyy.gen.h includes are for the test readback path (the code in the test that
+// checks that the results are valid).
+#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
+#include "protos/perfetto/trace/interned_data/interned_data.gen.h"
+#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
+#include "protos/perfetto/trace/profiling/profile_common.gen.h"
+#include "protos/perfetto/trace/test_event.gen.h"
+#include "protos/perfetto/trace/test_event.pbzero.h"
+#include "protos/perfetto/trace/trace.gen.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "protos/perfetto/trace/track_event/debug_annotation.gen.h"
+#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
+#include "protos/perfetto/trace/track_event/log_message.gen.h"
+#include "protos/perfetto/trace/track_event/log_message.pbzero.h"
+#include "protos/perfetto/trace/track_event/process_descriptor.gen.h"
+#include "protos/perfetto/trace/track_event/source_location.gen.h"
+#include "protos/perfetto/trace/track_event/source_location.pbzero.h"
+#include "protos/perfetto/trace/track_event/thread_descriptor.gen.h"
+#include "protos/perfetto/trace/track_event/track_event.gen.h"
+
 // Trace categories used in the tests.
 PERFETTO_DEFINE_CATEGORIES(PERFETTO_CATEGORY(test),
                            PERFETTO_CATEGORY(foo),
@@ -267,10 +282,10 @@
     // Read back the trace, maintaining interning tables as we go.
     std::vector<std::string> log_messages;
     std::map<uint64_t, std::string> log_message_bodies;
-    std::map<uint64_t, perfetto::protos::SourceLocation> source_locations;
-    perfetto::protos::Trace parsed_trace;
+    std::map<uint64_t, perfetto::protos::gen::SourceLocation> source_locations;
+    perfetto::protos::gen::Trace parsed_trace;
     EXPECT_TRUE(
-        parsed_trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+        parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
 
     for (const auto& packet : parsed_trace.packet()) {
       if (!packet.has_track_event())
@@ -291,7 +306,8 @@
         }
       }
       const auto& track_event = packet.track_event();
-      if (track_event.type() != perfetto::protos::TrackEvent::TYPE_SLICE_BEGIN)
+      if (track_event.type() !=
+          perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN)
         continue;
 
       EXPECT_TRUE(track_event.has_log_message());
@@ -322,9 +338,9 @@
     std::map<uint64_t, std::string> categories;
     std::map<uint64_t, std::string> event_names;
     std::map<uint64_t, std::string> debug_annotation_names;
-    perfetto::protos::Trace parsed_trace;
+    perfetto::protos::gen::Trace parsed_trace;
     EXPECT_TRUE(
-        parsed_trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+        parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
 
     bool incremental_state_was_cleared = false;
     uint32_t sequence_id = 0;
@@ -366,20 +382,20 @@
       const auto& track_event = packet.track_event();
       std::string slice;
       switch (track_event.type()) {
-        case perfetto::protos::TrackEvent::TYPE_SLICE_BEGIN:
+        case perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN:
           slice += "B";
           break;
-        case perfetto::protos::TrackEvent::TYPE_SLICE_END:
+        case perfetto::protos::gen::TrackEvent::TYPE_SLICE_END:
           slice += "E";
           break;
-        case perfetto::protos::TrackEvent::TYPE_INSTANT:
+        case perfetto::protos::gen::TrackEvent::TYPE_INSTANT:
           slice += "I";
           break;
         default:
-        case perfetto::protos::TrackEvent::TYPE_UNSPECIFIED:
+        case perfetto::protos::gen::TrackEvent::TYPE_UNSPECIFIED:
           EXPECT_FALSE(track_event.type());
       }
-      slice += ":" + categories[track_event.category_iids().Get(0)] + "." +
+      slice += ":" + categories[track_event.category_iids()[0]] + "." +
                event_names[track_event.name_iid()];
 
       if (track_event.debug_annotations_size()) {
@@ -533,10 +549,10 @@
   ASSERT_GE(raw_trace.size(), 0u);
 
   // Read back the trace, maintaining interning tables as we go.
-  perfetto::protos::Trace trace;
+  perfetto::protos::gen::Trace trace;
   std::map<uint64_t, std::string> categories;
   std::map<uint64_t, std::string> event_names;
-  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
 
   bool incremental_state_was_cleared = false;
   bool begin_found = false;
@@ -601,19 +617,20 @@
         perfetto::protos::pbzero::ClockSnapshot::Clock::MONOTONIC;
     EXPECT_EQ(packet.timestamp_clock_id(), kClockMonotonic);
 #endif
-    EXPECT_EQ(track_event.category_iids().size(), 1);
-    EXPECT_GE(track_event.category_iids().Get(0), 1u);
+    EXPECT_EQ(track_event.category_iids().size(), 1u);
+    EXPECT_GE(track_event.category_iids()[0], 1u);
 
-    if (track_event.type() == perfetto::protos::TrackEvent::TYPE_SLICE_BEGIN) {
+    if (track_event.type() ==
+        perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN) {
       EXPECT_FALSE(begin_found);
-      EXPECT_EQ("test", categories[track_event.category_iids().Get(0)]);
+      EXPECT_EQ("test", categories[track_event.category_iids()[0]]);
       EXPECT_EQ("TestEvent", event_names[track_event.name_iid()]);
       begin_found = true;
     } else if (track_event.type() ==
-               perfetto::protos::TrackEvent::TYPE_SLICE_END) {
+               perfetto::protos::gen::TrackEvent::TYPE_SLICE_END) {
       EXPECT_FALSE(end_found);
       EXPECT_EQ(0u, track_event.name_iid());
-      EXPECT_EQ("test", categories[track_event.category_iids().Get(0)]);
+      EXPECT_EQ("test", categories[track_event.category_iids()[0]]);
       end_found = true;
     }
   }
@@ -734,9 +751,8 @@
   EXPECT_THAT(trace, HasSubstr("FooEventFromModule2"));
   EXPECT_THAT(trace, Not(HasSubstr("DisabledEventFromModule2")));
 
-  perfetto::protos::Trace parsed_trace;
-  ASSERT_TRUE(
-      parsed_trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+  perfetto::protos::gen::Trace parsed_trace;
+  ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
 
   uint32_t sequence_id = 0;
   for (const auto& packet : parsed_trace.packet()) {
@@ -841,16 +857,16 @@
   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
   std::string trace(raw_trace.data(), raw_trace.size());
 
-  perfetto::protos::Trace parsed_trace;
-  ASSERT_TRUE(
-      parsed_trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+  perfetto::protos::gen::Trace parsed_trace;
+  ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
 
   bool found_args = false;
   for (const auto& packet : parsed_trace.packet()) {
     if (!packet.has_track_event())
       continue;
     const auto& track_event = packet.track_event();
-    if (track_event.type() != perfetto::protos::TrackEvent::TYPE_SLICE_BEGIN)
+    if (track_event.type() !=
+        perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN)
       continue;
 
     EXPECT_TRUE(track_event.has_log_message());
@@ -858,7 +874,7 @@
     EXPECT_EQ(1u, log.source_location_iid());
     EXPECT_EQ(2u, log.body_iid());
 
-    const auto& dbg = track_event.debug_annotations().Get(0);
+    const auto& dbg = track_event.debug_annotations()[0];
     EXPECT_EQ("random", dbg.name());
     EXPECT_EQ(random_value, dbg.int_value());
 
@@ -1286,6 +1302,27 @@
                   "B:test.E(plain_arg=(int)42,raw_arg=(nested)nested_value)"));
 }
 
+TEST_F(PerfettoApiTest, TrackEventComputedName) {
+  // Setup the trace config.
+  perfetto::TraceConfig cfg;
+  cfg.set_duration_ms(500);
+  cfg.add_buffers()->set_size_kb(1024);
+  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+  ds_cfg->set_name("track_event");
+
+  // Create a new trace session.
+  auto* tracing_session = NewTrace(cfg);
+  tracing_session->get()->StartBlocking();
+
+  for (int i = 0; i < 3; i++)
+    TRACE_EVENT_BEGIN("test", i % 2 ? "Odd" : "Even");
+  perfetto::TrackEvent::Flush();
+
+  tracing_session->get()->StopBlocking();
+  auto slices = ReadSlicesFromTrace(tracing_session->get());
+  EXPECT_THAT(slices, ElementsAre("B:test.Even", "B:test.Odd", "B:test.Even"));
+}
+
 TEST_F(PerfettoApiTest, TrackEventArgumentsNotEvaluatedWhenDisabled) {
   // Setup the trace config.
   perfetto::TraceConfig cfg;
@@ -1378,8 +1415,8 @@
   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
   ASSERT_GE(raw_trace.size(), 0u);
 
-  perfetto::protos::Trace trace;
-  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+  perfetto::protos::gen::Trace trace;
+  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
   bool test_packet_found = false;
   for (const auto& packet : trace.packet()) {
     if (!packet.has_for_testing())
@@ -1489,8 +1526,8 @@
   // Check the contents of the trace.
   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
   ASSERT_GE(raw_trace.size(), 0u);
-  perfetto::protos::Trace trace;
-  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+  perfetto::protos::gen::Trace trace;
+  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
   int test_packet_found = 0;
   for (const auto& packet : trace.packet()) {
     if (!packet.has_for_testing())
@@ -1666,8 +1703,8 @@
   std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
   ASSERT_GE(raw_trace.size(), 0u);
 
-  perfetto::protos::Trace trace;
-  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+  perfetto::protos::gen::Trace trace;
+  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
   int packets_found = 0;
   for (const auto& packet : trace.packet()) {
     if (!packet.has_for_testing())
diff --git a/src/tracing/core/packet_stream_validator_unittest.cc b/src/tracing/core/packet_stream_validator_unittest.cc
index bdb8ffd..fab2a60 100644
--- a/src/tracing/core/packet_stream_validator_unittest.cc
+++ b/src/tracing/core/packet_stream_validator_unittest.cc
@@ -18,7 +18,11 @@
 
 #include <string>
 
-#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
+#include "protos/perfetto/trace/ftrace/sched.gen.h"
+#include "protos/perfetto/trace/test_event.gen.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
 #include "test/gtest_and_gmock.h"
 
 namespace perfetto {
@@ -31,7 +35,7 @@
 }
 
 TEST(PacketStreamValidatorTest, SimplePacket) {
-  protos::TracePacket proto;
+  protos::gen::TracePacket proto;
   proto.mutable_for_testing()->set_str("string field");
   std::string ser_buf = proto.SerializeAsString();
 
@@ -41,7 +45,7 @@
 }
 
 TEST(PacketStreamValidatorTest, ComplexPacket) {
-  protos::TracePacket proto;
+  protos::gen::TracePacket proto;
   proto.mutable_for_testing()->set_str("string field");
   proto.mutable_ftrace_events()->set_cpu(0);
   auto* ft = proto.mutable_ftrace_events()->add_event();
@@ -58,7 +62,7 @@
 }
 
 TEST(PacketStreamValidatorTest, SimplePacketWithUid) {
-  protos::TracePacket proto;
+  protos::gen::TracePacket proto;
   proto.set_trusted_uid(123);
   std::string ser_buf = proto.SerializeAsString();
 
@@ -68,7 +72,7 @@
 }
 
 TEST(PacketStreamValidatorTest, SimplePacketWithZeroUid) {
-  protos::TracePacket proto;
+  protos::gen::TracePacket proto;
   proto.set_trusted_uid(0);
   std::string ser_buf = proto.SerializeAsString();
 
@@ -78,7 +82,7 @@
 }
 
 TEST(PacketStreamValidatorTest, SimplePacketWithNegativeOneUid) {
-  protos::TracePacket proto;
+  protos::gen::TracePacket proto;
   proto.set_trusted_uid(-1);
   std::string ser_buf = proto.SerializeAsString();
 
@@ -88,7 +92,7 @@
 }
 
 TEST(PacketStreamValidatorTest, ComplexPacketWithUid) {
-  protos::TracePacket proto;
+  protos::gen::TracePacket proto;
   proto.mutable_for_testing()->set_str("string field");
   proto.mutable_ftrace_events()->set_cpu(0);
   auto* ft = proto.mutable_ftrace_events()->add_event();
@@ -106,7 +110,7 @@
 }
 
 TEST(PacketStreamValidatorTest, FragmentedPacket) {
-  protos::TracePacket proto;
+  protos::gen::TracePacket proto;
   proto.mutable_for_testing()->set_str("string field");
   proto.mutable_ftrace_events()->set_cpu(0);
   auto* ft = proto.mutable_ftrace_events()->add_event();
@@ -126,7 +130,7 @@
 }
 
 TEST(PacketStreamValidatorTest, FragmentedPacketWithUid) {
-  protos::TracePacket proto;
+  protos::gen::TracePacket proto;
   proto.mutable_for_testing()->set_str("string field");
   proto.set_trusted_uid(123);
   proto.mutable_ftrace_events()->set_cpu(0);
@@ -148,7 +152,7 @@
 }
 
 TEST(PacketStreamValidatorTest, TruncatedPacket) {
-  protos::TracePacket proto;
+  protos::gen::TracePacket proto;
   proto.mutable_for_testing()->set_str("string field");
   std::string ser_buf = proto.SerializeAsString();
 
@@ -160,7 +164,7 @@
 }
 
 TEST(PacketStreamValidatorTest, TrailingGarbage) {
-  protos::TracePacket proto;
+  protos::gen::TracePacket proto;
   proto.mutable_for_testing()->set_str("string field");
   std::string ser_buf = proto.SerializeAsString();
   ser_buf += "bike is short for bichael";
diff --git a/src/tracing/core/startup_trace_writer_unittest.cc b/src/tracing/core/startup_trace_writer_unittest.cc
index a7cd419..3942124 100644
--- a/src/tracing/core/startup_trace_writer_unittest.cc
+++ b/src/tracing/core/startup_trace_writer_unittest.cc
@@ -28,8 +28,9 @@
 #include "src/tracing/test/fake_producer_endpoint.h"
 #include "test/gtest_and_gmock.h"
 
+#include "protos/perfetto/trace/test_event.gen.h"
 #include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
@@ -146,7 +147,7 @@
       EXPECT_EQ(static_cast<uid_t>(1),
                 sequence_properties.producer_uid_trusted);
 
-      protos::TracePacket parsed_packet;
+      protos::gen::TracePacket parsed_packet;
       bool res = parsed_packet.ParseFromString(packet.GetRawBytesForTesting());
       EXPECT_TRUE(res);
       if (!res)
diff --git a/src/tracing/core/trace_packet_unittest.cc b/src/tracing/core/trace_packet_unittest.cc
index 57d6631..72f4215 100644
--- a/src/tracing/core/trace_packet_unittest.cc
+++ b/src/tracing/core/trace_packet_unittest.cc
@@ -18,15 +18,16 @@
 
 #include <string>
 
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "protos/perfetto/trace/test_event.gen.h"
+#include "protos/perfetto/trace/trace.gen.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
 #include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 namespace {
 
 TEST(TracePacketTest, Simple) {
-  protos::TracePacket proto;
+  protos::gen::TracePacket proto;
   proto.mutable_for_testing()->set_str("string field");
   std::string ser_buf = proto.SerializeAsString();
   TracePacket tp;
@@ -37,13 +38,13 @@
   ASSERT_EQ(ser_buf.size(), slice->size);
   ASSERT_EQ(tp.slices().end(), ++slice);
 
-  protos::TracePacket decoded_packet;
+  protos::gen::TracePacket decoded_packet;
   ASSERT_TRUE(decoded_packet.ParseFromString(tp.GetRawBytesForTesting()));
   ASSERT_EQ(proto.for_testing().str(), decoded_packet.for_testing().str());
 }
 
 TEST(TracePacketTest, Sliced) {
-  protos::TracePacket proto;
+  protos::gen::TracePacket proto;
   proto.mutable_for_testing()->set_str(
       "this is an arbitrarily long string ........................");
   std::string ser_buf = proto.SerializeAsString();
@@ -68,18 +69,18 @@
 
   ASSERT_EQ(tp.slices().end(), ++slice);
 
-  protos::TracePacket decoded_packet;
+  protos::gen::TracePacket decoded_packet;
   ASSERT_TRUE(decoded_packet.ParseFromString(tp.GetRawBytesForTesting()));
   ASSERT_EQ(proto.for_testing().str(), decoded_packet.for_testing().str());
 }
 
 TEST(TracePacketTest, Corrupted) {
-  protos::TracePacket proto;
+  protos::gen::TracePacket proto;
   proto.mutable_for_testing()->set_str("string field");
   std::string ser_buf = proto.SerializeAsString();
   TracePacket tp;
   tp.AddSlice({ser_buf.data(), ser_buf.size() - 2});  // corrupted.
-  protos::TracePacket decoded_packet;
+  protos::gen::TracePacket decoded_packet;
   ASSERT_FALSE(decoded_packet.ParseFromString(tp.GetRawBytesForTesting()));
 }
 
@@ -96,7 +97,7 @@
   ASSERT_EQ(0, preamble[1]);
 
   // Test packet with one slice.
-  protos::TracePacket tp_proto;
+  protos::gen::TracePacket tp_proto;
   char payload[257];
   for (size_t i = 0; i < sizeof(payload) - 1; i++)
     payload[i] = 'a' + (i % 16);
@@ -113,11 +114,10 @@
   memcpy(buf, preamble, preamble_size);
   ASSERT_EQ(1u, tp.slices().size());
   memcpy(&buf[preamble_size], tp.slices()[0].start, tp.slices()[0].size);
-  protos::Trace trace;
-  ASSERT_TRUE(
-      trace.ParseFromArray(buf, static_cast<int>(preamble_size + tp.size())));
+  protos::gen::Trace trace;
+  ASSERT_TRUE(trace.ParseFromArray(buf, preamble_size + tp.size()));
   ASSERT_EQ(1, trace.packet_size());
-  ASSERT_EQ(payload, trace.packet(0).for_testing().str());
+  ASSERT_EQ(payload, trace.packet()[0].for_testing().str());
 }
 
 TEST(TracePacketTest, MoveOperators) {
diff --git a/src/tracing/core/trace_writer_for_testing.cc b/src/tracing/core/trace_writer_for_testing.cc
index 98544b8..838f93e 100644
--- a/src/tracing/core/trace_writer_for_testing.cc
+++ b/src/tracing/core/trace_writer_for_testing.cc
@@ -19,9 +19,7 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/protozero/message.h"
-#include "protos/perfetto/trace/trace.pb.h"
 #include "protos/perfetto/trace/trace.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
@@ -45,22 +43,24 @@
     callback();
 }
 
-std::vector<protos::TracePacket> TraceWriterForTesting::GetAllTracePackets() {
+std::vector<protos::gen::TracePacket>
+TraceWriterForTesting::GetAllTracePackets() {
   PERFETTO_CHECK(cur_packet_->is_finalized());
 
-  auto trace = protos::Trace();
   std::vector<uint8_t> buffer = delegate_.StitchSlices();
-  if (!trace.ParseFromArray(buffer.data(), static_cast<int>(buffer.size())))
-    return {};
-
-  std::vector<protos::TracePacket> ret;
-  for (const auto& packet : trace.packet()) {
-    ret.emplace_back(packet);
+  protozero::ProtoDecoder trace(buffer.data(), buffer.size());
+  std::vector<protos::gen::TracePacket> ret;
+  for (auto fld = trace.ReadField(); fld.valid(); fld = trace.ReadField()) {
+    PERFETTO_CHECK(fld.id() == protos::pbzero::Trace::kPacketFieldNumber);
+    protos::gen::TracePacket packet;
+    packet.ParseFromArray(fld.data(), fld.size());
+    ret.emplace_back(std::move(packet));
   }
+  PERFETTO_CHECK(trace.bytes_left() == 0);
   return ret;
 }
 
-protos::TracePacket TraceWriterForTesting::GetOnlyTracePacket() {
+protos::gen::TracePacket TraceWriterForTesting::GetOnlyTracePacket() {
   auto packets = GetAllTracePackets();
   PERFETTO_CHECK(packets.size() == 1);
   return packets[0];
diff --git a/src/tracing/core/trace_writer_for_testing.h b/src/tracing/core/trace_writer_for_testing.h
index b71f605..f066fee 100644
--- a/src/tracing/core/trace_writer_for_testing.h
+++ b/src/tracing/core/trace_writer_for_testing.h
@@ -21,7 +21,7 @@
 #include "perfetto/ext/tracing/core/trace_writer.h"
 #include "perfetto/protozero/message_handle.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
 
 namespace perfetto {
 
@@ -38,8 +38,8 @@
   TracePacketHandle NewTracePacket() override;
   void Flush(std::function<void()> callback = {}) override;
 
-  std::vector<protos::TracePacket> GetAllTracePackets();
-  protos::TracePacket GetOnlyTracePacket();
+  std::vector<protos::gen::TracePacket> GetAllTracePackets();
+  protos::gen::TracePacket GetOnlyTracePacket();
 
   WriterID writer_id() const override;
   uint64_t written() const override;
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index 6850c0b..f40606f 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -76,6 +76,7 @@
 constexpr base::TimeMillis kSnapshotsInterval(10 * 1000);
 constexpr int kDefaultWriteIntoFilePeriodMs = 5000;
 constexpr int kMaxConcurrentTracingSessions = 15;
+constexpr int64_t kMinSecondsBetweenTracesGuardrail = 5 * 60;
 
 constexpr uint32_t kMillisPerHour = 3600000;
 constexpr uint32_t kMaxTracingDurationMillis = 7 * 24 * kMillisPerHour;
@@ -421,7 +422,7 @@
   }
 
   if (cfg.buffers_size() > kMaxBuffersPerConsumer) {
-    PERFETTO_DLOG("Too many buffers configured (%d)", cfg.buffers_size());
+    PERFETTO_ELOG("Too many buffers configured (%d)", cfg.buffers_size());
     return false;
   }
 
@@ -437,6 +438,34 @@
     }
   }
 
+  if (cfg.enable_extra_guardrails()) {
+    // unique_session_name can be empty
+    const std::string& name = cfg.unique_session_name();
+    int64_t now_s = base::GetBootTimeS().count();
+
+    // Remove any entries where the time limit has passed so this map doesn't
+    // grow indefinitely:
+    std::map<std::string, int64_t>& sessions = session_to_last_trace_s_;
+    for (auto it = sessions.cbegin(); it != sessions.cend();) {
+      if (now_s - it->second > kMinSecondsBetweenTracesGuardrail) {
+        it = sessions.erase(it);
+      } else {
+        ++it;
+      }
+    }
+
+    int64_t& previous_s = session_to_last_trace_s_[name];
+    if (previous_s == 0) {
+      previous_s = now_s;
+    } else {
+      PERFETTO_ELOG(
+          "A trace with unique session name \"%s\" began less than %" PRId64
+          "s ago (%" PRId64 "s)",
+          name.c_str(), kMinSecondsBetweenTracesGuardrail, now_s - previous_s);
+      return false;
+    }
+  }
+
   // TODO(primiano): This is a workaround to prevent that a producer gets stuck
   // in a state where it stalls by design by having more TraceWriterImpl
   // instances than free pages in the buffer. This is really a bug in
diff --git a/src/tracing/core/tracing_service_impl.h b/src/tracing/core/tracing_service_impl.h
index 36561be..61c6ef6 100644
--- a/src/tracing/core/tracing_service_impl.h
+++ b/src/tracing/core/tracing_service_impl.h
@@ -560,6 +560,7 @@
   std::set<ConsumerEndpointImpl*> consumers_;
   std::map<TracingSessionID, TracingSession> tracing_sessions_;
   std::map<BufferID, std::unique_ptr<TraceBuffer>> buffers_;
+  std::map<std::string, int64_t> session_to_last_trace_s_;
 
   bool smb_scraping_enabled_ = false;
   bool lockdown_mode_ = false;
diff --git a/src/tracing/core/tracing_service_impl_unittest.cc b/src/tracing/core/tracing_service_impl_unittest.cc
index b301612..2643cc7 100644
--- a/src/tracing/core/tracing_service_impl_unittest.cc
+++ b/src/tracing/core/tracing_service_impl_unittest.cc
@@ -36,10 +36,12 @@
 #include "src/tracing/test/test_shared_memory.h"
 #include "test/gtest_and_gmock.h"
 
+#include "protos/perfetto/trace/test_event.gen.h"
 #include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "protos/perfetto/trace/trace.gen.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "protos/perfetto/trace/trigger.gen.h"
 
 using ::testing::_;
 using ::testing::AssertionFailure;
@@ -68,15 +70,16 @@
 constexpr size_t kMaxShmSizeKb = TracingServiceImpl::kMaxShmSize / 1024;
 
 AssertionResult HasTriggerModeInternal(
-    const std::vector<protos::TracePacket>& packets,
-    protos::TraceConfig::TriggerConfig::TriggerMode mode) {
+    const std::vector<protos::gen::TracePacket>& packets,
+    protos::gen::TraceConfig::TriggerConfig::TriggerMode mode) {
   StringMatchResultListener matcher_result_string;
   bool contains = ExplainMatchResult(
       Contains(Property(
-          &protos::TracePacket::trace_config,
-          Property(&protos::TraceConfig::trigger_config,
-                   Property(&protos::TraceConfig::TriggerConfig::trigger_mode,
-                            Eq(mode))))),
+          &protos::gen::TracePacket::trace_config,
+          Property(
+              &protos::gen::TraceConfig::trigger_config,
+              Property(&protos::gen::TraceConfig::TriggerConfig::trigger_mode,
+                       Eq(mode))))),
       packets, &matcher_result_string);
   if (contains) {
     return AssertionSuccess();
@@ -222,6 +225,39 @@
   EXPECT_THAT(consumer_b->ReadBuffers(), IsEmpty());
 }
 
+TEST_F(TracingServiceImplTest, CantBackToBackConfigsForWithExtraGuardrails) {
+  {
+    std::unique_ptr<MockConsumer> consumer_a = CreateMockConsumer();
+    consumer_a->Connect(svc.get());
+
+    TraceConfig trace_config_a;
+    trace_config_a.add_buffers()->set_size_kb(128);
+    trace_config_a.set_duration_ms(0);
+    trace_config_a.set_enable_extra_guardrails(true);
+    trace_config_a.set_unique_session_name("foo");
+
+    consumer_a->EnableTracing(trace_config_a);
+    consumer_a->DisableTracing();
+    consumer_a->WaitForTracingDisabled();
+    EXPECT_THAT(consumer_a->ReadBuffers(), Not(IsEmpty()));
+  }
+
+  {
+    std::unique_ptr<MockConsumer> consumer_b = CreateMockConsumer();
+    consumer_b->Connect(svc.get());
+
+    TraceConfig trace_config_b;
+    trace_config_b.add_buffers()->set_size_kb(128);
+    trace_config_b.set_duration_ms(10000);
+    trace_config_b.set_enable_extra_guardrails(true);
+    trace_config_b.set_unique_session_name("foo");
+
+    consumer_b->EnableTracing(trace_config_b);
+    consumer_b->WaitForTracingDisabled(2000);
+    EXPECT_THAT(consumer_b->ReadBuffers(), IsEmpty());
+  }
+}
+
 TEST_F(TracingServiceImplTest, RegisterAndUnregister) {
   std::unique_ptr<MockProducer> mock_producer_1 = CreateMockProducer();
   std::unique_ptr<MockProducer> mock_producer_2 = CreateMockProducer();
@@ -330,7 +366,7 @@
 
   EXPECT_THAT(
       consumer->ReadBuffers(),
-      HasTriggerMode(protos::TraceConfig::TriggerConfig::START_TRACING));
+      HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::START_TRACING));
 }
 
 // Creates a tracing session with a START_TRACING trigger and checks that the
@@ -466,7 +502,7 @@
   consumer->WaitForTracingDisabled();
   EXPECT_THAT(
       consumer->ReadBuffers(),
-      HasTriggerMode(protos::TraceConfig::TriggerConfig::START_TRACING));
+      HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::START_TRACING));
 }
 
 // Creates a tracing session with a START_TRACING trigger and checks that the
@@ -557,7 +593,7 @@
   consumer->WaitForTracingDisabled();
   EXPECT_THAT(
       consumer->ReadBuffers(),
-      HasTriggerMode(protos::TraceConfig::TriggerConfig::START_TRACING));
+      HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::START_TRACING));
 }
 
 // Creates two tracing sessions with a START_TRACING trigger and checks that
@@ -686,10 +722,10 @@
   EXPECT_TRUE(flushed_writer_2);
   EXPECT_THAT(
       consumer_1->ReadBuffers(),
-      HasTriggerMode(protos::TraceConfig::TriggerConfig::START_TRACING));
+      HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::START_TRACING));
   EXPECT_THAT(
       consumer_2->ReadBuffers(),
-      HasTriggerMode(protos::TraceConfig::TriggerConfig::START_TRACING));
+      HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::START_TRACING));
 }
 
 // Creates a tracing session with a START_TRACING trigger and checks that the
@@ -741,21 +777,21 @@
   EXPECT_THAT(
       packets,
       Contains(Property(
-          &protos::TracePacket::trace_config,
+          &protos::gen::TracePacket::trace_config,
           Property(
-              &protos::TraceConfig::trigger_config,
-              Property(
-                  &protos::TraceConfig::TriggerConfig::trigger_mode,
-                  Eq(protos::TraceConfig::TriggerConfig::START_TRACING))))));
+              &protos::gen::TraceConfig::trigger_config,
+              Property(&protos::gen::TraceConfig::TriggerConfig::trigger_mode,
+                       Eq(protos::gen::TraceConfig::TriggerConfig::
+                              START_TRACING))))));
   auto expect_received_trigger = [&](const std::string& name) {
     return Contains(AllOf(
-        Property(
-            &protos::TracePacket::trigger,
-            AllOf(Property(&protos::Trigger::trigger_name, Eq(name)),
-                  Property(&protos::Trigger::trusted_producer_uid, Eq(123)),
-                  Property(&protos::Trigger::producer_name,
-                           Eq("mock_producer")))),
-        Property(&protos::TracePacket::trusted_packet_sequence_id,
+        Property(&protos::gen::TracePacket::trigger,
+                 AllOf(Property(&protos::gen::Trigger::trigger_name, Eq(name)),
+                       Property(&protos::gen::Trigger::trusted_producer_uid,
+                                Eq(123)),
+                       Property(&protos::gen::Trigger::producer_name,
+                                Eq("mock_producer")))),
+        Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
                  Eq(kServicePacketSequenceID))));
   };
   EXPECT_THAT(packets, expect_received_trigger("trigger_name"));
@@ -816,22 +852,22 @@
   EXPECT_THAT(
       packets,
       Contains(Property(
-          &protos::TracePacket::trace_config,
+          &protos::gen::TracePacket::trace_config,
           Property(
-              &protos::TraceConfig::trigger_config,
-              Property(
-                  &protos::TraceConfig::TriggerConfig::trigger_mode,
-                  Eq(protos::TraceConfig::TriggerConfig::STOP_TRACING))))));
+              &protos::gen::TraceConfig::trigger_config,
+              Property(&protos::gen::TraceConfig::TriggerConfig::trigger_mode,
+                       Eq(protos::gen::TraceConfig::TriggerConfig::
+                              STOP_TRACING))))));
 
   auto expect_received_trigger = [&](const std::string& name) {
     return Contains(AllOf(
-        Property(
-            &protos::TracePacket::trigger,
-            AllOf(Property(&protos::Trigger::trigger_name, Eq(name)),
-                  Property(&protos::Trigger::trusted_producer_uid, Eq(321)),
-                  Property(&protos::Trigger::producer_name,
-                           Eq("mock_producer")))),
-        Property(&protos::TracePacket::trusted_packet_sequence_id,
+        Property(&protos::gen::TracePacket::trigger,
+                 AllOf(Property(&protos::gen::Trigger::trigger_name, Eq(name)),
+                       Property(&protos::gen::Trigger::trusted_producer_uid,
+                                Eq(321)),
+                       Property(&protos::gen::Trigger::producer_name,
+                                Eq("mock_producer")))),
+        Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
                  Eq(kServicePacketSequenceID))));
   };
   EXPECT_THAT(packets, expect_received_trigger("trigger_name"));
@@ -868,13 +904,13 @@
   trigger_config->set_trigger_timeout_ms(30000);
 
   auto expect_received_trigger = [&](const std::string& name) {
-    return Contains(
-        AllOf(Property(&protos::TracePacket::trigger,
-                       AllOf(Property(&protos::Trigger::trigger_name, Eq(name)),
-                             Property(&protos::Trigger::producer_name,
-                                      Eq("mock_producer")))),
-              Property(&protos::TracePacket::trusted_packet_sequence_id,
-                       Eq(kServicePacketSequenceID))));
+    return Contains(AllOf(
+        Property(&protos::gen::TracePacket::trigger,
+                 AllOf(Property(&protos::gen::Trigger::trigger_name, Eq(name)),
+                       Property(&protos::gen::Trigger::producer_name,
+                                Eq("mock_producer")))),
+        Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
+                 Eq(kServicePacketSequenceID))));
   };
 
   consumer->EnableTracing(trace_config);
@@ -890,12 +926,12 @@
   EXPECT_THAT(
       packets,
       Contains(Property(
-          &protos::TracePacket::trace_config,
+          &protos::gen::TracePacket::trace_config,
           Property(
-              &protos::TraceConfig::trigger_config,
-              Property(
-                  &protos::TraceConfig::TriggerConfig::trigger_mode,
-                  Eq(protos::TraceConfig::TriggerConfig::STOP_TRACING))))));
+              &protos::gen::TraceConfig::trigger_config,
+              Property(&protos::gen::TraceConfig::TriggerConfig::trigger_mode,
+                       Eq(protos::gen::TraceConfig::TriggerConfig::
+                              STOP_TRACING))))));
   EXPECT_THAT(packets, expect_received_trigger("trigger_name"));
   EXPECT_THAT(packets, Not(expect_received_trigger("trigger_name_2")));
 
@@ -1041,21 +1077,24 @@
   // We expect for the TraceConfig preamble packet to be there correctly and
   // then we expect each payload to be there, but not the |large_payload|
   // packet.
-  EXPECT_THAT(packets,
-              HasTriggerMode(protos::TraceConfig::TriggerConfig::STOP_TRACING));
+  EXPECT_THAT(
+      packets,
+      HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::STOP_TRACING));
   for (size_t i = 0; i < kNumTestPackets; i++) {
     std::string payload = kPayload;
     payload += std::to_string(i);
-    EXPECT_THAT(packets, Contains(Property(
-                             &protos::TracePacket::for_testing,
-                             Property(&protos::TestEvent::str, Eq(payload)))));
+    EXPECT_THAT(packets,
+                Contains(Property(
+                    &protos::gen::TracePacket::for_testing,
+                    Property(&protos::gen::TestEvent::str, Eq(payload)))));
   }
 
   // The large payload was overwritten before we trigger and ReadBuffers so it
   // should not be in the returned data.
-  EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
-                                             Property(&protos::TestEvent::str,
-                                                      Eq(large_payload))))));
+  EXPECT_THAT(packets,
+              Not(Contains(Property(
+                  &protos::gen::TracePacket::for_testing,
+                  Property(&protos::gen::TestEvent::str, Eq(large_payload))))));
 }
 
 // Creates a tracing session with a STOP_TRACING trigger and checks that the
@@ -1111,8 +1150,9 @@
 
   producer->WaitForDataSourceStop("ds_1");
   consumer->WaitForTracingDisabled();
-  EXPECT_THAT(consumer->ReadBuffers(),
-              HasTriggerMode(protos::TraceConfig::TriggerConfig::STOP_TRACING));
+  EXPECT_THAT(
+      consumer->ReadBuffers(),
+      HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::STOP_TRACING));
 }
 
 TEST_F(TracingServiceImplTest, LockdownMode) {
@@ -1382,12 +1422,13 @@
   // Verify the contents of the file.
   std::string trace_raw;
   ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
-  protos::Trace trace;
+  protos::gen::Trace trace;
   ASSERT_TRUE(trace.ParseFromString(trace_raw));
 
   ASSERT_EQ(trace.packet_size(), kNumPreamblePackets + kNumTestPackets);
-  for (int i = 0; i < kNumTestPackets; i++) {
-    const protos::TracePacket& tp = trace.packet(kNumPreamblePackets + i);
+  for (size_t i = 0; i < kNumTestPackets; i++) {
+    const protos::gen::TracePacket& tp =
+        trace.packet()[kNumPreamblePackets + i];
     ASSERT_EQ(kPayload + std::to_string(i++), tp.for_testing().str());
   }
 }
@@ -1499,10 +1540,10 @@
   consumer->DisableTracing();
   producer->WaitForDataSourceStop("data_source");
   consumer->WaitForTracingDisabled();
-  EXPECT_THAT(
-      consumer->ReadBuffers(),
-      Contains(Property(&protos::TracePacket::for_testing,
-                        Property(&protos::TestEvent::str, Eq("payload")))));
+  EXPECT_THAT(consumer->ReadBuffers(),
+              Contains(Property(
+                  &protos::gen::TracePacket::for_testing,
+                  Property(&protos::gen::TestEvent::str, Eq("payload")))));
 }
 
 TEST_F(TracingServiceImplTest, ImplicitFlushOnTimedTraces) {
@@ -1536,10 +1577,10 @@
   producer->WaitForDataSourceStop("data_source");
   consumer->WaitForTracingDisabled();
 
-  EXPECT_THAT(
-      consumer->ReadBuffers(),
-      Contains(Property(&protos::TracePacket::for_testing,
-                        Property(&protos::TestEvent::str, Eq("payload")))));
+  EXPECT_THAT(consumer->ReadBuffers(),
+              Contains(Property(
+                  &protos::gen::TracePacket::for_testing,
+                  Property(&protos::gen::TestEvent::str, Eq("payload")))));
 }
 
 // Tests the monotonic semantic of flush request IDs, i.e., once a producer
@@ -1599,10 +1640,10 @@
   consumer->DisableTracing();
   producer->WaitForDataSourceStop("data_source");
   consumer->WaitForTracingDisabled();
-  EXPECT_THAT(
-      consumer->ReadBuffers(),
-      Contains(Property(&protos::TracePacket::for_testing,
-                        Property(&protos::TestEvent::str, Eq("payload")))));
+  EXPECT_THAT(consumer->ReadBuffers(),
+              Contains(Property(
+                  &protos::gen::TracePacket::for_testing,
+                  Property(&protos::gen::TestEvent::str, Eq("payload")))));
 }
 
 TEST_F(TracingServiceImplTest, PeriodicFlush) {
@@ -1653,8 +1694,8 @@
   auto trace_packets = consumer->ReadBuffers();
   for (int i = 0; i < kNumFlushes; i++) {
     EXPECT_THAT(trace_packets,
-                Contains(Property(&protos::TracePacket::for_testing,
-                                  Property(&protos::TestEvent::str,
+                Contains(Property(&protos::gen::TracePacket::for_testing,
+                                  Property(&protos::gen::TestEvent::str,
                                            Eq("f_" + std::to_string(i))))));
   }
 }
@@ -1999,22 +2040,26 @@
   size_t num_markers = 0;
   size_t start = 0;
   size_t end = 0;
-  protos::Trace merged_trace;
+  std::string merged_trace_raw;
   for (size_t pos = 0; pos != std::string::npos; start = end) {
     pos = trace_raw.find(kSyncMarkerStr, pos + 1);
     num_markers++;
     end = (pos == std::string::npos) ? trace_raw.size() : pos + kMarkerSize;
-    int size = static_cast<int>(end - start);
-    ASSERT_GT(size, 0);
-    protos::Trace trace_partition;
-    ASSERT_TRUE(trace_partition.ParseFromArray(trace_raw.data() + start, size));
-    merged_trace.MergeFrom(trace_partition);
+    size_t size = end - start;
+    ASSERT_GT(size, 0u);
+    std::string trace_partition_raw = trace_raw.substr(start, size);
+    protos::gen::Trace trace_partition;
+    ASSERT_TRUE(trace_partition.ParseFromString(trace_partition_raw));
+    merged_trace_raw += trace_partition_raw;
   }
   EXPECT_GE(num_markers, static_cast<size_t>(kNumMarkers));
 
-  protos::Trace whole_trace;
+  protos::gen::Trace whole_trace;
   ASSERT_TRUE(whole_trace.ParseFromString(trace_raw));
 
+  protos::gen::Trace merged_trace;
+  merged_trace.ParseFromString(merged_trace_raw);
+
   ASSERT_EQ(whole_trace.packet_size(), merged_trace.packet_size());
   EXPECT_EQ(whole_trace.SerializeAsString(), merged_trace.SerializeAsString());
 }
@@ -2114,38 +2159,43 @@
   EXPECT_THAT(
       packets,
       Contains(AllOf(
-          Property(&protos::TracePacket::for_testing,
-                   Property(&protos::TestEvent::str, Eq("payload1a1"))),
-          Property(&protos::TracePacket::trusted_uid, Eq(123)),
-          Property(&protos::TracePacket::trusted_packet_sequence_id, Eq(2u)))));
+          Property(&protos::gen::TracePacket::for_testing,
+                   Property(&protos::gen::TestEvent::str, Eq("payload1a1"))),
+          Property(&protos::gen::TracePacket::trusted_uid, Eq(123)),
+          Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
+                   Eq(2u)))));
   EXPECT_THAT(
       packets,
       Contains(AllOf(
-          Property(&protos::TracePacket::for_testing,
-                   Property(&protos::TestEvent::str, Eq("payload1a2"))),
-          Property(&protos::TracePacket::trusted_uid, Eq(123)),
-          Property(&protos::TracePacket::trusted_packet_sequence_id, Eq(2u)))));
+          Property(&protos::gen::TracePacket::for_testing,
+                   Property(&protos::gen::TestEvent::str, Eq("payload1a2"))),
+          Property(&protos::gen::TracePacket::trusted_uid, Eq(123)),
+          Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
+                   Eq(2u)))));
   EXPECT_THAT(
       packets,
       Contains(AllOf(
-          Property(&protos::TracePacket::for_testing,
-                   Property(&protos::TestEvent::str, Eq("payload1b1"))),
-          Property(&protos::TracePacket::trusted_uid, Eq(123)),
-          Property(&protos::TracePacket::trusted_packet_sequence_id, Eq(3u)))));
+          Property(&protos::gen::TracePacket::for_testing,
+                   Property(&protos::gen::TestEvent::str, Eq("payload1b1"))),
+          Property(&protos::gen::TracePacket::trusted_uid, Eq(123)),
+          Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
+                   Eq(3u)))));
   EXPECT_THAT(
       packets,
       Contains(AllOf(
-          Property(&protos::TracePacket::for_testing,
-                   Property(&protos::TestEvent::str, Eq("payload1b2"))),
-          Property(&protos::TracePacket::trusted_uid, Eq(123)),
-          Property(&protos::TracePacket::trusted_packet_sequence_id, Eq(3u)))));
+          Property(&protos::gen::TracePacket::for_testing,
+                   Property(&protos::gen::TestEvent::str, Eq("payload1b2"))),
+          Property(&protos::gen::TracePacket::trusted_uid, Eq(123)),
+          Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
+                   Eq(3u)))));
   EXPECT_THAT(
       packets,
       Contains(AllOf(
-          Property(&protos::TracePacket::for_testing,
-                   Property(&protos::TestEvent::str, Eq("payload2a1"))),
-          Property(&protos::TracePacket::trusted_uid, Eq(456)),
-          Property(&protos::TracePacket::trusted_packet_sequence_id, Eq(4u)))));
+          Property(&protos::gen::TracePacket::for_testing,
+                   Property(&protos::gen::TestEvent::str, Eq("payload2a1"))),
+          Property(&protos::gen::TracePacket::trusted_uid, Eq(456)),
+          Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
+                   Eq(4u)))));
 }
 
 TEST_F(TracingServiceImplTest, AllowedBuffers) {
@@ -2288,12 +2338,13 @@
   consumer->WaitForTracingDisabled();
 
   auto packets = consumer->ReadBuffers();
-  EXPECT_THAT(packets, Contains(Property(&protos::TracePacket::for_testing,
-                                         Property(&protos::TestEvent::str,
+  EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
+                                         Property(&protos::gen::TestEvent::str,
                                                   Eq("good_payload")))));
-  EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
-                                             Property(&protos::TestEvent::str,
-                                                      Eq("bad_payload"))))));
+  EXPECT_THAT(packets,
+              Not(Contains(Property(
+                  &protos::gen::TracePacket::for_testing,
+                  Property(&protos::gen::TestEvent::str, Eq("bad_payload"))))));
 
   consumer->FreeBuffers();
   EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer_id));
@@ -2356,9 +2407,9 @@
   consumer->WaitForTracingDisabled();
 
   auto packets = consumer->ReadBuffers();
-  EXPECT_THAT(packets, Contains(Property(
-                           &protos::TracePacket::for_testing,
-                           Property(&protos::TestEvent::str, Eq("payload")))));
+  EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
+                                         Property(&protos::gen::TestEvent::str,
+                                                  Eq("payload")))));
 }
 
 TEST_F(TracingServiceImplTest, ScrapeBuffersOnFlush) {
@@ -2404,15 +2455,16 @@
   // Chunk with the packets should have been scraped. The service can't know
   // whether the last packet was completed, so shouldn't read it.
   auto packets = consumer->ReadBuffers();
-  EXPECT_THAT(packets, Contains(Property(
-                           &protos::TracePacket::for_testing,
-                           Property(&protos::TestEvent::str, Eq("payload1")))));
-  EXPECT_THAT(packets, Contains(Property(
-                           &protos::TracePacket::for_testing,
-                           Property(&protos::TestEvent::str, Eq("payload2")))));
-  EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
-                                             Property(&protos::TestEvent::str,
-                                                      Eq("payload3"))))));
+  EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
+                                         Property(&protos::gen::TestEvent::str,
+                                                  Eq("payload1")))));
+  EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
+                                         Property(&protos::gen::TestEvent::str,
+                                                  Eq("payload2")))));
+  EXPECT_THAT(packets,
+              Not(Contains(Property(
+                  &protos::gen::TracePacket::for_testing,
+                  Property(&protos::gen::TestEvent::str, Eq("payload3"))))));
 
   // Write some more packets.
   writer->NewTracePacket()->set_for_testing()->set_str("payload4");
@@ -2427,21 +2479,24 @@
   // original one. Again, the last packet should be ignored and the first two
   // should not be read twice.
   packets = consumer->ReadBuffers();
-  EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
-                                             Property(&protos::TestEvent::str,
-                                                      Eq("payload1"))))));
-  EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
-                                             Property(&protos::TestEvent::str,
-                                                      Eq("payload2"))))));
-  EXPECT_THAT(packets, Contains(Property(
-                           &protos::TracePacket::for_testing,
-                           Property(&protos::TestEvent::str, Eq("payload3")))));
-  EXPECT_THAT(packets, Contains(Property(
-                           &protos::TracePacket::for_testing,
-                           Property(&protos::TestEvent::str, Eq("payload4")))));
-  EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
-                                             Property(&protos::TestEvent::str,
-                                                      Eq("payload5"))))));
+  EXPECT_THAT(packets,
+              Not(Contains(Property(
+                  &protos::gen::TracePacket::for_testing,
+                  Property(&protos::gen::TestEvent::str, Eq("payload1"))))));
+  EXPECT_THAT(packets,
+              Not(Contains(Property(
+                  &protos::gen::TracePacket::for_testing,
+                  Property(&protos::gen::TestEvent::str, Eq("payload2"))))));
+  EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
+                                         Property(&protos::gen::TestEvent::str,
+                                                  Eq("payload3")))));
+  EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
+                                         Property(&protos::gen::TestEvent::str,
+                                                  Eq("payload4")))));
+  EXPECT_THAT(packets,
+              Not(Contains(Property(
+                  &protos::gen::TracePacket::for_testing,
+                  Property(&protos::gen::TestEvent::str, Eq("payload5"))))));
 
   consumer->DisableTracing();
   producer->WaitForDataSourceStop("data_source");
@@ -2549,15 +2604,16 @@
   // Chunk with the packets should have been scraped. The service can't know
   // whether the last packet was completed, so shouldn't read it.
   auto packets = consumer->ReadBuffers();
-  EXPECT_THAT(packets, Contains(Property(
-                           &protos::TracePacket::for_testing,
-                           Property(&protos::TestEvent::str, Eq("payload1")))));
-  EXPECT_THAT(packets, Contains(Property(
-                           &protos::TracePacket::for_testing,
-                           Property(&protos::TestEvent::str, Eq("payload2")))));
-  EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
-                                             Property(&protos::TestEvent::str,
-                                                      Eq("payload3"))))));
+  EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
+                                         Property(&protos::gen::TestEvent::str,
+                                                  Eq("payload1")))));
+  EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
+                                         Property(&protos::gen::TestEvent::str,
+                                                  Eq("payload2")))));
+  EXPECT_THAT(packets,
+              Not(Contains(Property(
+                  &protos::gen::TracePacket::for_testing,
+                  Property(&protos::gen::TestEvent::str, Eq("payload3"))))));
 
   // Cleanup writer without causing a crash because the producer already went
   // away.
@@ -2611,15 +2667,16 @@
   // Chunk with the packets should have been scraped. The service can't know
   // whether the last packet was completed, so shouldn't read it.
   auto packets = consumer->ReadBuffers();
-  EXPECT_THAT(packets, Contains(Property(
-                           &protos::TracePacket::for_testing,
-                           Property(&protos::TestEvent::str, Eq("payload1")))));
-  EXPECT_THAT(packets, Contains(Property(
-                           &protos::TracePacket::for_testing,
-                           Property(&protos::TestEvent::str, Eq("payload2")))));
-  EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
-                                             Property(&protos::TestEvent::str,
-                                                      Eq("payload3"))))));
+  EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
+                                         Property(&protos::gen::TestEvent::str,
+                                                  Eq("payload1")))));
+  EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
+                                         Property(&protos::gen::TestEvent::str,
+                                                  Eq("payload2")))));
+  EXPECT_THAT(packets,
+              Not(Contains(Property(
+                  &protos::gen::TracePacket::for_testing,
+                  Property(&protos::gen::TestEvent::str, Eq("payload3"))))));
 }
 
 TEST_F(TracingServiceImplTest, AbortIfTraceDurationIsTooLong) {
diff --git a/src/tracing/test/mock_consumer.cc b/src/tracing/test/mock_consumer.cc
index 17a983d..e7cf3b1 100644
--- a/src/tracing/test/mock_consumer.cc
+++ b/src/tracing/test/mock_consumer.cc
@@ -97,8 +97,8 @@
   return FlushRequest(wait_for_flush_completion);
 }
 
-std::vector<protos::TracePacket> MockConsumer::ReadBuffers() {
-  std::vector<protos::TracePacket> decoded_packets;
+std::vector<protos::gen::TracePacket> MockConsumer::ReadBuffers() {
+  std::vector<protos::gen::TracePacket> decoded_packets;
   static int i = 0;
   std::string checkpoint_name = "on_read_buffers_" + std::to_string(i++);
   auto on_read_buffers = task_runner_->CreateCheckpoint(checkpoint_name);
@@ -108,7 +108,8 @@
                      std::vector<TracePacket>* packets, bool has_more) {
             for (TracePacket& packet : *packets) {
               decoded_packets.emplace_back();
-              protos::TracePacket* decoded_packet = &decoded_packets.back();
+              protos::gen::TracePacket* decoded_packet =
+                  &decoded_packets.back();
               decoded_packet->ParseFromString(packet.GetRawBytesForTesting());
             }
             if (!has_more)
diff --git a/src/tracing/test/mock_consumer.h b/src/tracing/test/mock_consumer.h
index b2f3563..a1f050e 100644
--- a/src/tracing/test/mock_consumer.h
+++ b/src/tracing/test/mock_consumer.h
@@ -25,7 +25,7 @@
 #include "perfetto/tracing/core/tracing_service_state.h"
 #include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
 
 namespace perfetto {
 
@@ -55,7 +55,7 @@
   void FreeBuffers();
   void WaitForTracingDisabled(uint32_t timeout_ms = 3000);
   FlushRequest Flush(uint32_t timeout_ms = 10000);
-  std::vector<protos::TracePacket> ReadBuffers();
+  std::vector<protos::gen::TracePacket> ReadBuffers();
   void GetTraceStats();
   void WaitForTraceStats(bool success);
   TracingServiceState QueryServiceState();
diff --git a/src/tracing/test/tracing_integration_test.cc b/src/tracing/test/tracing_integration_test.cc
index 799b614..8e4ec3a 100644
--- a/src/tracing/test/tracing_integration_test.cc
+++ b/src/tracing/test/tracing_integration_test.cc
@@ -34,10 +34,12 @@
 #include "src/tracing/core/tracing_service_impl.h"
 #include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/config/trace_config.pb.h"
+#include "protos/perfetto/config/trace_config.gen.h"
+#include "protos/perfetto/trace/clock_snapshot.gen.h"
+#include "protos/perfetto/trace/test_event.gen.h"
 #include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "protos/perfetto/trace/trace.gen.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
@@ -91,7 +93,7 @@
   }
 };
 
-void CheckTraceStats(const protos::TracePacket& packet) {
+void CheckTraceStats(const protos::gen::TracePacket& packet) {
   EXPECT_TRUE(packet.has_trace_stats());
   EXPECT_GE(packet.trace_stats().producers_seen(), 1u);
   EXPECT_EQ(1u, packet.trace_stats().producers_connected());
@@ -100,7 +102,7 @@
   EXPECT_EQ(1u, packet.trace_stats().total_buffers());
   EXPECT_EQ(1, packet.trace_stats().buffer_stats_size());
 
-  const auto& buf_stats = packet.trace_stats().buffer_stats(0);
+  const auto& buf_stats = packet.trace_stats().buffer_stats()[0];
   EXPECT_GT(buf_stats.bytes_written(), 0u);
   EXPECT_GT(buf_stats.chunks_written(), 0u);
   EXPECT_EQ(0u, buf_stats.chunks_overwritten());
@@ -238,14 +240,13 @@
   // Store the arguments passed to SetupDataSource() and later check that they
   // match the ones passed to StartDataSource().
   DataSourceInstanceID setup_id;
-  perfetto::protos::DataSourceConfig setup_cfg_proto;
+  DataSourceConfig setup_cfg_proto;
   EXPECT_CALL(producer_, SetupDataSource(_, _))
       .WillOnce(
           Invoke([&setup_id, &setup_cfg_proto](DataSourceInstanceID id,
                                                const DataSourceConfig& cfg) {
-
             setup_id = id;
-            cfg.ToProto(&setup_cfg_proto);
+            setup_cfg_proto = cfg;
           }));
   EXPECT_CALL(producer_, StartDataSource(_, _))
       .WillOnce(
@@ -254,11 +255,7 @@
                                     const DataSourceConfig& cfg) {
             // id and config should match the ones passed to SetupDataSource.
             ASSERT_EQ(id, setup_id);
-            perfetto::protos::DataSourceConfig cfg_proto;
-            cfg.ToProto(&cfg_proto);
-            ASSERT_EQ(cfg_proto.SerializeAsString(),
-                      setup_cfg_proto.SerializeAsString());
-
+            ASSERT_EQ(setup_cfg_proto, cfg);
             ASSERT_NE(0u, id);
             ds_iid = id;
             ASSERT_EQ("perfetto.test", cfg.name());
@@ -307,7 +304,7 @@
 #endif
 
             for (auto& encoded_packet : *packets) {
-              protos::TracePacket packet;
+              protos::gen::TracePacket packet;
               ASSERT_TRUE(packet.ParseFromString(
                   encoded_packet.GetRawBytesForTesting()));
               if (packet.has_for_testing()) {
@@ -319,22 +316,7 @@
                           kExpectedMinNumberOfClocks);
                 saw_clock_snapshot = true;
               } else if (packet.has_trace_config()) {
-                protos::TraceConfig config_proto;
-                trace_config.ToProto(&config_proto);
-                Slice expected_slice = Slice::Allocate(
-                    static_cast<size_t>(config_proto.ByteSize()));
-                config_proto.SerializeWithCachedSizesToArray(
-                    expected_slice.own_data());
-                Slice actual_slice = Slice::Allocate(
-                    static_cast<size_t>(packet.trace_config().ByteSize()));
-                packet.trace_config().SerializeWithCachedSizesToArray(
-                    actual_slice.own_data());
-                EXPECT_EQ(std::string(reinterpret_cast<const char*>(
-                                          expected_slice.own_data()),
-                                      expected_slice.size),
-                          std::string(reinterpret_cast<const char*>(
-                                          actual_slice.own_data()),
-                                      actual_slice.size));
+                EXPECT_EQ(packet.trace_config(), trace_config);
                 saw_trace_config = true;
               } else if (packet.has_trace_stats()) {
                 saw_trace_stats = true;
@@ -417,14 +399,14 @@
   char tmp_buf[1024];
   ssize_t rsize = read(tmp_file.fd(), tmp_buf, sizeof(tmp_buf));
   ASSERT_GT(rsize, 0);
-  protos::Trace tmp_trace;
-  ASSERT_TRUE(tmp_trace.ParseFromArray(tmp_buf, static_cast<int>(rsize)));
+  protos::gen::Trace tmp_trace;
+  ASSERT_TRUE(tmp_trace.ParseFromArray(tmp_buf, static_cast<size_t>(rsize)));
   size_t num_test_packet = 0;
   size_t num_clock_snapshot_packet = 0;
   size_t num_system_info_packet = 0;
   bool saw_trace_stats = false;
   for (int i = 0; i < tmp_trace.packet_size(); i++) {
-    const protos::TracePacket& packet = tmp_trace.packet(i);
+    const auto& packet = tmp_trace.packet()[static_cast<size_t>(i)];
     if (packet.has_for_testing()) {
       ASSERT_EQ("evt_" + std::to_string(num_test_packet++),
                 packet.for_testing().str());
@@ -516,7 +498,7 @@
           Invoke([&num_test_pack_rx, all_packets_rx](
                      std::vector<TracePacket>* packets, bool has_more) {
             for (auto& encoded_packet : *packets) {
-              protos::TracePacket packet;
+              protos::gen::TracePacket packet;
               ASSERT_TRUE(packet.ParseFromString(
                   encoded_packet.GetRawBytesForTesting()));
               if (packet.has_for_testing()) {
diff --git a/test/BUILD.gn b/test/BUILD.gn
index d30efae..0e9ff85 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -29,8 +29,10 @@
     "../protos/perfetto/config:cpp",
     "../protos/perfetto/config:zero",
     "../protos/perfetto/config/power:zero",
-    "../protos/perfetto/trace:lite",
+    "../protos/perfetto/trace:cpp",
     "../protos/perfetto/trace:zero",
+    "../protos/perfetto/trace/ftrace:cpp",
+    "../protos/perfetto/trace/power:cpp",
     "../src/base:base",
     "../src/base:test_support",
     "../src/traced/probes/ftrace",
@@ -130,6 +132,7 @@
 source_set("test_helper") {
   testonly = true
   public_deps = [
+    "../protos/perfetto/trace:cpp",
     "../src/tracing:ipc",
   ]
   deps = [
@@ -137,7 +140,6 @@
     ":task_runner_thread_delegates",
     "../gn:default_deps",
     "../include/perfetto/ext/traced",
-    "../protos/perfetto/trace:lite",
     "../protos/perfetto/trace:zero",
     "../src/base:test_support",
   ]
@@ -162,7 +164,7 @@
       "../gn:gtest_and_gmock",
       "../include/perfetto/ext/traced",
       "../protos/perfetto/config:cpp",
-      "../protos/perfetto/trace:lite",
+      "../protos/perfetto/trace:cpp",
       "../protos/perfetto/trace:zero",
       "../src/base:test_support",
     ]
diff --git a/test/cts/Android.bp b/test/cts/Android.bp
index 69803de..4871ebb 100644
--- a/test/cts/Android.bp
+++ b/test/cts/Android.bp
@@ -15,15 +15,13 @@
     "libgmock",
     "libprotobuf-cpp-lite",
     "libperfetto_client_experimental",
+    "perfetto_cts_deps",
     "perfetto_trace_protos",
   ],
   shared_libs: [
     "libandroid",
     "liblog",
   ],
-  whole_static_libs: [
-    "perfetto_cts_deps"
-  ],
   test_suites: [
     "cts",
     "vts",
diff --git a/test/cts/AndroidTest.xml b/test/cts/AndroidTest.xml
index d34d264..a6deef2 100644
--- a/test/cts/AndroidTest.xml
+++ b/test/cts/AndroidTest.xml
@@ -24,7 +24,6 @@
         <option name="test-file-name" value="CtsPerfettoProducerApp.apk" />
         <option name="test-file-name" value="CtsPerfettoDebuggableApp.apk" />
         <option name="test-file-name" value="CtsPerfettoReleaseApp.apk" />
-        <option name="test-file-name" value="CtsPerfettoProfileableApp.apk" />
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
         <option name="cleanup" value="true" />
diff --git a/test/cts/BUILD.gn b/test/cts/BUILD.gn
new file mode 100644
index 0000000..4ecb26c
--- /dev/null
+++ b/test/cts/BUILD.gn
@@ -0,0 +1,41 @@
+# Copyright (C) 2018 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.gni")
+
+assert(is_android)
+
+static_library("perfetto_cts_deps") {
+  complete_static_lib = true
+  testonly = true
+  deps = [
+    "../..:libperfetto_client_experimental",
+    "../../gn:default_deps",
+    "../../gn:gtest_and_gmock",
+    "../../include/perfetto/ext/tracing/core",
+    "../../protos/perfetto/config:cpp",
+    "../../protos/perfetto/config/profiling:cpp",
+    "../../protos/perfetto/trace:cpp",
+    "../../protos/perfetto/trace/profiling:cpp",
+    "../../src/base:test_support",
+    "../../test:test_helper",
+  ]
+  sources = [
+    "device_feature_test_cts.cc",
+    "end_to_end_integrationtest_cts.cc",
+    "heapprofd_java_test_cts.cc",
+    "heapprofd_test_cts.cc",
+    "utils.cc",
+  ]
+}
diff --git a/test/cts/device_feature_test_cts.cc b/test/cts/device_feature_test_cts.cc
index c91fe49..3ed5bc1 100644
--- a/test/cts/device_feature_test_cts.cc
+++ b/test/cts/device_feature_test_cts.cc
@@ -23,7 +23,7 @@
 TEST(PerfettoDeviceFeatureTest, TestMaxCpusForAtraceChmod) {
   // Check that there are no more than 16 CPUs so that the assumption in the
   // atrace.rc for clearing CPU buffers is valid.
-  ASSERT_LE(get_nprocs(), 16);
+  ASSERT_LE(sysconf(_SC_NPROCESSORS_CONF), 16);
 }
 
 }  // namespace perfetto
diff --git a/test/cts/end_to_end_integrationtest_cts.cc b/test/cts/end_to_end_integrationtest_cts.cc
index e174bb4..1a9407b 100644
--- a/test/cts/end_to_end_integrationtest_cts.cc
+++ b/test/cts/end_to_end_integrationtest_cts.cc
@@ -18,16 +18,13 @@
 #include <random>
 #include "test/gtest_and_gmock.h"
 
-#include "perfetto/ext/traced/traced.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "src/base/test/test_task_runner.h"
 #include "test/test_helper.h"
 
 #include "protos/perfetto/config/test_config.gen.h"
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "protos/perfetto/trace/test_event.gen.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
 
 namespace perfetto {
 
diff --git a/test/cts/heapprofd_java_test_cts.cc b/test/cts/heapprofd_java_test_cts.cc
index 8ac3760..010404b 100644
--- a/test/cts/heapprofd_java_test_cts.cc
+++ b/test/cts/heapprofd_java_test_cts.cc
@@ -26,12 +26,15 @@
 #include "test/gtest_and_gmock.h"
 #include "test/test_helper.h"
 
-#include "protos/perfetto/config/profiling/java_hprof_config.pb.h"
+#include "protos/perfetto/config/profiling/java_hprof_config.gen.h"
+#include "protos/perfetto/trace/profiling/heap_graph.gen.h"
+#include "protos/perfetto/trace/profiling/profile_common.gen.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
 
 namespace perfetto {
 namespace {
 
-std::vector<protos::TracePacket> ProfileRuntime(std::string app_name) {
+std::vector<protos::gen::TracePacket> ProfileRuntime(std::string app_name) {
   base::TestTaskRunner task_runner;
 
   // (re)start the target app's main activity
@@ -59,7 +62,7 @@
   ds_config->set_name("android.java_hprof");
   ds_config->set_target_buffer(0);
 
-  protos::JavaHprofConfig java_hprof_config;
+  protos::gen::JavaHprofConfig java_hprof_config;
   java_hprof_config.add_process_cmdline(app_name.c_str());
   ds_config->set_java_hprof_config_raw(java_hprof_config.SerializeAsString());
 
@@ -73,20 +76,20 @@
   return helper.trace();
 }
 
-void AssertGraphPresent(std::vector<protos::TracePacket> packets) {
-  ASSERT_GT(packets.size(), 0);
+void AssertGraphPresent(std::vector<protos::gen::TracePacket> packets) {
+  ASSERT_GT(packets.size(), 0u);
 
   size_t objects = 0;
   size_t roots = 0;
   for (const auto& packet : packets) {
-    objects += packet.heap_graph().objects_size();
-    roots += packet.heap_graph().roots_size();
+    objects += static_cast<size_t>(packet.heap_graph().objects_size());
+    roots += static_cast<size_t>(packet.heap_graph().roots_size());
   }
-  ASSERT_GT(objects, 0);
-  ASSERT_GT(roots, 0);
+  ASSERT_GT(objects, 0u);
+  ASSERT_GT(roots, 0u);
 }
 
-void AssertNoProfileContents(std::vector<protos::TracePacket> packets) {
+void AssertNoProfileContents(std::vector<protos::gen::TracePacket> packets) {
   // If profile packets are present, they must be empty.
   for (const auto& packet : packets) {
     ASSERT_EQ(packet.heap_graph().roots_size(), 0);
@@ -102,7 +105,7 @@
   AssertGraphPresent(packets);
 }
 
-TEST(HeapprofdJavaCtsTest, ProfileableAppRuntime) {
+TEST(HeapprofdJavaCtsTest, DISABLED_ProfileableAppRuntime) {
   std::string app_name = "android.perfetto.cts.app.profileable";
   const auto& packets = ProfileRuntime(app_name);
   AssertGraphPresent(packets);
diff --git a/test/cts/heapprofd_test_apps/Android.bp b/test/cts/heapprofd_test_apps/Android.bp
index bc2b323..e759410 100644
--- a/test/cts/heapprofd_test_apps/Android.bp
+++ b/test/cts/heapprofd_test_apps/Android.bp
@@ -51,23 +51,3 @@
         "libnativehelper_compat_libc++",
     ],
 }
-
-android_test_helper_app {
-    name: "CtsPerfettoProfileableApp",
-    // tag this module as a cts test artifact
-    test_suites: [
-        "cts",
-        "vts",
-        "general-tests",
-    ],
-
-    manifest: "AndroidManifest_profileable.xml",
-
-    compile_multilib: "both",
-    srcs: ["src/**/*.java"],
-    sdk_version: "current",
-    jni_libs: [
-        "libperfettocts_heapprofdtarget",
-        "libnativehelper_compat_libc++",
-    ],
-}
diff --git a/test/cts/heapprofd_test_cts.cc b/test/cts/heapprofd_test_cts.cc
index acb92c3..bd9c49a 100644
--- a/test/cts/heapprofd_test_cts.cc
+++ b/test/cts/heapprofd_test_cts.cc
@@ -27,7 +27,10 @@
 #include "test/gtest_and_gmock.h"
 #include "test/test_helper.h"
 
-#include "protos/perfetto/config/profiling/heapprofd_config.pb.h"
+#include "protos/perfetto/config/profiling/heapprofd_config.gen.h"
+#include "protos/perfetto/trace/profiling/profile_common.gen.h"
+#include "protos/perfetto/trace/profiling/profile_packet.gen.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
 
 namespace perfetto {
 namespace {
@@ -41,8 +44,7 @@
 static_assert(kExpectedIndividualAllocSz > kTestSamplingInterval,
               "kTestSamplingInterval invalid");
 
-
-std::vector<protos::TracePacket> ProfileRuntime(std::string app_name) {
+std::vector<protos::gen::TracePacket> ProfileRuntime(std::string app_name) {
   base::TestTaskRunner task_runner;
 
   // (re)start the target app's main activity
@@ -67,7 +69,7 @@
   ds_config->set_name("android.heapprofd");
   ds_config->set_target_buffer(0);
 
-  protos::HeapprofdConfig heapprofd_config;
+  protos::gen::HeapprofdConfig heapprofd_config;
   heapprofd_config.set_sampling_interval_bytes(kTestSamplingInterval);
   heapprofd_config.add_process_cmdline(app_name.c_str());
   heapprofd_config.set_block_client(true);
@@ -83,7 +85,7 @@
   return helper.trace();
 }
 
-std::vector<protos::TracePacket> ProfileStartup(std::string app_name) {
+std::vector<protos::gen::TracePacket> ProfileStartup(std::string app_name) {
   base::TestTaskRunner task_runner;
 
   if (IsAppRunning(app_name)) {
@@ -104,7 +106,7 @@
   ds_config->set_name("android.heapprofd");
   ds_config->set_target_buffer(0);
 
-  protos::HeapprofdConfig heapprofd_config;
+  protos::gen::HeapprofdConfig heapprofd_config;
   heapprofd_config.set_sampling_interval_bytes(kTestSamplingInterval);
   heapprofd_config.add_process_cmdline(app_name.c_str());
   heapprofd_config.set_block_client(true);
@@ -127,8 +129,8 @@
 }
 
 void AssertExpectedAllocationsPresent(
-    std::vector<protos::TracePacket> packets) {
-  ASSERT_GT(packets.size(), 0);
+    std::vector<protos::gen::TracePacket> packets) {
+  ASSERT_GT(packets.size(), 0u);
 
   // TODO(rsavitski): assert particular stack frames once we clarify the
   // expected behaviour of unwinding native libs within an apk.
@@ -152,7 +154,7 @@
   ASSERT_TRUE(found_alloc);
 }
 
-void AssertNoProfileContents(std::vector<protos::TracePacket> packets) {
+void AssertNoProfileContents(std::vector<protos::gen::TracePacket> packets) {
   // If profile packets are present, they must be empty.
   for (const auto& packet : packets) {
     ASSERT_EQ(packet.profile_packet().process_dumps_size(), 0);
@@ -173,14 +175,14 @@
   StopApp(app_name);
 }
 
-TEST(HeapprofdCtsTest, ProfileableAppRuntime) {
+TEST(HeapprofdCtsTest, DISABLED_ProfileableAppRuntime) {
   std::string app_name = "android.perfetto.cts.app.profileable";
   const auto& packets = ProfileRuntime(app_name);
   AssertExpectedAllocationsPresent(packets);
   StopApp(app_name);
 }
 
-TEST(HeapprofdCtsTest, ProfileableAppStartup) {
+TEST(HeapprofdCtsTest, DISABLED_ProfileableAppStartup) {
   std::string app_name = "android.perfetto.cts.app.profileable";
   const auto& packets = ProfileStartup(app_name);
   AssertExpectedAllocationsPresent(packets);
diff --git a/test/cts/utils.cc b/test/cts/utils.cc
index e37cbc7..1407fa1 100644
--- a/test/cts/utils.cc
+++ b/test/cts/utils.cc
@@ -82,7 +82,7 @@
         PollRunState(desired_run_state, task_runner, app_name,
                      std::move(checkpoint));
       },
-      delay_ms);
+      static_cast<uint32_t>(delay_ms));
 }
 
 void StopApp(const std::string& app_name,
diff --git a/test/end_to_end_benchmark.cc b/test/end_to_end_benchmark.cc
index 5cdedb3..91635f7 100644
--- a/test/end_to_end_benchmark.cc
+++ b/test/end_to_end_benchmark.cc
@@ -27,6 +27,7 @@
 #include "test/test_helper.h"
 
 #include "protos/perfetto/config/test_config.gen.h"
+#include "protos/perfetto/trace/test_event.gen.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
diff --git a/test/end_to_end_integrationtest.cc b/test/end_to_end_integrationtest.cc
index eab9338..209693d 100644
--- a/test/end_to_end_integrationtest.cc
+++ b/test/end_to_end_integrationtest.cc
@@ -31,12 +31,6 @@
 #include "perfetto/ext/tracing/core/trace_packet.h"
 #include "perfetto/ext/tracing/ipc/default_socket.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/config/power/android_power_config.pbzero.h"
-#include "protos/perfetto/config/test_config.gen.h"
-#include "protos/perfetto/config/trace_config.gen.h"
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/traced/probes/ftrace/ftrace_controller.h"
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
@@ -45,6 +39,19 @@
 #include "test/task_runner_thread_delegates.h"
 #include "test/test_helper.h"
 
+#include "protos/perfetto/config/power/android_power_config.pbzero.h"
+#include "protos/perfetto/config/test_config.gen.h"
+#include "protos/perfetto/config/trace_config.gen.h"
+#include "protos/perfetto/trace/ftrace/ftrace.gen.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
+#include "protos/perfetto/trace/power/battery_counters.gen.h"
+#include "protos/perfetto/trace/test_event.gen.h"
+#include "protos/perfetto/trace/trace.gen.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "protos/perfetto/trace/trigger.gen.h"
+
 namespace perfetto {
 
 namespace {
@@ -371,7 +378,7 @@
   ds_config->set_name("linux.ftrace");
   ds_config->set_target_buffer(0);
 
-  protos::FtraceConfig ftrace_config;
+  protos::gen::FtraceConfig ftrace_config;
   ftrace_config.add_ftrace_events("sched_switch");
   ftrace_config.add_ftrace_events("bar");
   ds_config->set_ftrace_config_raw(ftrace_config.SerializeAsString());
@@ -387,7 +394,9 @@
 
   for (const auto& packet : packets) {
     for (int ev = 0; ev < packet.ftrace_events().event_size(); ev++) {
-      ASSERT_TRUE(packet.ftrace_events().event(ev).has_sched_switch());
+      ASSERT_TRUE(packet.ftrace_events()
+                      .event()[static_cast<size_t>(ev)]
+                      .has_sched_switch());
     }
   }
 }
@@ -415,7 +424,7 @@
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("linux.ftrace");
 
-  protos::FtraceConfig ftrace_config;
+  protos::gen::FtraceConfig ftrace_config;
   ftrace_config.add_ftrace_events("print");
   ds_config->set_ftrace_config_raw(ftrace_config.SerializeAsString());
 
@@ -443,7 +452,7 @@
   int marker_found = 0;
   for (const auto& packet : helper.trace()) {
     for (int i = 0; i < packet.ftrace_events().event_size(); i++) {
-      const auto& ev = packet.ftrace_events().event(i);
+      const auto& ev = packet.ftrace_events().event()[static_cast<size_t>(i)];
       if (ev.has_print() && ev.print().buf().find(kMarker) != std::string::npos)
         marker_found++;
     }
@@ -814,7 +823,7 @@
   // See |message_count| and |message_size| in the TraceConfig above.
   constexpr size_t kMessageCount = 11;
   constexpr size_t kMessageSize = 32;
-  protos::TraceConfig trace_config;
+  protos::gen::TraceConfig trace_config;
   trace_config.add_buffers()->set_size_kb(1024);
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("android.perfetto.FakeProducer");
@@ -822,7 +831,7 @@
   ds_config->mutable_for_testing()->set_message_size(kMessageSize);
   auto* trigger_cfg = trace_config.mutable_trigger_config();
   trigger_cfg->set_trigger_mode(
-      protos::TraceConfig::TriggerConfig::START_TRACING);
+      protos::gen::TraceConfig::TriggerConfig::START_TRACING);
   trigger_cfg->set_trigger_timeout_ms(15000);
   auto* trigger = trigger_cfg->add_triggers();
   trigger->set_name("trigger_name");
@@ -878,19 +887,20 @@
 
   std::string trace_str;
   base::ReadFile(path, &trace_str);
-  protos::Trace trace;
+  protos::gen::Trace trace;
   ASSERT_TRUE(trace.ParseFromString(trace_str));
   EXPECT_EQ(static_cast<int>(kPreamblePackets + kMessageCount),
             trace.packet_size());
   for (const auto& packet : trace.packet()) {
-    if (packet.data_case() == protos::TracePacket::kTraceConfig) {
+    if (packet.has_trace_config()) {
       // Ensure the trace config properly includes the trigger mode we set.
-      EXPECT_EQ(protos::TraceConfig::TriggerConfig::START_TRACING,
+      auto kStartTrig = protos::gen::TraceConfig::TriggerConfig::START_TRACING;
+      EXPECT_EQ(kStartTrig,
                 packet.trace_config().trigger_config().trigger_mode());
-    } else if (packet.data_case() == protos::TracePacket::kTrigger) {
+    } else if (packet.has_trigger()) {
       // validate that the triggers are properly added to the trace.
       EXPECT_EQ("trigger_name", packet.trigger().trigger_name());
-    } else if (packet.data_case() == protos::TracePacket::kForTesting) {
+    } else if (packet.has_for_testing()) {
       // Make sure that the data size is correctly set based on what we
       // requested.
       EXPECT_EQ(kMessageSize, packet.for_testing().str().size());
@@ -902,7 +912,7 @@
   // See |message_count| and |message_size| in the TraceConfig above.
   constexpr size_t kMessageCount = 11;
   constexpr size_t kMessageSize = 32;
-  protos::TraceConfig trace_config;
+  protos::gen::TraceConfig trace_config;
   trace_config.add_buffers()->set_size_kb(1024);
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("android.perfetto.FakeProducer");
@@ -910,7 +920,7 @@
   ds_config->mutable_for_testing()->set_message_size(kMessageSize);
   auto* trigger_cfg = trace_config.mutable_trigger_config();
   trigger_cfg->set_trigger_mode(
-      protos::TraceConfig::TriggerConfig::STOP_TRACING);
+      protos::gen::TraceConfig::TriggerConfig::STOP_TRACING);
   trigger_cfg->set_trigger_timeout_ms(15000);
   auto* trigger = trigger_cfg->add_triggers();
   trigger->set_name("trigger_name");
@@ -970,17 +980,18 @@
 
   std::string trace_str;
   base::ReadFile(path, &trace_str);
-  protos::Trace trace;
+  protos::gen::Trace trace;
   ASSERT_TRUE(trace.ParseFromString(trace_str));
   EXPECT_EQ(static_cast<int>(kPreamblePackets + kMessageCount),
             trace.packet_size());
   bool seen_first_trigger = false;
   for (const auto& packet : trace.packet()) {
-    if (packet.data_case() == protos::TracePacket::kTraceConfig) {
+    if (packet.has_trace_config()) {
       // Ensure the trace config properly includes the trigger mode we set.
-      EXPECT_EQ(protos::TraceConfig::TriggerConfig::STOP_TRACING,
+      auto kStopTrig = protos::gen::TraceConfig::TriggerConfig::STOP_TRACING;
+      EXPECT_EQ(kStopTrig,
                 packet.trace_config().trigger_config().trigger_mode());
-    } else if (packet.data_case() == protos::TracePacket::kTrigger) {
+    } else if (packet.has_trigger()) {
       // validate that the triggers are properly added to the trace.
       if (!seen_first_trigger) {
         EXPECT_EQ("trigger_name", packet.trigger().trigger_name());
@@ -988,7 +999,7 @@
       } else {
         EXPECT_EQ("trigger_name_3", packet.trigger().trigger_name());
       }
-    } else if (packet.data_case() == protos::TracePacket::kForTesting) {
+    } else if (packet.has_for_testing()) {
       // Make sure that the data size is correctly set based on what we
       // requested.
       EXPECT_EQ(kMessageSize, packet.for_testing().str().size());
@@ -1006,7 +1017,7 @@
   // See |message_count| and |message_size| in the TraceConfig above.
   constexpr size_t kMessageCount = 11;
   constexpr size_t kMessageSize = 32;
-  protos::TraceConfig trace_config;
+  protos::gen::TraceConfig trace_config;
   trace_config.add_buffers()->set_size_kb(1024);
   trace_config.set_allow_user_build_tracing(true);
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
@@ -1015,7 +1026,7 @@
   ds_config->mutable_for_testing()->set_message_size(kMessageSize);
   auto* trigger_cfg = trace_config.mutable_trigger_config();
   trigger_cfg->set_trigger_mode(
-      protos::TraceConfig::TriggerConfig::STOP_TRACING);
+      protos::gen::TraceConfig::TriggerConfig::STOP_TRACING);
   trigger_cfg->set_trigger_timeout_ms(1000);
   auto* trigger = trigger_cfg->add_triggers();
   trigger->set_name("trigger_name");
@@ -1059,7 +1070,7 @@
   // See |message_count| and |message_size| in the TraceConfig above.
   constexpr size_t kMessageCount = 11;
   constexpr size_t kMessageSize = 32;
-  protos::TraceConfig trace_config;
+  protos::gen::TraceConfig trace_config;
   trace_config.add_buffers()->set_size_kb(1024);
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("android.perfetto.FakeProducer");
@@ -1067,7 +1078,7 @@
   ds_config->mutable_for_testing()->set_message_size(kMessageSize);
   auto* trigger_cfg = trace_config.mutable_trigger_config();
   trigger_cfg->set_trigger_mode(
-      protos::TraceConfig::TriggerConfig::STOP_TRACING);
+      protos::gen::TraceConfig::TriggerConfig::STOP_TRACING);
   trigger_cfg->set_trigger_timeout_ms(15000);
   auto* trigger = trigger_cfg->add_triggers();
   trigger->set_name("trigger_name");
@@ -1132,16 +1143,17 @@
 
   std::string trace_str;
   base::ReadFile(path, &trace_str);
-  protos::Trace trace;
+  protos::gen::Trace trace;
   ASSERT_TRUE(trace.ParseFromString(trace_str));
   EXPECT_LT(static_cast<int>(kMessageCount), trace.packet_size());
   bool seen_first_trigger = false;
   for (const auto& packet : trace.packet()) {
-    if (packet.data_case() == protos::TracePacket::kTraceConfig) {
+    if (packet.has_trace_config()) {
       // Ensure the trace config properly includes the trigger mode we set.
-      EXPECT_EQ(protos::TraceConfig::TriggerConfig::STOP_TRACING,
+      auto kStopTrig = protos::gen::TraceConfig::TriggerConfig::STOP_TRACING;
+      EXPECT_EQ(kStopTrig,
                 packet.trace_config().trigger_config().trigger_mode());
-    } else if (packet.data_case() == protos::TracePacket::kTrigger) {
+    } else if (packet.has_trigger()) {
       // validate that the triggers are properly added to the trace.
       if (!seen_first_trigger) {
         EXPECT_EQ("trigger_name", packet.trigger().trigger_name());
@@ -1149,7 +1161,7 @@
       } else {
         EXPECT_EQ("trigger_name_3", packet.trigger().trigger_name());
       }
-    } else if (packet.data_case() == protos::TracePacket::kForTesting) {
+    } else if (packet.has_for_testing()) {
       // Make sure that the data size is correctly set based on what we
       // requested.
       EXPECT_EQ(kMessageSize, packet.for_testing().str().size());
@@ -1161,7 +1173,7 @@
   // See |message_count| and |message_size| in the TraceConfig above.
   constexpr size_t kMessageCount = 11;
   constexpr size_t kMessageSize = 32;
-  protos::TraceConfig trace_config;
+  protos::gen::TraceConfig trace_config;
   trace_config.add_buffers()->set_size_kb(1024);
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("android.perfetto.FakeProducer");
@@ -1169,7 +1181,7 @@
   ds_config->mutable_for_testing()->set_message_size(kMessageSize);
   auto* trigger_cfg = trace_config.mutable_trigger_config();
   trigger_cfg->set_trigger_mode(
-      protos::TraceConfig::TriggerConfig::STOP_TRACING);
+      protos::gen::TraceConfig::TriggerConfig::STOP_TRACING);
   trigger_cfg->set_trigger_timeout_ms(15000);
   auto* trigger = trigger_cfg->add_triggers();
   trigger->set_name("trigger_name");
diff --git a/test/metrics/heap_profile.textproto b/test/metrics/heap_profile.textproto
index d7dcfd7..7ca4b08 100644
--- a/test/metrics/heap_profile.textproto
+++ b/test/metrics/heap_profile.textproto
@@ -14,6 +14,20 @@
     }
   }
 }
+
+packet {
+  clock_snapshot {
+    clocks: {
+      clock_id: 6 # BOOTTIME
+      timestamp: 0
+    }
+    clocks: {
+      clock_id: 4 # MONOTONIC_COARSE
+      timestamp: 10
+    }
+  }
+}
+
 packet {
   trusted_packet_sequence_id: 999
   previous_packet_dropped: true
diff --git a/test/synth_common.py b/test/synth_common.py
index 984105b..fb5f32d 100644
--- a/test/synth_common.py
+++ b/test/synth_common.py
@@ -275,6 +275,67 @@
     gpu_counter.counter_id = counter_id
     gpu_counter.int_value = value
 
+  def add_gpu_render_stages_hw_queue_spec(self, specs=[]):
+    packet = self.add_packet()
+    spec = self.packet.gpu_render_stage_event.specifications
+    for s in specs:
+      hw_queue = spec.hw_queue.add()
+      hw_queue.name = s.get('name', '')
+      if 'description' in s:
+        hw_queue.description = s['description']
+
+  def add_gpu_render_stages_stage_spec(self, specs=[]):
+    packet = self.add_packet()
+    spec = self.packet.gpu_render_stage_event.specifications
+    for s in specs:
+      stage = spec.stage.add()
+      stage.name = s.get('name', '')
+      if 'description' in s:
+        stage.description = s['description']
+
+  def add_gpu_render_stages(self,
+                            ts,
+                            event_id,
+                            duration,
+                            hw_queue_id,
+                            stage_id,
+                            context,
+                            render_target_handle=None,
+                            render_pass_handle=None,
+                            command_buffer_handle=None,
+                            submission_id=None,
+                            extra_data={}):
+    packet = self.add_packet()
+    packet.timestamp = ts
+    render_stage = self.packet.gpu_render_stage_event
+    render_stage.event_id = event_id
+    render_stage.duration = duration
+    render_stage.hw_queue_id = hw_queue_id
+    render_stage.stage_id = stage_id
+    render_stage.context = context
+    if render_target_handle is not None:
+      render_stage.render_target_handle = render_target_handle
+    if render_pass_handle is not None:
+      render_stage.render_pass_handle = render_pass_handle
+    if command_buffer_handle is not None:
+      render_stage.command_buffer_handle = command_buffer_handle
+    if submission_id is not None:
+      render_stage.submission_id = submission_id
+    for key, value in extra_data.items():
+      data = render_stage.extra_data.add()
+      data.name = key
+      if value is not None:
+        data.value = value
+
+  def add_vk_debug_marker(self, ts, pid, vk_device, obj, obj_name):
+    packet = self.add_packet()
+    packet.timestamp = ts
+    debug_marker = (self.packet.vulkan_api_event.vk_debug_utils_object_name)
+    debug_marker.pid = pid
+    debug_marker.vk_device = vk_device
+    debug_marker.object = obj
+    debug_marker.object_name = obj_name
+
   def add_gpu_log(self, ts, severity, tag, message):
     packet = self.add_packet()
     packet.timestamp = ts
diff --git a/test/test_helper.cc b/test/test_helper.cc
index 57e8b10..e716c07 100644
--- a/test/test_helper.cc
+++ b/test/test_helper.cc
@@ -19,10 +19,8 @@
 #include "perfetto/ext/traced/traced.h"
 #include "perfetto/ext/tracing/core/trace_packet.h"
 #include "test/task_runner_thread_delegates.h"
-
 #include "perfetto/ext/tracing/ipc/default_socket.h"
 
-#include "protos/perfetto/trace/trace_packet.pb.h"
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
@@ -60,7 +58,7 @@
 
 void TestHelper::OnTraceData(std::vector<TracePacket> packets, bool has_more) {
   for (auto& encoded_packet : packets) {
-    protos::TracePacket packet;
+    protos::gen::TracePacket packet;
     PERFETTO_CHECK(
         packet.ParseFromString(encoded_packet.GetRawBytesForTesting()));
     if (packet.has_clock_snapshot() || packet.has_trace_config() ||
@@ -68,8 +66,7 @@
         packet.has_system_info()) {
       continue;
     }
-    PERFETTO_CHECK(packet.optional_trusted_uid_case() ==
-                   protos::TracePacket::kTrustedUid);
+    PERFETTO_CHECK(packet.has_trusted_uid());
     trace_.push_back(std::move(packet));
   }
 
diff --git a/test/test_helper.h b/test/test_helper.h
index f20c206..11897e5 100644
--- a/test/test_helper.h
+++ b/test/test_helper.h
@@ -26,7 +26,7 @@
 #include "test/fake_producer.h"
 #include "test/task_runner_thread.h"
 
-#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
 
 namespace perfetto {
 
@@ -81,7 +81,7 @@
 
   TaskRunnerThread* service_thread() { return &service_thread_; }
   TaskRunnerThread* producer_thread() { return &producer_thread_; }
-  const std::vector<protos::TracePacket>& trace() { return trace_; }
+  const std::vector<protos::gen::TracePacket>& trace() { return trace_; }
 
  private:
   static uint64_t next_instance_num_;
@@ -95,7 +95,7 @@
   std::function<void()> on_detach_callback_;
   std::function<void(bool)> on_attach_callback_;
 
-  std::vector<protos::TracePacket> trace_;
+  std::vector<protos::gen::TracePacket> trace_;
 
   TaskRunnerThread service_thread_;
   TaskRunnerThread producer_thread_;
diff --git a/test/trace_processor/gpu_render_stages.out b/test/trace_processor/gpu_render_stages.out
index 4eaa783..7dbfd7a 100644
--- a/test/trace_processor/gpu_render_stages.out
+++ b/test/trace_processor/gpu_render_stages.out
@@ -1,19 +1,24 @@
-"track_name","ts","dur","slice_name","depth","arg_set_id","flat_key","string_value","context_id","render_target","submission_id","hw_queue_id"
-"queue 1",10,5,"stage 1",0,1,"keyOnlyTest","[NULL]",42,0,0,1
-"queue 1",10,5,"stage 1",0,1,"stencilBPP","1",42,0,0,1
-"queue 1",10,5,"stage 1",0,1,"height","1.000000",42,0,0,1
-"queue 0",20,5,"stage 2",0,2,"keyOnlyTest","[NULL]",42,0,0,0
-"queue 0",20,5,"stage 2",0,2,"height","4.000000",42,0,0,0
-"queue 1",30,5,"stage 0",0,3,"keyOnlyTest","[NULL]",42,0,0,1
-"queue 1",30,5,"stage 0",0,3,"stencilBPP","1",42,0,0,1
-"queue 1",30,5,"stage 0",0,3,"height","9.000000",42,0,0,1
-"queue 0",40,5,"stage 1",0,0,"[NULL]","[NULL]",42,0,0,0
-"queue 1",50,5,"stage 2",0,4,"keyOnlyTest","[NULL]",42,0,0,1
-"queue 1",50,5,"stage 2",0,4,"stencilBPP","1",42,0,0,1
-"queue 1",50,5,"stage 2",0,4,"height","25.000000",42,0,0,1
-"queue 0",60,5,"stage 0",0,5,"keyOnlyTest","[NULL]",42,0,0,0
-"queue 0",60,5,"stage 0",0,5,"height","36.000000",42,0,0,0
-"queue 1",70,5,"stage 1",0,6,"keyOnlyTest","[NULL]",42,0,0,1
-"queue 1",70,5,"stage 1",0,6,"stencilBPP","1",42,0,0,1
-"queue 1",70,5,"stage 1",0,6,"height","49.000000",42,0,0,1
-"queue 0",80,5,"stage 2",0,0,"[NULL]","[NULL]",42,0,0,0
+"track_name","track_desc","ts","dur","slice_name","depth","flat_key","string_value","context_id","render_target","submission_id","hw_queue_id"
+"queue 1","[NULL]",10,5,"stage 1",0,"description","stage desc 1",42,0,0,1
+"queue 1","[NULL]",10,5,"stage 1",0,"keyOnlyTest","[NULL]",42,0,0,1
+"queue 1","[NULL]",10,5,"stage 1",0,"stencilBPP","1",42,0,0,1
+"queue 1","[NULL]",10,5,"stage 1",0,"height","1",42,0,0,1
+"queue 0","queue desc 0",20,5,"stage 2",0,"keyOnlyTest","[NULL]",42,0,0,0
+"queue 0","queue desc 0",20,5,"stage 2",0,"height","4",42,0,0,0
+"queue 1","[NULL]",30,5,"stage 0",0,"keyOnlyTest","[NULL]",42,0,0,1
+"queue 1","[NULL]",30,5,"stage 0",0,"stencilBPP","1",42,0,0,1
+"queue 1","[NULL]",30,5,"stage 0",0,"height","9",42,0,0,1
+"queue 0","queue desc 0",40,5,"stage 1",0,"description","stage desc 1",42,0,0,0
+"queue 1","[NULL]",50,5,"stage 2",0,"keyOnlyTest","[NULL]",42,0,0,1
+"queue 1","[NULL]",50,5,"stage 2",0,"stencilBPP","1",42,0,0,1
+"queue 1","[NULL]",50,5,"stage 2",0,"height","25",42,0,0,1
+"queue 0","queue desc 0",60,5,"stage 0",0,"keyOnlyTest","[NULL]",42,0,0,0
+"queue 0","queue desc 0",60,5,"stage 0",0,"height","36",42,0,0,0
+"queue 1","[NULL]",70,5,"stage 1",0,"description","stage desc 1",42,0,0,1
+"queue 1","[NULL]",70,5,"stage 1",0,"keyOnlyTest","[NULL]",42,0,0,1
+"queue 1","[NULL]",70,5,"stage 1",0,"stencilBPP","1",42,0,0,1
+"queue 1","[NULL]",70,5,"stage 1",0,"height","49",42,0,0,1
+"queue 0","queue desc 0",80,5,"stage 2",0,"[NULL]","[NULL]",42,0,0,0
+"queue 0","queue desc 0",90,5,"stage 0[0x10]",0,"[NULL]","[NULL]",42,16,0,0
+"queue 0","queue desc 0",100,5,"stage 0[frame_buffer]",0,"[NULL]","[NULL]",42,16,0,0
+"queue 0","queue desc 0",110,5,"stage 0[renamed_buffer]",0,"[NULL]","[NULL]",42,16,0,0
diff --git a/test/trace_processor/gpu_render_stages.py b/test/trace_processor/gpu_render_stages.py
new file mode 100644
index 0000000..30d890c
--- /dev/null
+++ b/test/trace_processor/gpu_render_stages.py
@@ -0,0 +1,93 @@
+#!/usr/bin/python
+# Copyright (C) 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
+#
+#      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.
+
+from os import sys, path
+sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+import synth_common
+
+trace = synth_common.create_trace()
+
+trace.add_gpu_render_stages_stage_spec([{
+    'name': 'stage 0'
+}, {
+    'name': 'stage 1',
+    'description': 'stage desc 1'
+}, {
+    'name': 'stage 2'
+}])
+
+trace.add_gpu_render_stages_hw_queue_spec([{
+    'name': 'queue 0',
+    'description': 'queue desc 0'
+}, {
+    'name': 'queue 1',
+}])
+
+for i in range(1, 8):
+  extra_data = {}
+  render_target_handle = None
+  if i % 4 != 0:
+    extra_data['keyOnlyTest'] = None
+    if i % 2 != 0:
+      extra_data['stencilBPP'] = '1'
+    extra_data['height'] = str(pow(i, 2))
+
+  trace.add_gpu_render_stages(
+      ts=i * 10,
+      event_id=i,
+      duration=5,
+      hw_queue_id=i % 2,
+      stage_id=i % 3,
+      context=42,
+      extra_data=extra_data)
+
+# Test stage naming with render target handle.
+trace.add_gpu_render_stages(
+    ts=80, event_id=8, duration=5, hw_queue_id=0, stage_id=2, context=42)
+
+trace.add_gpu_render_stages(
+    ts=90,
+    event_id=9,
+    duration=5,
+    hw_queue_id=0,
+    stage_id=0,
+    context=42,
+    render_target_handle=0x10)
+
+trace.add_vk_debug_marker(
+    ts=91, pid=100, vk_device=1, obj=0x10, obj_name="frame_buffer")
+
+trace.add_gpu_render_stages(
+    ts=100,
+    event_id=10,
+    duration=5,
+    hw_queue_id=0,
+    stage_id=0,
+    context=42,
+    render_target_handle=0x10)
+
+trace.add_vk_debug_marker(
+    ts=101, pid=100, vk_device=1, obj=0x10, obj_name="renamed_buffer")
+
+trace.add_gpu_render_stages(
+    ts=110,
+    event_id=11,
+    duration=5,
+    hw_queue_id=0,
+    stage_id=0,
+    context=42,
+    render_target_handle=0x10)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/gpu_render_stages.sql b/test/trace_processor/gpu_render_stages.sql
index 978a033..dbfe545 100644
--- a/test/trace_processor/gpu_render_stages.sql
+++ b/test/trace_processor/gpu_render_stages.sql
@@ -13,9 +13,9 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 --
-SELECT track.name AS track_name, ts,dur, gpu_slice.name AS slice_name,
-    depth, gpu_slice.arg_set_id, flat_key, string_value, gpu_slice.context_id,
-    render_target, submission_id, hw_queue_id
+SELECT track.name AS track_name, gpu_track.description AS track_desc, ts, dur,
+    gpu_slice.name AS slice_name, depth, flat_key, string_value,
+    gpu_slice.context_id, render_target, submission_id, hw_queue_id
 FROM gpu_track
 LEFT JOIN track USING (id)
 INNER JOIN gpu_slice on gpu_track.id=gpu_slice.track_id
diff --git a/test/trace_processor/heap_graph.textproto b/test/trace_processor/heap_graph.textproto
index 74ec8b1..295e284 100644
--- a/test/trace_processor/heap_graph.textproto
+++ b/test/trace_processor/heap_graph.textproto
@@ -52,6 +52,7 @@
   }
 }
 packet {
+  trusted_packet_sequence_id: 999
   heap_graph {
     pid: 2
     type_names {
diff --git a/test/trace_processor/heap_graph_interleaved.textproto b/test/trace_processor/heap_graph_interleaved.textproto
new file mode 100644
index 0000000..a27462c
--- /dev/null
+++ b/test/trace_processor/heap_graph_interleaved.textproto
@@ -0,0 +1,115 @@
+packet {
+  process_tree {
+    processes {
+      pid: 1
+      ppid: 0
+      cmdline: "init"
+      uid: 0
+    }
+    processes {
+      pid: 2
+      ppid: 1
+      cmdline: "system_server"
+      uid: 1000
+    }
+  }
+}
+packet {
+  trusted_packet_sequence_id: 999
+  timestamp: 10
+  heap_graph {
+    pid: 2
+    roots {
+      root_type: ROOT_JAVA_FRAME
+      object_ids: 0x01
+    }
+    objects {
+      id: 0x01
+      type_id: 1
+      self_size: 64
+      reference_field_id: 1
+      reference_object_id: 0x02
+    }
+    objects {
+      id: 0x02
+      type_id: 2
+      self_size: 32
+    }
+    objects {
+      id: 0x03
+      type_id: 2
+      self_size: 128
+    }
+    objects {
+      id: 0x04
+      type_id: 3
+      self_size: 256
+      reference_field_id: 2
+      reference_object_id: 0x01
+    }
+    continued: true
+    index: 1
+  }
+}
+packet {
+  trusted_packet_sequence_id: 1
+  timestamp: 10
+  heap_graph {
+    pid: 3
+    roots {
+      root_type: ROOT_JAVA_FRAME
+      object_ids: 0x01
+    }
+    objects {
+      id: 0x01
+      type_id: 1
+      self_size: 64
+    }
+    type_names {
+      iid: 1
+      str: "FactoryProducerDelegateImplActor"
+    }
+    continued: false
+    index: 1
+  }
+}
+packet {
+  trusted_packet_sequence_id: 999
+  heap_graph {
+    pid: 2
+    type_names {
+      iid: 1
+      str: "FactoryProducerDelegateImplActor"
+    }
+    type_names {
+      iid: 2
+      str: "Foo"
+    }
+    type_names {
+      iid: 3
+      str: "a"
+    }
+    field_names {
+      iid: 1
+      str: "FactoryProducerDelegateImplActor.foo"
+    }
+    field_names {
+      iid: 2
+      str: "a.a"
+    }
+    continued: false
+    index: 2
+  }
+}
+packet {
+  deobfuscation_mapping {
+    obfuscated_classes {
+      obfuscated_name: "a"
+      deobfuscated_name: "DeobfuscatedA"
+      obfuscated_members {
+        obfuscated_name: "a"
+        deobfuscated_name: "deobfuscatedA"
+      }
+    }
+  }
+}
diff --git a/test/trace_processor/heap_graph_interleaved_object.out b/test/trace_processor/heap_graph_interleaved_object.out
new file mode 100644
index 0000000..c64ab68
--- /dev/null
+++ b/test/trace_processor/heap_graph_interleaved_object.out
@@ -0,0 +1,6 @@
+"id","type","upid","graph_sample_ts","object_id","self_size","retained_size","unique_retained_size","reference_set_id","reachable","type_name","deobfuscated_type_name","root_type"
+0,"heap_graph_object",3,10,1,64,64,64,0,1,"FactoryProducerDelegateImplActor","[NULL]","ROOT_JAVA_FRAME"
+1,"heap_graph_object",2,10,1,64,96,96,0,1,"FactoryProducerDelegateImplActor","[NULL]","ROOT_JAVA_FRAME"
+2,"heap_graph_object",2,10,2,32,32,32,1,1,"Foo","[NULL]","[NULL]"
+3,"heap_graph_object",2,10,3,128,-1,-1,1,0,"Foo","[NULL]","[NULL]"
+4,"heap_graph_object",2,10,4,256,-1,-1,1,0,"a","DeobfuscatedA","[NULL]"
diff --git a/test/trace_processor/heap_graph_interleaved_reference.out b/test/trace_processor/heap_graph_interleaved_reference.out
new file mode 100644
index 0000000..805e67c
--- /dev/null
+++ b/test/trace_processor/heap_graph_interleaved_reference.out
@@ -0,0 +1,3 @@
+"id","type","reference_set_id","owner_id","owned_id","field_name","deobfuscated_field_name"
+0,"heap_graph_reference",0,1,2,"FactoryProducerDelegateImplActor.foo","[NULL]"
+1,"heap_graph_reference",1,4,1,"a.a","DeobfuscatedA.deobfuscatedA"
diff --git a/test/trace_processor/index b/test/trace_processor/index
index fc2ba72..6793acd 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -122,7 +122,7 @@
 
 # GPU trace tests.
 gpu_counters.py gpu_counters.sql gpu_counters.out
-../data/gpu_trace.pb gpu_render_stages.sql gpu_render_stages.out
+gpu_render_stages.py gpu_render_stages.sql gpu_render_stages.out
 gpu_log.py gpu_log.sql gpu_log.out
 
 # Clock sync
@@ -143,6 +143,8 @@
 
 heap_graph.textproto heap_graph_object.sql heap_graph_object.out
 heap_graph.textproto heap_graph_reference.sql heap_graph_reference.out
+heap_graph_interleaved.textproto heap_graph_object.sql heap_graph_interleaved_object.out
+heap_graph_interleaved.textproto heap_graph_reference.sql heap_graph_interleaved_reference.out
 
 # TrackEvent tests.
 track_event_same_tids.textproto process_tracking.sql track_event_same_tids_threads.out
diff --git a/test/trace_processor/process_metadata_matching.out b/test/trace_processor/process_metadata_matching.out
index 616216e..e80bf61 100644
--- a/test/trace_processor/process_metadata_matching.out
+++ b/test/trace_processor/process_metadata_matching.out
@@ -5,3 +5,4 @@
 2,"system_server",1000,"[NULL]","[NULL]","[NULL]"
 3,"com.google.android.gms",10100,1,"com.google.android.gms",1234
 4,"com.google.android.gms.persistent",10100,1,"com.google.android.gms",1234
+5,"com.google.android.gms",10100,1,"com.google.android.gms",1234
diff --git a/test/trace_processor/process_metadata_matching.textproto b/test/trace_processor/process_metadata_matching.textproto
index 8325a46..c372464 100644
--- a/test/trace_processor/process_metadata_matching.textproto
+++ b/test/trace_processor/process_metadata_matching.textproto
@@ -24,6 +24,12 @@
       cmdline: "com.google.android.gms.persistent"
       uid: 10100
     }
+    processes {
+      pid: 5
+      ppid: 1
+      cmdline: "com.google.android.gms"
+      uid: 1010100
+    }
   }
 }
 packet {
diff --git a/tools/dev_server b/tools/dev_server
new file mode 100755
index 0000000..b73e28a
--- /dev/null
+++ b/tools/dev_server
@@ -0,0 +1,167 @@
+# Copyright (C) 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
+#
+#      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.
+
+#!/usr/bin/env python
+from __future__ import print_function
+import sys
+import os
+import time
+import argparse
+import socket
+import subprocess
+
+try:
+  import socketserver
+  from http.server import SimpleHTTPRequestHandler
+except ImportError:
+  import SocketServer as socketserver
+  import SimpleHTTPServer
+  SimpleHTTPRequestHandler = SimpleHTTPServer.SimpleHTTPRequestHandler
+
+
+class TCPServer(socketserver.TCPServer):
+
+  def server_bind(self):
+    self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+    self.socket.bind(self.server_address)
+
+
+class Server(object):
+
+  def __init__(self, port, directory, rebuilder):
+    self.port = port
+    self.directory = directory
+    self.rebuilder = rebuilder
+
+  def serve(self):
+    this = self
+
+    class Handler(SimpleHTTPRequestHandler):
+
+      def __init__(self, *args, **kwargs):
+        SimpleHTTPRequestHandler.__init__(self, *args, **kwargs)
+
+      def translate_path(self, path):
+        path = SimpleHTTPRequestHandler.translate_path(self, path)
+        relpath = os.path.relpath(path, os.getcwd())
+        fullpath = os.path.join(this.directory, relpath)
+        return fullpath
+
+      def do_GET(self):
+        try:
+          this.rebuilder.rebuild_if_needed()
+        except RebuildFailed as e:
+          self.send_response(200)
+          self.send_header("Content-type", "text/html")
+          self.end_headers()
+          self.wfile.write(e.stdout_and_stderr)
+          return
+        return SimpleHTTPRequestHandler.do_GET(self)
+
+    print('Starting server at http://localhost:{}'.format(self.port))
+    httpd = TCPServer(('', self.port), Handler)
+    try:
+      httpd.serve_forever()
+    except KeyboardInterrupt:
+      httpd.shutdown()
+    httpd.server_close()
+
+
+class RebuildFailed(Exception):
+
+  def __init__(self, stdout_and_stderr):
+    self.stdout_and_stderr = stdout_and_stderr
+
+
+class Rebuilder(object):
+
+  def __init__(self, command, ignored_paths):
+    self.command = command
+    self.ignored_paths = ignored_paths
+    self.last_disk_state = None
+
+  def rebuild_if_needed(self):
+    if self.last_disk_state == self.last_modified_time():
+      return
+    stdout_and_stderr, success = self.rebuild()
+    if not success:
+      message = b"Failed to build! Command output:\n\n" + stdout_and_stderr
+      raise RebuildFailed(message)
+    self.last_disk_state = self.last_modified_time()
+
+  def last_modified_time(self):
+    start_time = time.time()
+    max_mtime = 0
+    for dirpath, dirnames, filenames in os.walk('.', topdown=True):
+      dirnames[:] = [
+          n for n in dirnames
+          if not self.should_ignore_path(os.path.join(dirpath, n))
+      ]
+      for filename in filenames:
+        path = os.path.join(dirpath, filename)
+        if self.should_ignore_path(path):
+          continue
+        mtime = os.stat(path).st_mtime
+        max_mtime = max(max_mtime, mtime)
+    print(' scanned in {:.03f}s'.format(time.time() - start_time).rjust(
+        80, '='))
+    return max_mtime
+
+  def should_ignore_path(self, path):
+    return os.path.abspath(path) in (
+        os.path.abspath(p) for p in self.ignored_paths)
+
+  def rebuild(self):
+    print('Running command: {}'.format(self.command))
+    print(' begin build'.rjust(80, '='))
+    start_time = time.time()
+    status = 0
+    try:
+      stdout_and_stderr = subprocess.check_output(
+          self.command, shell=True, stderr=subprocess.STDOUT)
+    except subprocess.CalledProcessError as e:
+      status = e.returncode
+      stdout_and_stderr = e.output
+    print(stdout_and_stderr.decode('utf8'))
+    print(' built in {:.03f}s'.format(time.time() - start_time).rjust(80, '='))
+    return stdout_and_stderr, status == 0
+
+
+def main(argv):
+  parser = argparse.ArgumentParser(description='HTTP server for UI development')
+  parser.add_argument(
+      '-p',
+      '--port',
+      help='port number (default: 3000)',
+      type=int,
+      default=3000)
+  parser.add_argument(
+      '-i', '--ignore', default=[], action='append', help='Ignore this path')
+  parser.add_argument(
+      '-s',
+      '--serve',
+      default=os.getcwd(),
+      help='Serve this directory (default: current directory)')
+  parser.add_argument('command', default='', nargs='?', help='Command to run')
+
+  args = parser.parse_args(argv)
+
+  rebuilder = Rebuilder(args.command, args.ignore)
+  server = Server(args.port, args.serve, rebuilder)
+  server.serve()
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv[1:]))
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index fa689ca..c00e697 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -61,6 +61,7 @@
     '//src/profiling/perf:traced_perf',
     '//src/traced/probes:traced_probes',
     '//src/traced/service:traced',
+    '//test/cts:perfetto_cts_deps',
 ]
 
 # Host targets
@@ -169,8 +170,9 @@
 }
 
 
-def enable_gmock(module):
+def enable_gtest_and_gmock(module):
   module.static_libs.add('libgmock')
+  module.static_libs.add('libgtest')
 
 
 def enable_protobuf_full(module):
@@ -224,7 +226,7 @@
     '//gn:default_deps': lambda x: None,
     '//gn:gtest_main': lambda x: None,
     '//gn:protoc': lambda x: None,
-    '//gn:gtest_and_gmock': enable_gmock,
+    '//gn:gtest_and_gmock': enable_gtest_and_gmock,
     '//gn:libunwind': enable_libunwind,
     '//gn:protobuf_full': enable_protobuf_full,
     '//gn:protobuf_lite': enable_protobuf_lite,
diff --git a/tools/gen_binary_descriptors b/tools/gen_binary_descriptors
index e980379..439d596 100755
--- a/tools/gen_binary_descriptors
+++ b/tools/gen_binary_descriptors
@@ -35,6 +35,8 @@
         'src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h',
     'src/protozero/test/example_proto/test_messages.proto':
         'src/protozero/test/example_proto/test_messages.descriptor.h',
+    'protos/perfetto/trace/track_event/track_event.proto':
+        'src/trace_processor/importers/proto/track_event.descriptor.h',
 }
 
 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
diff --git a/tools/gen_merged_protos b/tools/gen_merged_protos
index 1289e37..1dee4a7 100755
--- a/tools/gen_merged_protos
+++ b/tools/gen_merged_protos
@@ -112,6 +112,7 @@
     'protos/perfetto/trace/gpu/gpu_counter_event.proto',
     'protos/perfetto/trace/gpu/gpu_log.proto',
     'protos/perfetto/trace/gpu/gpu_render_stage_event.proto',
+    'protos/perfetto/trace/gpu/vulkan_api_event.proto',
 )
 
 MERGED_TRACE_PROTO = 'protos/perfetto/trace/perfetto_trace.proto'
diff --git a/ui/bs-config.js b/ui/bs-config.js
deleted file mode 100644
index b93c74c..0000000
--- a/ui/bs-config.js
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (C) 2018 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.
-
-/**
- * Configuration file for lite-server. Contains configuration for auto rerunning
- * ninja on file change.
- */
-'use strict';
-
-const { spawn } = require('child_process');
-const path = require('path');
-
-// Print without added new line.
-const print = data => process.stdout.write(data);
-const printErr = data => process.stderr.write(data);
-
-const ninjaOutDir = process.env.OUT_DIR;
-const uiOutDir = path.join(ninjaOutDir, 'ui');
-const perfettoRoot = process.env.ROOT_DIR;
-const ninjaPath = path.join(perfettoRoot, 'tools', 'ninja');
-let ninjaRunning = false;
-
-function rebasePath(relative_path) {
-  return path.join(perfettoRoot, relative_path);
-}
-
-module.exports = function(bs) {
-  return {
-    files: [
-      {
-        match: [
-          "ui/**",
-          "src/trace_processor/**",
-          "protos/**",
-        ].map(rebasePath),
-        fn: function(event, file) {
-          console.log(`Change detected on ${file}`);
-          if (ninjaRunning) {
-            console.log("Already have a ninja build running. Doing nothing.");
-            return;
-          }
-
-          ninjaRunning = true;
-
-          console.log(`Executing: ninja -C ${ninjaOutDir} ui`);
-          const ninja = spawn(ninjaPath, ['-C', ninjaOutDir, 'ui']);
-          ninja.stdout.on('data', data => print(data.toString()));
-          ninja.stderr.on('data', data => printErr(data.toString()));
-
-          // We can be smarter and load just the file we need. Need to
-          // resolve to the dist/location of the file in that case.
-          // For now, we're reloading the whole page.
-          ninja.on('exit', () => {
-            ninjaRunning = false;
-            bs.reload();
-          });
-        },
-        options: {
-          ignored: [
-            "ui/dist/",
-            "ui/.git/",
-            "ui/node_modules/",
-          ].map(rebasePath),
-          ignoreInitial: true,
-        }
-      }
-    ],
-    server: {
-      baseDir: uiOutDir,
-    },
-  };
-};
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 61d7ad6..2b06d8c 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -200,16 +200,6 @@
       "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
       "dev": true
     },
-    "accepts": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
-      "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
-      "dev": true,
-      "requires": {
-        "mime-types": "~2.1.18",
-        "negotiator": "0.6.1"
-      }
-    },
     "acorn": {
       "version": "5.7.3",
       "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
@@ -240,12 +230,6 @@
       "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==",
       "dev": true
     },
-    "after": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
-      "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
-      "dev": true
-    },
     "ajv": {
       "version": "6.9.1",
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz",
@@ -661,12 +645,6 @@
       "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
       "dev": true
     },
-    "arraybuffer.slice": {
-      "version": "0.0.7",
-      "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
-      "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==",
-      "dev": true
-    },
     "arrify": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
@@ -709,18 +687,6 @@
         "lodash": "^4.17.11"
       }
     },
-    "async-each": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
-      "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
-      "dev": true
-    },
-    "async-each-series": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-0.1.1.tgz",
-      "integrity": "sha1-dhfBkXQB/Yykooqtzj266Yr+tDI=",
-      "dev": true
-    },
     "async-foreach": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
@@ -983,12 +949,6 @@
       "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
       "dev": true
     },
-    "backo2": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
-      "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
-      "dev": true
-    },
     "balanced-match": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@@ -1062,24 +1022,6 @@
         }
       }
     },
-    "base64-arraybuffer": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
-      "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
-      "dev": true
-    },
-    "base64id": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
-      "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=",
-      "dev": true
-    },
-    "batch": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
-      "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
-      "dev": true
-    },
     "bcrypt-pbkdf": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
@@ -1089,27 +1031,6 @@
         "tweetnacl": "^0.14.3"
       }
     },
-    "better-assert": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
-      "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
-      "dev": true,
-      "requires": {
-        "callsite": "1.0.0"
-      }
-    },
-    "binary-extensions": {
-      "version": "1.13.0",
-      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz",
-      "integrity": "sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw==",
-      "dev": true
-    },
-    "blob": {
-      "version": "0.0.5",
-      "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
-      "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==",
-      "dev": true
-    },
     "block-stream": {
       "version": "0.0.9",
       "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@@ -1163,565 +1084,6 @@
         }
       }
     },
-    "browser-sync": {
-      "version": "2.26.7",
-      "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.26.7.tgz",
-      "integrity": "sha512-lY3emme0OyvA2ujEMpRmyRy9LY6gHLuTr2/ABxhIm3lADOiRXzP4dgekvnDrQqZ/Ec2Fz19lEjm6kglSG5766w==",
-      "dev": true,
-      "requires": {
-        "browser-sync-client": "^2.26.6",
-        "browser-sync-ui": "^2.26.4",
-        "bs-recipes": "1.3.4",
-        "bs-snippet-injector": "^2.0.1",
-        "chokidar": "^2.0.4",
-        "connect": "3.6.6",
-        "connect-history-api-fallback": "^1",
-        "dev-ip": "^1.0.1",
-        "easy-extender": "^2.3.4",
-        "eazy-logger": "^3",
-        "etag": "^1.8.1",
-        "fresh": "^0.5.2",
-        "fs-extra": "3.0.1",
-        "http-proxy": "1.15.2",
-        "immutable": "^3",
-        "localtunnel": "1.9.2",
-        "micromatch": "^3.1.10",
-        "opn": "5.3.0",
-        "portscanner": "2.1.1",
-        "qs": "6.2.3",
-        "raw-body": "^2.3.2",
-        "resp-modifier": "6.0.2",
-        "rx": "4.1.0",
-        "send": "0.16.2",
-        "serve-index": "1.9.1",
-        "serve-static": "1.13.2",
-        "server-destroy": "1.0.1",
-        "socket.io": "2.1.1",
-        "ua-parser-js": "0.7.17",
-        "yargs": "6.4.0"
-      },
-      "dependencies": {
-        "arr-diff": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
-          "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
-          "dev": true
-        },
-        "array-unique": {
-          "version": "0.3.2",
-          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
-          "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
-          "dev": true
-        },
-        "axios": {
-          "version": "0.19.0",
-          "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz",
-          "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==",
-          "dev": true,
-          "requires": {
-            "follow-redirects": "1.5.10",
-            "is-buffer": "^2.0.2"
-          }
-        },
-        "braces": {
-          "version": "2.3.2",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
-          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
-          "dev": true,
-          "requires": {
-            "arr-flatten": "^1.1.0",
-            "array-unique": "^0.3.2",
-            "extend-shallow": "^2.0.1",
-            "fill-range": "^4.0.0",
-            "isobject": "^3.0.1",
-            "repeat-element": "^1.1.2",
-            "snapdragon": "^0.8.1",
-            "snapdragon-node": "^2.0.1",
-            "split-string": "^3.0.2",
-            "to-regex": "^3.0.1"
-          },
-          "dependencies": {
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            }
-          }
-        },
-        "browser-sync-client": {
-          "version": "2.26.6",
-          "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.26.6.tgz",
-          "integrity": "sha512-mGrkZdNzttKdf/16I+y+2dTQxoMCIpKbVIMJ/uP8ZpnKu9f9qa/2CYVtLtbjZG8nsM14EwiCrjuFTGBEnT3Gjw==",
-          "dev": true,
-          "requires": {
-            "etag": "1.8.1",
-            "fresh": "0.5.2",
-            "mitt": "^1.1.3",
-            "rxjs": "^5.5.6"
-          }
-        },
-        "browser-sync-ui": {
-          "version": "2.26.4",
-          "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.26.4.tgz",
-          "integrity": "sha512-u20P3EsZoM8Pt+puoi3BU3KlbQAH1lAcV+/O4saF26qokrBqIDotmGonfWwoRbUmdxZkM9MBmA0K39ZTG1h4sA==",
-          "dev": true,
-          "requires": {
-            "async-each-series": "0.1.1",
-            "connect-history-api-fallback": "^1",
-            "immutable": "^3",
-            "server-destroy": "1.0.1",
-            "socket.io-client": "^2.0.4",
-            "stream-throttle": "^0.1.3"
-          }
-        },
-        "camelcase": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
-          "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
-          "dev": true
-        },
-        "cliui": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
-          "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
-          "dev": true,
-          "requires": {
-            "string-width": "^1.0.1",
-            "strip-ansi": "^3.0.1",
-            "wrap-ansi": "^2.0.0"
-          }
-        },
-        "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-          "dev": true,
-          "requires": {
-            "ms": "^2.1.1"
-          },
-          "dependencies": {
-            "ms": {
-              "version": "2.1.2",
-              "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-              "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-              "dev": true
-            }
-          }
-        },
-        "expand-brackets": {
-          "version": "2.1.4",
-          "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
-          "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
-          "dev": true,
-          "requires": {
-            "debug": "^2.3.3",
-            "define-property": "^0.2.5",
-            "extend-shallow": "^2.0.1",
-            "posix-character-classes": "^0.1.0",
-            "regex-not": "^1.0.0",
-            "snapdragon": "^0.8.1",
-            "to-regex": "^3.0.1"
-          },
-          "dependencies": {
-            "debug": {
-              "version": "2.6.9",
-              "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-              "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-              "dev": true,
-              "requires": {
-                "ms": "2.0.0"
-              }
-            },
-            "define-property": {
-              "version": "0.2.5",
-              "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-              "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-              "dev": true,
-              "requires": {
-                "is-descriptor": "^0.1.0"
-              }
-            },
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            },
-            "is-accessor-descriptor": {
-              "version": "0.1.6",
-              "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-              "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
-              "dev": true,
-              "requires": {
-                "kind-of": "^3.0.2"
-              },
-              "dependencies": {
-                "kind-of": {
-                  "version": "3.2.2",
-                  "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                  "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-                  "dev": true,
-                  "requires": {
-                    "is-buffer": "^1.1.5"
-                  }
-                }
-              }
-            },
-            "is-buffer": {
-              "version": "1.1.6",
-              "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-              "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
-              "dev": true
-            },
-            "is-data-descriptor": {
-              "version": "0.1.4",
-              "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-              "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
-              "dev": true,
-              "requires": {
-                "kind-of": "^3.0.2"
-              },
-              "dependencies": {
-                "kind-of": {
-                  "version": "3.2.2",
-                  "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                  "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-                  "dev": true,
-                  "requires": {
-                    "is-buffer": "^1.1.5"
-                  }
-                }
-              }
-            },
-            "is-descriptor": {
-              "version": "0.1.6",
-              "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
-              "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
-              "dev": true,
-              "requires": {
-                "is-accessor-descriptor": "^0.1.6",
-                "is-data-descriptor": "^0.1.4",
-                "kind-of": "^5.0.0"
-              }
-            },
-            "kind-of": {
-              "version": "5.1.0",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-              "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
-              "dev": true
-            }
-          }
-        },
-        "extglob": {
-          "version": "2.0.4",
-          "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
-          "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
-          "dev": true,
-          "requires": {
-            "array-unique": "^0.3.2",
-            "define-property": "^1.0.0",
-            "expand-brackets": "^2.1.4",
-            "extend-shallow": "^2.0.1",
-            "fragment-cache": "^0.2.1",
-            "regex-not": "^1.0.0",
-            "snapdragon": "^0.8.1",
-            "to-regex": "^3.0.1"
-          },
-          "dependencies": {
-            "define-property": {
-              "version": "1.0.0",
-              "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-              "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-              "dev": true,
-              "requires": {
-                "is-descriptor": "^1.0.0"
-              }
-            },
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            }
-          }
-        },
-        "fill-range": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
-          "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
-          "dev": true,
-          "requires": {
-            "extend-shallow": "^2.0.1",
-            "is-number": "^3.0.0",
-            "repeat-string": "^1.6.1",
-            "to-regex-range": "^2.1.0"
-          },
-          "dependencies": {
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            }
-          }
-        },
-        "follow-redirects": {
-          "version": "1.5.10",
-          "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
-          "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
-          "dev": true,
-          "requires": {
-            "debug": "=3.1.0"
-          },
-          "dependencies": {
-            "debug": {
-              "version": "3.1.0",
-              "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-              "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-              "dev": true,
-              "requires": {
-                "ms": "2.0.0"
-              }
-            }
-          }
-        },
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-buffer": {
-          "version": "2.0.4",
-          "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
-          "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==",
-          "dev": true
-        },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^1.0.0",
-            "is-data-descriptor": "^1.0.0",
-            "kind-of": "^6.0.2"
-          }
-        },
-        "is-fullwidth-code-point": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
-          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
-          "dev": true,
-          "requires": {
-            "number-is-nan": "^1.0.0"
-          }
-        },
-        "is-number": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
-          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          },
-          "dependencies": {
-            "is-buffer": {
-              "version": "1.1.6",
-              "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-              "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
-              "dev": true
-            },
-            "kind-of": {
-              "version": "3.2.2",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "dev": true,
-              "requires": {
-                "is-buffer": "^1.1.5"
-              }
-            }
-          }
-        },
-        "isobject": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
-          "dev": true
-        },
-        "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
-          "dev": true
-        },
-        "localtunnel": {
-          "version": "1.9.2",
-          "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.2.tgz",
-          "integrity": "sha512-NEKF7bDJE9U3xzJu3kbayF0WTvng6Pww7tzqNb/XtEARYwqw7CKEX7BvOMg98FtE9es2CRizl61gkV3hS8dqYg==",
-          "dev": true,
-          "requires": {
-            "axios": "0.19.0",
-            "debug": "4.1.1",
-            "openurl": "1.1.1",
-            "yargs": "6.6.0"
-          },
-          "dependencies": {
-            "yargs": {
-              "version": "6.6.0",
-              "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz",
-              "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=",
-              "dev": true,
-              "requires": {
-                "camelcase": "^3.0.0",
-                "cliui": "^3.2.0",
-                "decamelize": "^1.1.1",
-                "get-caller-file": "^1.0.1",
-                "os-locale": "^1.4.0",
-                "read-pkg-up": "^1.0.1",
-                "require-directory": "^2.1.1",
-                "require-main-filename": "^1.0.1",
-                "set-blocking": "^2.0.0",
-                "string-width": "^1.0.2",
-                "which-module": "^1.0.0",
-                "y18n": "^3.2.1",
-                "yargs-parser": "^4.2.0"
-              }
-            }
-          }
-        },
-        "micromatch": {
-          "version": "3.1.10",
-          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
-          "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
-          "dev": true,
-          "requires": {
-            "arr-diff": "^4.0.0",
-            "array-unique": "^0.3.2",
-            "braces": "^2.3.1",
-            "define-property": "^2.0.2",
-            "extend-shallow": "^3.0.2",
-            "extglob": "^2.0.4",
-            "fragment-cache": "^0.2.1",
-            "kind-of": "^6.0.2",
-            "nanomatch": "^1.2.9",
-            "object.pick": "^1.3.0",
-            "regex-not": "^1.0.0",
-            "snapdragon": "^0.8.1",
-            "to-regex": "^3.0.2"
-          }
-        },
-        "os-locale": {
-          "version": "1.4.0",
-          "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
-          "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
-          "dev": true,
-          "requires": {
-            "lcid": "^1.0.0"
-          }
-        },
-        "qs": {
-          "version": "6.2.3",
-          "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz",
-          "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=",
-          "dev": true
-        },
-        "string-width": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
-          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
-          "dev": true,
-          "requires": {
-            "code-point-at": "^1.0.0",
-            "is-fullwidth-code-point": "^1.0.0",
-            "strip-ansi": "^3.0.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^2.0.0"
-          }
-        },
-        "which-module": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
-          "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
-          "dev": true
-        },
-        "yargs": {
-          "version": "6.4.0",
-          "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.4.0.tgz",
-          "integrity": "sha1-gW4ahm1VmMzzTlWW3c4i2S2kkNQ=",
-          "dev": true,
-          "requires": {
-            "camelcase": "^3.0.0",
-            "cliui": "^3.2.0",
-            "decamelize": "^1.1.1",
-            "get-caller-file": "^1.0.1",
-            "os-locale": "^1.4.0",
-            "read-pkg-up": "^1.0.1",
-            "require-directory": "^2.1.1",
-            "require-main-filename": "^1.0.1",
-            "set-blocking": "^2.0.0",
-            "string-width": "^1.0.2",
-            "which-module": "^1.0.0",
-            "window-size": "^0.2.0",
-            "y18n": "^3.2.1",
-            "yargs-parser": "^4.1.0"
-          }
-        },
-        "yargs-parser": {
-          "version": "4.2.1",
-          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
-          "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
-          "dev": true,
-          "requires": {
-            "camelcase": "^3.0.0"
-          }
-        }
-      }
-    },
-    "bs-recipes": {
-      "version": "1.3.4",
-      "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz",
-      "integrity": "sha1-DS1NSKcYyMBEdp/cT4lZLci2lYU=",
-      "dev": true
-    },
-    "bs-snippet-injector": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz",
-      "integrity": "sha1-YbU5PxH1JVntEgaTEANDtu2wTdU=",
-      "dev": true
-    },
     "bser": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz",
@@ -1749,12 +1111,6 @@
       "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==",
       "dev": true
     },
-    "bytes": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
-      "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
-      "dev": true
-    },
     "cache-base": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
@@ -1780,12 +1136,6 @@
         }
       }
     },
-    "callsite": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
-      "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
-      "dev": true
-    },
     "callsites": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
@@ -1842,130 +1192,6 @@
         "supports-color": "^5.3.0"
       }
     },
-    "chokidar": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.1.tgz",
-      "integrity": "sha512-gfw3p2oQV2wEt+8VuMlNsPjCxDxvvgnm/kz+uATu805mWVF8IJN7uz9DN7iBz+RMJISmiVbCOBFs9qBGMjtPfQ==",
-      "dev": true,
-      "requires": {
-        "anymatch": "^2.0.0",
-        "async-each": "^1.0.1",
-        "braces": "^2.3.2",
-        "fsevents": "^1.2.7",
-        "glob-parent": "^3.1.0",
-        "inherits": "^2.0.3",
-        "is-binary-path": "^1.0.0",
-        "is-glob": "^4.0.0",
-        "normalize-path": "^3.0.0",
-        "path-is-absolute": "^1.0.0",
-        "readdirp": "^2.2.1",
-        "upath": "^1.1.0"
-      },
-      "dependencies": {
-        "array-unique": {
-          "version": "0.3.2",
-          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
-          "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
-          "dev": true
-        },
-        "braces": {
-          "version": "2.3.2",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
-          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
-          "dev": true,
-          "requires": {
-            "arr-flatten": "^1.1.0",
-            "array-unique": "^0.3.2",
-            "extend-shallow": "^2.0.1",
-            "fill-range": "^4.0.0",
-            "isobject": "^3.0.1",
-            "repeat-element": "^1.1.2",
-            "snapdragon": "^0.8.1",
-            "snapdragon-node": "^2.0.1",
-            "split-string": "^3.0.2",
-            "to-regex": "^3.0.1"
-          }
-        },
-        "extend-shallow": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-          "dev": true,
-          "requires": {
-            "is-extendable": "^0.1.0"
-          }
-        },
-        "fill-range": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
-          "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
-          "dev": true,
-          "requires": {
-            "extend-shallow": "^2.0.1",
-            "is-number": "^3.0.0",
-            "repeat-string": "^1.6.1",
-            "to-regex-range": "^2.1.0"
-          }
-        },
-        "glob-parent": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
-          "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
-          "dev": true,
-          "requires": {
-            "is-glob": "^3.1.0",
-            "path-dirname": "^1.0.0"
-          },
-          "dependencies": {
-            "is-glob": {
-              "version": "3.1.0",
-              "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
-              "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
-              "dev": true,
-              "requires": {
-                "is-extglob": "^2.1.0"
-              }
-            }
-          }
-        },
-        "is-extglob": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-          "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
-          "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^2.1.1"
-          }
-        },
-        "is-number": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
-          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          }
-        },
-        "isobject": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
-          "dev": true
-        },
-        "normalize-path": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
-          "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-          "dev": true
-        }
-      }
-    },
     "ci-info": {
       "version": "1.6.0",
       "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
@@ -2062,24 +1288,12 @@
       "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
       "dev": true
     },
-    "component-bind": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
-      "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=",
-      "dev": true
-    },
     "component-emitter": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
       "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
       "dev": true
     },
-    "component-inherit": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
-      "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=",
-      "dev": true
-    },
     "concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -2098,33 +1312,6 @@
         "typedarray": "^0.0.6"
       }
     },
-    "connect": {
-      "version": "3.6.6",
-      "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz",
-      "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=",
-      "dev": true,
-      "requires": {
-        "debug": "2.6.9",
-        "finalhandler": "1.1.0",
-        "parseurl": "~1.3.2",
-        "utils-merge": "1.0.1"
-      }
-    },
-    "connect-history-api-fallback": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
-      "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
-      "dev": true
-    },
-    "connect-logger": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/connect-logger/-/connect-logger-0.0.1.tgz",
-      "integrity": "sha1-TZmZeKHSC7RgjnzUNNdBZSJVF0s=",
-      "dev": true,
-      "requires": {
-        "moment": "*"
-      }
-    },
     "console-control-strings": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
@@ -2140,12 +1327,6 @@
         "safe-buffer": "~5.1.1"
       }
     },
-    "cookie": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
-      "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
-      "dev": true
-    },
     "copy-descriptor": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
@@ -2344,18 +1525,6 @@
       "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
       "dev": true
     },
-    "depd": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
-      "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
-      "dev": true
-    },
-    "destroy": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
-      "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
-      "dev": true
-    },
     "detect-indent": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
@@ -2371,12 +1540,6 @@
       "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=",
       "dev": true
     },
-    "dev-ip": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz",
-      "integrity": "sha1-p2o+0YVb56ASu4rBbLgPPADcKPA=",
-      "dev": true
-    },
     "devtools-protocol": {
       "version": "0.0.681549",
       "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.681549.tgz",
@@ -2403,24 +1566,6 @@
         "webidl-conversions": "^4.0.2"
       }
     },
-    "easy-extender": {
-      "version": "2.3.4",
-      "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz",
-      "integrity": "sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q==",
-      "dev": true,
-      "requires": {
-        "lodash": "^4.17.10"
-      }
-    },
-    "eazy-logger": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/eazy-logger/-/eazy-logger-3.0.2.tgz",
-      "integrity": "sha1-oyWqXlPROiIliJsqxBE7K5Y29Pw=",
-      "dev": true,
-      "requires": {
-        "tfunk": "^3.0.1"
-      }
-    },
     "ecc-jsbn": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -2431,106 +1576,6 @@
         "safer-buffer": "^2.1.0"
       }
     },
-    "ee-first": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
-      "dev": true
-    },
-    "encodeurl": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-      "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
-      "dev": true
-    },
-    "engine.io": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz",
-      "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==",
-      "dev": true,
-      "requires": {
-        "accepts": "~1.3.4",
-        "base64id": "1.0.0",
-        "cookie": "0.3.1",
-        "debug": "~3.1.0",
-        "engine.io-parser": "~2.1.0",
-        "ws": "~3.3.1"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
-        "ws": {
-          "version": "3.3.3",
-          "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
-          "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
-          "dev": true,
-          "requires": {
-            "async-limiter": "~1.0.0",
-            "safe-buffer": "~5.1.0",
-            "ultron": "~1.1.0"
-          }
-        }
-      }
-    },
-    "engine.io-client": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.2.tgz",
-      "integrity": "sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ==",
-      "dev": true,
-      "requires": {
-        "component-emitter": "1.2.1",
-        "component-inherit": "0.0.3",
-        "debug": "~3.1.0",
-        "engine.io-parser": "~2.1.1",
-        "has-cors": "1.1.0",
-        "indexof": "0.0.1",
-        "parseqs": "0.0.5",
-        "parseuri": "0.0.5",
-        "ws": "~6.1.0",
-        "xmlhttprequest-ssl": "~1.5.4",
-        "yeast": "0.1.2"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
-        "ws": {
-          "version": "6.1.3",
-          "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.3.tgz",
-          "integrity": "sha512-tbSxiT+qJI223AP4iLfQbkbxkwdFcneYinM2+x46Gx2wgvbaOMO36czfdfVUBRTHvzAMRhDd98sA5d/BuWbQdg==",
-          "dev": true,
-          "requires": {
-            "async-limiter": "~1.0.0"
-          }
-        }
-      }
-    },
-    "engine.io-parser": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
-      "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
-      "dev": true,
-      "requires": {
-        "after": "0.8.2",
-        "arraybuffer.slice": "~0.0.7",
-        "base64-arraybuffer": "0.1.5",
-        "blob": "0.0.5",
-        "has-binary2": "~1.0.2"
-      }
-    },
     "error-ex": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -2586,12 +1631,6 @@
         }
       }
     },
-    "escape-html": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
-      "dev": true
-    },
     "escape-string-regexp": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@@ -2650,18 +1689,6 @@
       "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
       "dev": true
     },
-    "etag": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-      "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
-      "dev": true
-    },
-    "eventemitter3": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz",
-      "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=",
-      "dev": true
-    },
     "events": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz",
@@ -2848,21 +1875,6 @@
         "repeat-string": "^1.5.2"
       }
     },
-    "finalhandler": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz",
-      "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=",
-      "dev": true,
-      "requires": {
-        "debug": "2.6.9",
-        "encodeurl": "~1.0.1",
-        "escape-html": "~1.0.3",
-        "on-finished": "~2.3.0",
-        "parseurl": "~1.3.2",
-        "statuses": "~1.3.1",
-        "unpipe": "~1.0.0"
-      }
-    },
     "find-up": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
@@ -2913,23 +1925,6 @@
         "map-cache": "^0.2.2"
       }
     },
-    "fresh": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-      "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
-      "dev": true
-    },
-    "fs-extra": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz",
-      "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "^4.1.2",
-        "jsonfile": "^3.0.0",
-        "universalify": "^0.1.0"
-      }
-    },
     "fs.realpath": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -3686,29 +2681,6 @@
         "ansi-regex": "^2.0.0"
       }
     },
-    "has-binary2": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
-      "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
-      "dev": true,
-      "requires": {
-        "isarray": "2.0.1"
-      },
-      "dependencies": {
-        "isarray": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
-          "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
-          "dev": true
-        }
-      }
-    },
-    "has-cors": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
-      "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=",
-      "dev": true
-    },
     "has-flag": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -3811,36 +2783,6 @@
         "whatwg-encoding": "^1.0.1"
       }
     },
-    "http-errors": {
-      "version": "1.6.3",
-      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
-      "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
-      "dev": true,
-      "requires": {
-        "depd": "~1.1.2",
-        "inherits": "2.0.3",
-        "setprototypeof": "1.1.0",
-        "statuses": ">= 1.4.0 < 2"
-      },
-      "dependencies": {
-        "statuses": {
-          "version": "1.5.0",
-          "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
-          "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
-          "dev": true
-        }
-      }
-    },
-    "http-proxy": {
-      "version": "1.15.2",
-      "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.15.2.tgz",
-      "integrity": "sha1-ZC/cr/5S00SNK9o7AHnpQJBk2jE=",
-      "dev": true,
-      "requires": {
-        "eventemitter3": "1.x.x",
-        "requires-port": "1.x.x"
-      }
-    },
     "http-signature": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
@@ -3902,12 +2844,6 @@
       "resolved": "https://registry.npmjs.org/immer/-/immer-1.12.1.tgz",
       "integrity": "sha512-3fmKM6ovaqDt0CdC9daXpNi5x/YCYS3i4cwLdTVkhJdk5jrDXoPs7lCm3IqM3yhfSnz4tjjxbRG2CziQ7m8ztg=="
     },
-    "immutable": {
-      "version": "3.8.2",
-      "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz",
-      "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=",
-      "dev": true
-    },
     "import-local": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz",
@@ -3939,12 +2875,6 @@
         "repeating": "^2.0.0"
       }
     },
-    "indexof": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
-      "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
-      "dev": true
-    },
     "inflight": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -3995,15 +2925,6 @@
       "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
       "dev": true
     },
-    "is-binary-path": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
-      "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
-      "dev": true,
-      "requires": {
-        "binary-extensions": "^1.0.0"
-      }
-    },
     "is-buffer": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
@@ -4134,15 +3055,6 @@
         "kind-of": "^3.0.2"
       }
     },
-    "is-number-like": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz",
-      "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==",
-      "dev": true,
-      "requires": {
-        "lodash.isfinite": "^3.3.2"
-      }
-    },
     "is-plain-object": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@@ -4862,15 +3774,6 @@
       "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
       "dev": true
     },
-    "jsonfile": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz",
-      "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "^4.1.6"
-      }
-    },
     "jsprim": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -4929,25 +3832,6 @@
         "type-check": "~0.3.2"
       }
     },
-    "limiter": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.4.tgz",
-      "integrity": "sha512-XCpr5bElgDI65vVgstP8TWjv6/QKWm9GU5UG0Pr5sLQ3QLo8NVKsioe+Jed5/3vFOe3IQuqE7DKwTvKQkjTHvg==",
-      "dev": true
-    },
-    "lite-server": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/lite-server/-/lite-server-2.4.0.tgz",
-      "integrity": "sha512-Vo06tHpXrqm37i6T7tVdq5PSbrFmvQRw64+dlFXdh1tltv6KCvpE+xzXz2+x6KWJ8ja+GgwSy4P13GUWyhaDHQ==",
-      "dev": true,
-      "requires": {
-        "browser-sync": "^2.24.4",
-        "connect-history-api-fallback": "^1.2.0",
-        "connect-logger": "0.0.1",
-        "lodash": "^4.11.1",
-        "minimist": "1.2.0"
-      }
-    },
     "load-json-file": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
@@ -4977,12 +3861,6 @@
       "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
       "dev": true
     },
-    "lodash.isfinite": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz",
-      "integrity": "sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=",
-      "dev": true
-    },
     "lodash.sortby": {
       "version": "4.7.0",
       "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
@@ -5144,12 +4022,6 @@
       "resolved": "https://registry.npmjs.org/micromodal/-/micromodal-0.4.0.tgz",
       "integrity": "sha512-YDku9Fi57S4Sm6oitSy3sr786qSp5L6NbatuH2kEeXf0jStvZgZk4bLBKaoSONBaq3BEvFz3hAaoUa7/pV1Kgg=="
     },
-    "mime": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
-      "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==",
-      "dev": true
-    },
     "mime-db": {
       "version": "1.38.0",
       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz",
@@ -5191,12 +4063,6 @@
       "resolved": "https://registry.npmjs.org/mithril/-/mithril-1.1.7.tgz",
       "integrity": "sha512-1SAkGeVrIVvkUHlPHvR3pXdWzNfTzmS/fBAe+rC2ApEBfZFFc+idi8Qg/M5JoW/sZkIDXSfQYVgvENMIhBIVAg=="
     },
-    "mitt": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.1.3.tgz",
-      "integrity": "sha512-mUDCnVNsAi+eD6qA0HkRkwYczbLHJ49z17BGe2PYRhZL4wpZUFZGJHU7/5tmvohoma+Hdn0Vh/oJTiPEmgSruA==",
-      "dev": true
-    },
     "mixin-deep": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
@@ -5235,12 +4101,6 @@
         }
       }
     },
-    "moment": {
-      "version": "2.24.0",
-      "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
-      "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==",
-      "dev": true
-    },
     "ms": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -5299,12 +4159,6 @@
       "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
       "dev": true
     },
-    "negotiator": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
-      "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
-      "dev": true
-    },
     "neo-async": {
       "version": "2.6.1",
       "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
@@ -5532,12 +4386,6 @@
       "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
       "dev": true
     },
-    "object-component": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
-      "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=",
-      "dev": true
-    },
     "object-copy": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
@@ -5565,12 +4413,6 @@
       "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz",
       "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg=="
     },
-    "object-path": {
-      "version": "0.9.2",
-      "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.9.2.tgz",
-      "integrity": "sha1-D9mnT8X60a45aLWGvaXGMr1sBaU=",
-      "dev": true
-    },
     "object-visit": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
@@ -5636,15 +4478,6 @@
         }
       }
     },
-    "on-finished": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
-      "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
-      "dev": true,
-      "requires": {
-        "ee-first": "1.1.1"
-      }
-    },
     "once": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -5654,21 +4487,6 @@
         "wrappy": "1"
       }
     },
-    "openurl": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz",
-      "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=",
-      "dev": true
-    },
-    "opn": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz",
-      "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==",
-      "dev": true,
-      "requires": {
-        "is-wsl": "^1.1.0"
-      }
-    },
     "optimist": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
@@ -5804,42 +4622,12 @@
       "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
       "dev": true
     },
-    "parseqs": {
-      "version": "0.0.5",
-      "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
-      "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
-      "dev": true,
-      "requires": {
-        "better-assert": "~1.0.0"
-      }
-    },
-    "parseuri": {
-      "version": "0.0.5",
-      "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
-      "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
-      "dev": true,
-      "requires": {
-        "better-assert": "~1.0.0"
-      }
-    },
-    "parseurl": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
-      "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=",
-      "dev": true
-    },
     "pascalcase": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
       "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
       "dev": true
     },
-    "path-dirname": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
-      "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
-      "dev": true
-    },
     "path-exists": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
@@ -5923,24 +4711,6 @@
       "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==",
       "dev": true
     },
-    "portscanner": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.1.1.tgz",
-      "integrity": "sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y=",
-      "dev": true,
-      "requires": {
-        "async": "1.5.2",
-        "is-number-like": "^1.0.3"
-      },
-      "dependencies": {
-        "async": {
-          "version": "1.5.2",
-          "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
-          "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
-          "dev": true
-        }
-      }
-    },
     "posix-character-classes": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
@@ -6135,35 +4905,6 @@
         }
       }
     },
-    "range-parser": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
-      "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=",
-      "dev": true
-    },
-    "raw-body": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
-      "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
-      "dev": true,
-      "requires": {
-        "bytes": "3.0.0",
-        "http-errors": "1.6.3",
-        "iconv-lite": "0.4.23",
-        "unpipe": "1.0.0"
-      },
-      "dependencies": {
-        "iconv-lite": {
-          "version": "0.4.23",
-          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
-          "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
-          "dev": true,
-          "requires": {
-            "safer-buffer": ">= 2.1.2 < 3"
-          }
-        }
-      }
-    },
     "read-pkg": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
@@ -6221,293 +4962,6 @@
         "util-deprecate": "~1.0.1"
       }
     },
-    "readdirp": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
-      "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "^4.1.11",
-        "micromatch": "^3.1.10",
-        "readable-stream": "^2.0.2"
-      },
-      "dependencies": {
-        "arr-diff": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
-          "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
-          "dev": true
-        },
-        "array-unique": {
-          "version": "0.3.2",
-          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
-          "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
-          "dev": true
-        },
-        "braces": {
-          "version": "2.3.2",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
-          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
-          "dev": true,
-          "requires": {
-            "arr-flatten": "^1.1.0",
-            "array-unique": "^0.3.2",
-            "extend-shallow": "^2.0.1",
-            "fill-range": "^4.0.0",
-            "isobject": "^3.0.1",
-            "repeat-element": "^1.1.2",
-            "snapdragon": "^0.8.1",
-            "snapdragon-node": "^2.0.1",
-            "split-string": "^3.0.2",
-            "to-regex": "^3.0.1"
-          },
-          "dependencies": {
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            }
-          }
-        },
-        "expand-brackets": {
-          "version": "2.1.4",
-          "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
-          "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
-          "dev": true,
-          "requires": {
-            "debug": "^2.3.3",
-            "define-property": "^0.2.5",
-            "extend-shallow": "^2.0.1",
-            "posix-character-classes": "^0.1.0",
-            "regex-not": "^1.0.0",
-            "snapdragon": "^0.8.1",
-            "to-regex": "^3.0.1"
-          },
-          "dependencies": {
-            "define-property": {
-              "version": "0.2.5",
-              "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-              "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-              "dev": true,
-              "requires": {
-                "is-descriptor": "^0.1.0"
-              }
-            },
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            },
-            "is-accessor-descriptor": {
-              "version": "0.1.6",
-              "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-              "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
-              "dev": true,
-              "requires": {
-                "kind-of": "^3.0.2"
-              },
-              "dependencies": {
-                "kind-of": {
-                  "version": "3.2.2",
-                  "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                  "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-                  "dev": true,
-                  "requires": {
-                    "is-buffer": "^1.1.5"
-                  }
-                }
-              }
-            },
-            "is-data-descriptor": {
-              "version": "0.1.4",
-              "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-              "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
-              "dev": true,
-              "requires": {
-                "kind-of": "^3.0.2"
-              },
-              "dependencies": {
-                "kind-of": {
-                  "version": "3.2.2",
-                  "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                  "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-                  "dev": true,
-                  "requires": {
-                    "is-buffer": "^1.1.5"
-                  }
-                }
-              }
-            },
-            "is-descriptor": {
-              "version": "0.1.6",
-              "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
-              "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
-              "dev": true,
-              "requires": {
-                "is-accessor-descriptor": "^0.1.6",
-                "is-data-descriptor": "^0.1.4",
-                "kind-of": "^5.0.0"
-              }
-            },
-            "kind-of": {
-              "version": "5.1.0",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-              "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
-              "dev": true
-            }
-          }
-        },
-        "extglob": {
-          "version": "2.0.4",
-          "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
-          "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
-          "dev": true,
-          "requires": {
-            "array-unique": "^0.3.2",
-            "define-property": "^1.0.0",
-            "expand-brackets": "^2.1.4",
-            "extend-shallow": "^2.0.1",
-            "fragment-cache": "^0.2.1",
-            "regex-not": "^1.0.0",
-            "snapdragon": "^0.8.1",
-            "to-regex": "^3.0.1"
-          },
-          "dependencies": {
-            "define-property": {
-              "version": "1.0.0",
-              "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-              "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-              "dev": true,
-              "requires": {
-                "is-descriptor": "^1.0.0"
-              }
-            },
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            }
-          }
-        },
-        "fill-range": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
-          "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
-          "dev": true,
-          "requires": {
-            "extend-shallow": "^2.0.1",
-            "is-number": "^3.0.0",
-            "repeat-string": "^1.6.1",
-            "to-regex-range": "^2.1.0"
-          },
-          "dependencies": {
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            }
-          }
-        },
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^1.0.0",
-            "is-data-descriptor": "^1.0.0",
-            "kind-of": "^6.0.2"
-          }
-        },
-        "is-number": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
-          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "3.2.2",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "dev": true,
-              "requires": {
-                "is-buffer": "^1.1.5"
-              }
-            }
-          }
-        },
-        "isobject": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
-          "dev": true
-        },
-        "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
-          "dev": true
-        },
-        "micromatch": {
-          "version": "3.1.10",
-          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
-          "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
-          "dev": true,
-          "requires": {
-            "arr-diff": "^4.0.0",
-            "array-unique": "^0.3.2",
-            "braces": "^2.3.1",
-            "define-property": "^2.0.2",
-            "extend-shallow": "^3.0.2",
-            "extglob": "^2.0.4",
-            "fragment-cache": "^0.2.1",
-            "kind-of": "^6.0.2",
-            "nanomatch": "^1.2.9",
-            "object.pick": "^1.3.0",
-            "regex-not": "^1.0.0",
-            "snapdragon": "^0.8.1",
-            "to-regex": "^3.0.2"
-          }
-        }
-      }
-    },
     "realpath-native": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz",
@@ -6657,12 +5111,6 @@
       "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
       "dev": true
     },
-    "requires-port": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
-      "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
-      "dev": true
-    },
     "resolve": {
       "version": "1.11.0",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz",
@@ -6701,16 +5149,6 @@
       "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
       "dev": true
     },
-    "resp-modifier": {
-      "version": "6.0.2",
-      "resolved": "https://registry.npmjs.org/resp-modifier/-/resp-modifier-6.0.2.tgz",
-      "integrity": "sha1-sSTeXE+6/LpUH0j/pzlw9KpFa08=",
-      "dev": true,
-      "requires": {
-        "debug": "^2.2.0",
-        "minimatch": "^3.0.2"
-      }
-    },
     "ret": {
       "version": "0.1.15",
       "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
@@ -6798,21 +5236,6 @@
       "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==",
       "dev": true
     },
-    "rx": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz",
-      "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=",
-      "dev": true
-    },
-    "rxjs": {
-      "version": "5.5.12",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz",
-      "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==",
-      "dev": true,
-      "requires": {
-        "symbol-observable": "1.0.1"
-      }
-    },
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -7276,68 +5699,6 @@
       "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
       "dev": true
     },
-    "send": {
-      "version": "0.16.2",
-      "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
-      "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
-      "dev": true,
-      "requires": {
-        "debug": "2.6.9",
-        "depd": "~1.1.2",
-        "destroy": "~1.0.4",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "etag": "~1.8.1",
-        "fresh": "0.5.2",
-        "http-errors": "~1.6.2",
-        "mime": "1.4.1",
-        "ms": "2.0.0",
-        "on-finished": "~2.3.0",
-        "range-parser": "~1.2.0",
-        "statuses": "~1.4.0"
-      },
-      "dependencies": {
-        "statuses": {
-          "version": "1.4.0",
-          "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
-          "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==",
-          "dev": true
-        }
-      }
-    },
-    "serve-index": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
-      "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
-      "dev": true,
-      "requires": {
-        "accepts": "~1.3.4",
-        "batch": "0.6.1",
-        "debug": "2.6.9",
-        "escape-html": "~1.0.3",
-        "http-errors": "~1.6.2",
-        "mime-types": "~2.1.17",
-        "parseurl": "~1.3.2"
-      }
-    },
-    "serve-static": {
-      "version": "1.13.2",
-      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
-      "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
-      "dev": true,
-      "requires": {
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "parseurl": "~1.3.2",
-        "send": "0.16.2"
-      }
-    },
-    "server-destroy": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz",
-      "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=",
-      "dev": true
-    },
     "set-blocking": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
@@ -7367,12 +5728,6 @@
         }
       }
     },
-    "setprototypeof": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
-      "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
-      "dev": true
-    },
     "shebang-command": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
@@ -7520,167 +5875,6 @@
         "kind-of": "^3.2.0"
       }
     },
-    "socket.io": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz",
-      "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==",
-      "dev": true,
-      "requires": {
-        "debug": "~3.1.0",
-        "engine.io": "~3.2.0",
-        "has-binary2": "~1.0.2",
-        "socket.io-adapter": "~1.1.0",
-        "socket.io-client": "2.1.1",
-        "socket.io-parser": "~3.2.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
-        "engine.io-client": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz",
-          "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==",
-          "dev": true,
-          "requires": {
-            "component-emitter": "1.2.1",
-            "component-inherit": "0.0.3",
-            "debug": "~3.1.0",
-            "engine.io-parser": "~2.1.1",
-            "has-cors": "1.1.0",
-            "indexof": "0.0.1",
-            "parseqs": "0.0.5",
-            "parseuri": "0.0.5",
-            "ws": "~3.3.1",
-            "xmlhttprequest-ssl": "~1.5.4",
-            "yeast": "0.1.2"
-          }
-        },
-        "isarray": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
-          "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
-          "dev": true
-        },
-        "socket.io-client": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz",
-          "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==",
-          "dev": true,
-          "requires": {
-            "backo2": "1.0.2",
-            "base64-arraybuffer": "0.1.5",
-            "component-bind": "1.0.0",
-            "component-emitter": "1.2.1",
-            "debug": "~3.1.0",
-            "engine.io-client": "~3.2.0",
-            "has-binary2": "~1.0.2",
-            "has-cors": "1.1.0",
-            "indexof": "0.0.1",
-            "object-component": "0.0.3",
-            "parseqs": "0.0.5",
-            "parseuri": "0.0.5",
-            "socket.io-parser": "~3.2.0",
-            "to-array": "0.1.4"
-          }
-        },
-        "socket.io-parser": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz",
-          "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==",
-          "dev": true,
-          "requires": {
-            "component-emitter": "1.2.1",
-            "debug": "~3.1.0",
-            "isarray": "2.0.1"
-          }
-        },
-        "ws": {
-          "version": "3.3.3",
-          "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
-          "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
-          "dev": true,
-          "requires": {
-            "async-limiter": "~1.0.0",
-            "safe-buffer": "~5.1.0",
-            "ultron": "~1.1.0"
-          }
-        }
-      }
-    },
-    "socket.io-adapter": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz",
-      "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=",
-      "dev": true
-    },
-    "socket.io-client": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz",
-      "integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==",
-      "dev": true,
-      "requires": {
-        "backo2": "1.0.2",
-        "base64-arraybuffer": "0.1.5",
-        "component-bind": "1.0.0",
-        "component-emitter": "1.2.1",
-        "debug": "~3.1.0",
-        "engine.io-client": "~3.3.1",
-        "has-binary2": "~1.0.2",
-        "has-cors": "1.1.0",
-        "indexof": "0.0.1",
-        "object-component": "0.0.3",
-        "parseqs": "0.0.5",
-        "parseuri": "0.0.5",
-        "socket.io-parser": "~3.3.0",
-        "to-array": "0.1.4"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        }
-      }
-    },
-    "socket.io-parser": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz",
-      "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==",
-      "dev": true,
-      "requires": {
-        "component-emitter": "1.2.1",
-        "debug": "~3.1.0",
-        "isarray": "2.0.1"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
-        "isarray": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
-          "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
-          "dev": true
-        }
-      }
-    },
     "sorcery": {
       "version": "0.10.0",
       "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz",
@@ -7824,12 +6018,6 @@
         }
       }
     },
-    "statuses": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
-      "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=",
-      "dev": true
-    },
     "stdout-stream": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz",
@@ -7845,16 +6033,6 @@
       "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=",
       "dev": true
     },
-    "stream-throttle": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz",
-      "integrity": "sha1-rdV8jXzHOoFjDTHNVdOWHPr7qcM=",
-      "dev": true,
-      "requires": {
-        "commander": "^2.2.0",
-        "limiter": "^1.0.5"
-      }
-    },
     "string-length": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz",
@@ -7934,12 +6112,6 @@
         "has-flag": "^3.0.0"
       }
     },
-    "symbol-observable": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
-      "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=",
-      "dev": true
-    },
     "symbol-tree": {
       "version": "3.2.2",
       "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
@@ -7970,52 +6142,6 @@
         "require-main-filename": "^1.0.1"
       }
     },
-    "tfunk": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/tfunk/-/tfunk-3.1.0.tgz",
-      "integrity": "sha1-OORBT8ZJd9h6/apy+sttKfgve1s=",
-      "dev": true,
-      "requires": {
-        "chalk": "^1.1.1",
-        "object-path": "^0.9.0"
-      },
-      "dependencies": {
-        "ansi-styles": {
-          "version": "2.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
-          "dev": true
-        },
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "^2.2.1",
-            "escape-string-regexp": "^1.0.2",
-            "has-ansi": "^2.0.0",
-            "strip-ansi": "^3.0.0",
-            "supports-color": "^2.0.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "^2.0.0"
-          }
-        },
-        "supports-color": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
-          "dev": true
-        }
-      }
-    },
     "throat": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz",
@@ -8028,12 +6154,6 @@
       "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=",
       "dev": true
     },
-    "to-array": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
-      "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=",
-      "dev": true
-    },
     "to-fast-properties": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
@@ -8212,12 +6332,6 @@
       "integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==",
       "dev": true
     },
-    "ua-parser-js": {
-      "version": "0.7.17",
-      "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz",
-      "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==",
-      "dev": true
-    },
     "uglify-js": {
       "version": "3.4.9",
       "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz",
@@ -8238,12 +6352,6 @@
         }
       }
     },
-    "ultron": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
-      "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==",
-      "dev": true
-    },
     "union-value": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
@@ -8256,18 +6364,6 @@
         "set-value": "^2.0.1"
       }
     },
-    "universalify": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
-      "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
-      "dev": true
-    },
-    "unpipe": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
-      "dev": true
-    },
     "unset-value": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
@@ -8314,12 +6410,6 @@
         }
       }
     },
-    "upath": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz",
-      "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==",
-      "dev": true
-    },
     "uri-js": {
       "version": "4.2.2",
       "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
@@ -8369,12 +6459,6 @@
         "object.getownpropertydescriptors": "^2.0.3"
       }
     },
-    "utils-merge": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
-      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
-      "dev": true
-    },
     "uuid": {
       "version": "3.3.2",
       "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
@@ -8485,12 +6569,6 @@
         "string-width": "^1.0.2 || 2"
       }
     },
-    "window-size": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz",
-      "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=",
-      "dev": true
-    },
     "wordwrap": {
       "version": "0.0.3",
       "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
@@ -8570,12 +6648,6 @@
       "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==",
       "dev": true
     },
-    "xmlhttprequest-ssl": {
-      "version": "1.5.5",
-      "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
-      "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=",
-      "dev": true
-    },
     "y18n": {
       "version": "3.2.1",
       "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
@@ -8625,12 +6697,6 @@
       "requires": {
         "fd-slicer": "~1.0.1"
       }
-    },
-    "yeast": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
-      "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=",
-      "dev": true
     }
   }
 }
diff --git a/ui/package.json b/ui/package.json
index dd44b6f..6a0f0f8 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -4,10 +4,6 @@
   "description": "Perfetto UI",
   "repository": "https://android.googlesource.com/platform/external/perfetto",
   "main": "main.js",
-  "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1",
-    "dev": "lite-server --baseDir=dist"
-  },
   "author": "Perfetto Team",
   "license": "Apache-2.0",
   "dependencies": {
@@ -37,7 +33,6 @@
     "@types/puppeteer": "^1.12.4",
     "dingusjs": "^0.0.3",
     "jest": "^23.6.0",
-    "lite-server": "^2.4.0",
     "node-sass": "^4.12.0",
     "puppeteer": "^1.16.0",
     "rollup": "^1.17.0",
diff --git a/ui/run-dev-server b/ui/run-dev-server
index e42a940..843d2ac 100755
--- a/ui/run-dev-server
+++ b/ui/run-dev-server
@@ -15,15 +15,7 @@
 
 UI_DIR="$(cd -P ${BASH_SOURCE[0]%/*}; pwd)"
 ROOT_DIR=$(dirname "$UI_DIR")
-NODE=$ROOT_DIR/buildtools/nodejs/bin/node
-LITE="$UI_DIR/node_modules/.bin/lite-server"
 
-if [ ! -f "$LITE" ]; then
-  echo "ERROR: cannot find lite-server. You need to run:"
-  echo "  tools/install-build-deps --ui"
-  echo "  ninja -C out/xxx ui"
-  exit 127
-fi
 if [ -z "$1" ]; then
   echo "ERROR: no output directory specified."
   echo "Usage: $0 out/mac_debug"
@@ -31,16 +23,20 @@
 fi
 OUT_DIR="$1"
 UI_OUT_DIR="$OUT_DIR/ui"
-if [ ! -d $OUT_DIR ]; then
-  echo "ERROR: cannot find the output directory (\"$OUT_DIR\")"
-  echo "Did you run ninja?"
-  exit 127
-fi
 if [ ! -d $UI_OUT_DIR ]; then
   echo "ERROR: cannot find the UI output directory (\"$UI_OUT_DIR\")."
   echo "Did you run ninja ui?"
   exit 127
 fi
 
-OUT_DIR="$OUT_DIR" ROOT_DIR="$ROOT_DIR" $NODE $LITE -c $UI_DIR/bs-config.js
+$ROOT_DIR/tools/dev_server \
+  -p 10000 \
+  -i $ROOT_DIR/.git \
+  -i $ROOT_DIR/src/traced \
+  -i $ROOT_DIR/buildtools \
+  -i $ROOT_DIR/out \
+  -i $ROOT_DIR/ui/node_modules \
+  -s $UI_OUT_DIR \
+  "$ROOT_DIR/tools/ninja -C $OUT_DIR ui"
+
 
diff --git a/ui/src/common/engine.ts b/ui/src/common/engine.ts
index d9f6760..b7734e3 100644
--- a/ui/src/common/engine.ts
+++ b/ui/src/common/engine.ts
@@ -101,8 +101,11 @@
 
   async getNumberOfGpus(): Promise<number> {
     if (!this._numGpus) {
-      const result = await this.query(
-          'select count(distinct(arg_set_id)) as gpuCount from counters where name = "gpufreq";');
+      const result = await this.query(`
+        select count(distinct(gpu_id)) as gpuCount
+        from gpu_counter_track
+        where name = 'gpufreq';
+      `);
       this._numGpus = +result.columns[0].longValues![0];
     }
     return this._numGpus;
diff --git a/ui/src/common/search_data.ts b/ui/src/common/search_data.ts
index 79b7bbf..0969c1d 100644
--- a/ui/src/common/search_data.ts
+++ b/ui/src/common/search_data.ts
@@ -23,6 +23,6 @@
   tsStarts: Float64Array;
   utids: Float64Array;
   trackIds: string[];
-  refTypes: string[];
+  sources: string[];
   totalResults: number;
 }
diff --git a/ui/src/controller/search_controller.ts b/ui/src/controller/search_controller.ts
index 0edaa53..5e29627 100644
--- a/ui/src/controller/search_controller.ts
+++ b/ui/src/controller/search_controller.ts
@@ -55,7 +55,7 @@
     await this.query(`create virtual table search_summary_sched_span using
       span_join(sched PARTITIONED cpu, search_summary_window);`);
     await this.query(`create virtual table search_summary_slice_span using
-      span_join(slice PARTITIONED ref_type  ref, search_summary_window);`);
+      span_join(slice PARTITIONED track_id, search_summary_window);`);
   }
 
   run() {
@@ -92,7 +92,7 @@
         sliceIds: new Float64Array(0),
         tsStarts: new Float64Array(0),
         utids: new Float64Array(0),
-        refTypes: [],
+        sources: [],
         trackIds: [],
         totalResults: 0,
       });
@@ -208,7 +208,7 @@
       row_id as slice_id,
       ts,
       'cpu' as source,
-      cpu as ref,
+      cpu as source_id,
       utid
     from sched where utid in (${utids.join(',')})
     union
@@ -216,7 +216,7 @@
       slice_id,
       ts,
       'track' as source,
-      track_id as ref,
+      track_id as source_id,
       0 as utid
       from slice
       inner join track on slice.track_id = track.id
@@ -230,19 +230,19 @@
       tsStarts: new Float64Array(numRows),
       utids: new Float64Array(numRows),
       trackIds: [],
-      refTypes: [],
+      sources: [],
       totalResults: +numRows,
     };
 
     const columns = rawResult.columns;
     for (let row = 0; row < numRows; row++) {
       const source = columns[2].stringValues![row];
-      const ref = +columns[3].longValues![row];
+      const sourceId = +columns[3].longValues![row];
       let trackId = undefined;
       if (source === 'cpu') {
-        trackId = cpuToTrackId.get(ref);
+        trackId = cpuToTrackId.get(sourceId);
       } else if (source === 'track') {
-        trackId = engineTrackIdToTrackId.get(ref);
+        trackId = engineTrackIdToTrackId.get(sourceId);
       }
 
       if (trackId === undefined) {
@@ -251,7 +251,7 @@
       }
 
       searchResults.trackIds.push(trackId);
-      searchResults.refTypes.push(source);
+      searchResults.sources.push(source);
       searchResults.sliceIds[row] = +columns[0].longValues![row];
       searchResults.tsStarts[row] = +columns[1].longValues![row];
       searchResults.utids[row] = +columns[4].longValues![row];
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index ff6fd38..88e2190 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -309,10 +309,10 @@
     //  }));
     //}
     const maxCpuFreq = await engine.query(`
-     select max(value)
-     from counter c
-     inner join cpu_counter_track t on c.track_id = t.id
-     where name = 'cpufreq';
+      select max(value)
+      from counter c
+      inner join cpu_counter_track t on c.track_id = t.id
+      where name = 'cpufreq';
     `);
 
     const cpus = await engine.getCpus();
@@ -412,18 +412,19 @@
     }
 
     const maxGpuFreq = await engine.query(`
-     select max(value)
-     from counters
-     where name = 'gpufreq';
+      select max(value)
+      from counter c
+      inner join gpu_counter_track t on c.track_id = t.id
+      where name = 'gpufreq';
     `);
 
     for (let gpu = 0; gpu < numGpus; gpu++) {
       // Only add a gpu freq track if we have
       // gpu freq data.
       const freqExists = await engine.query(`
-        select value
-        from counters
-        where name = 'gpufreq' and ref = ${gpu}
+        select id
+        from gpu_counter_track
+        where name = 'gpufreq' and gpu_id = ${gpu}
         limit 1;
       `);
       if (freqExists.numRecords > 0) {
@@ -434,6 +435,7 @@
           trackGroup: SCROLLING_TRACK_GROUP,
           config: {
             gpu,
+            trackId: +freqExists.columns[0].longValues![0],
             maximumValue: +maxGpuFreq.columns[0].doubleValues![0],
           }
         });
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index d7d5d9a..0fb518d 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -111,7 +111,7 @@
     tsStarts: new Float64Array(0),
     utids: new Float64Array(0),
     trackIds: [],
-    refTypes: [],
+    sources: [],
     totalResults: 0,
   };
   searchSummary: SearchSummary = {
@@ -275,7 +275,7 @@
       tsStarts: new Float64Array(0),
       utids: new Float64Array(0),
       trackIds: [],
-      refTypes: [],
+      sources: [],
       totalResults: 0,
     };
     this._aggregateCpuData = {
diff --git a/ui/src/frontend/index.ts b/ui/src/frontend/index.ts
index dc46eca..c9f75bc 100644
--- a/ui/src/frontend/index.ts
+++ b/ui/src/frontend/index.ts
@@ -277,8 +277,10 @@
 
   updateAvailableAdbDevices();
   try {
-    navigator.usb.addEventListener('connect', updateAvailableAdbDevices);
-    navigator.usb.addEventListener('disconnect', updateAvailableAdbDevices);
+    navigator.usb.addEventListener(
+        'connect', () => updateAvailableAdbDevices());
+    navigator.usb.addEventListener(
+        'disconnect', () => updateAvailableAdbDevices());
   } catch (e) {
     console.error('WebUSB API not supported');
   }
diff --git a/ui/src/frontend/post_message_handler.ts b/ui/src/frontend/post_message_handler.ts
index 2f5c02f..1cc4285 100644
--- a/ui/src/frontend/post_message_handler.ts
+++ b/ui/src/frontend/post_message_handler.ts
@@ -29,11 +29,13 @@
 // which indicates it is ready to receive a trace.
 export function postMessageHandler(messageEvent: MessageEvent) {
   if (!isOriginAllowed(messageEvent.origin)) {
-    throw new Error('Invalid origin for postMessage: ' + messageEvent.origin);
+    console.error(
+        `Ignoring message - disallowed origin ${messageEvent.origin}`);
+    return;
   }
 
   if (document.readyState !== 'complete') {
-    console.error('Not ready.');
+    console.error('Ignoring message - document not ready yet.');
     return;
   }
 
diff --git a/ui/src/frontend/record_page.ts b/ui/src/frontend/record_page.ts
index 5a85756..135c874 100644
--- a/ui/src/frontend/record_page.ts
+++ b/ui/src/frontend/record_page.ts
@@ -724,7 +724,21 @@
           'label',
           'Target platform:',
           m('select',
-            {onchange: m.withAttr('value', onTargetChange), selectedIndex},
+            {
+              selectedIndex,
+              onchange: m.withAttr('value', onTargetChange),
+              onupdate: (select) => {
+                // Work around mithril bug
+                // (https://github.com/MithrilJS/mithril.js/issues/2107): We may
+                // update the select's options while also changing the
+                // selectedIndex at the same time. The update of selectedIndex
+                // may be applied before the new options are added to the select
+                // element. Because the new selectedIndex may be outside of the
+                // select's options at that time, we have to reselect the
+                // correct index here after any new children were added.
+                (select.dom as HTMLSelectElement).selectedIndex = selectedIndex;
+              }
+            },
             ...targets),
           ),
       m('.chip',
@@ -959,7 +973,7 @@
   try {
     device = await new AdbOverWebUsb().findDevice();
   } catch (e) {
-    console.error('No device found: ${e.name}: ${e.message}');
+    console.error(`No device found: ${e.name}: ${e.message}`);
     return;
   }
 
@@ -971,13 +985,15 @@
   // After the user has selected a device with the chrome UI, it will be
   // available when listing all the available device from WebUSB. Therefore,
   // we update the list of available devices.
-  await updateAvailableAdbDevices();
-  onTargetChange(device.serialNumber);
+  await updateAvailableAdbDevices(device.serialNumber);
 }
 
-export async function updateAvailableAdbDevices() {
+export async function updateAvailableAdbDevices(
+    preferredDeviceSerial?: string) {
   const devices = await new AdbOverWebUsb().getPairedDevices();
 
+  let recordingTarget: AdbRecordingTarget|undefined = undefined;
+
   const availableAdbDevices: AdbRecordingTarget[] = [];
   devices.forEach(d => {
     if (d.productName && d.serialNumber) {
@@ -987,31 +1003,41 @@
       // connection, from adb_record_controller
       availableAdbDevices.push(
           {name: d.productName, serial: d.serialNumber, os: 'Q'});
+      if (preferredDeviceSerial && preferredDeviceSerial === d.serialNumber) {
+        recordingTarget = availableAdbDevices[availableAdbDevices.length - 1];
+      }
     }
   });
 
   globals.dispatch(
       Actions.setAvailableAdbDevices({devices: availableAdbDevices}));
-  selectAndroidDeviceIfAvailable(availableAdbDevices);
+  selectAndroidDeviceIfAvailable(availableAdbDevices, recordingTarget);
   globals.rafScheduler.scheduleFullRedraw();
   return availableAdbDevices;
 }
 
 function selectAndroidDeviceIfAvailable(
-    availableAdbDevices: AdbRecordingTarget[]) {
-  const recordingTarget = globals.state.recordingTarget;
+    availableAdbDevices: AdbRecordingTarget[],
+    recordingTarget?: RecordingTarget) {
+  if (!recordingTarget) {
+    recordingTarget = globals.state.recordingTarget;
+  }
   const deviceConnected = isAdbTarget(recordingTarget);
   const connectedDeviceDisconnected = deviceConnected &&
       availableAdbDevices.find(
           e => e.serial === (recordingTarget as AdbRecordingTarget).serial) ===
           undefined;
 
-  // If there is an android device attached, but not selected (or the currently
-  // selected device was disconnected), select it by default.
-  if ((!deviceConnected || connectedDeviceDisconnected) &&
-      availableAdbDevices.length) {
-    globals.dispatch(
-        Actions.setRecordingTarget({target: availableAdbDevices[0]}));
+  if (availableAdbDevices.length) {
+    // If there's an Android device available and the current selection isn't
+    // one, select the Android device by default. If the current device isn't
+    // available anymore, but another Android device is, select the other
+    // Android device instead.
+    if (!deviceConnected || connectedDeviceDisconnected) {
+      recordingTarget = availableAdbDevices[0];
+    }
+
+    globals.dispatch(Actions.setRecordingTarget({target: recordingTarget}));
     return;
   }
 
diff --git a/ui/src/frontend/search_handler.ts b/ui/src/frontend/search_handler.ts
index 0e726a8..4db56c6 100644
--- a/ui/src/frontend/search_handler.ts
+++ b/ui/src/frontend/search_handler.ts
@@ -70,13 +70,13 @@
 function selectCurrentSearchResult() {
   const state = globals.frontendLocalState;
   const searchIndex = state.searchIndex;
-  const refType = globals.currentSearchResults.refTypes[searchIndex];
+  const source = globals.currentSearchResults.sources[searchIndex];
   const currentId = globals.currentSearchResults.sliceIds[searchIndex];
   const trackId = globals.currentSearchResults.trackIds[searchIndex];
 
   if (currentId === undefined) return;
 
-  if (refType === 'cpu') {
+  if (source === 'cpu') {
     globals.dispatch(Actions.selectSlice({id: currentId, trackId}));
   } else {
     globals.dispatch(Actions.selectChromeSlice({id: currentId, trackId}));
diff --git a/ui/src/frontend/sidebar.ts b/ui/src/frontend/sidebar.ts
index 420ac57..4e7c3aa 100644
--- a/ui/src/frontend/sidebar.ts
+++ b/ui/src/frontend/sidebar.ts
@@ -54,10 +54,11 @@
   sum(dur * freq)/1e6 as mcycles
 from (
   select
-    ref as cpu,
+    cpu,
     value as freq,
-    lead(ts) over (partition by ref order by ts) - ts as dur
-  from counters
+    lead(ts) over (partition by cpu order by ts) - ts as dur
+  from counter
+  inner join cpu_counter_track on counter.track_id = cpu_counter_track.id
   where name = 'cpufreq'
 ) group by cpu, freq
 order by mcycles desc limit 32;`;
diff --git a/ui/src/tracks/gpu_freq/common.ts b/ui/src/tracks/gpu_freq/common.ts
index dd8665d..f860234 100644
--- a/ui/src/tracks/gpu_freq/common.ts
+++ b/ui/src/tracks/gpu_freq/common.ts
@@ -27,5 +27,7 @@
 
 export interface Config {
   gpu: number;
+  trackId: number;
   maximumValue?: number;
-  minimumValue?: number;}
+  minimumValue?: number;
+}
diff --git a/ui/src/tracks/gpu_freq/controller.ts b/ui/src/tracks/gpu_freq/controller.ts
index 6fa2e39..a8bafd6 100644
--- a/ui/src/tracks/gpu_freq/controller.ts
+++ b/ui/src/tracks/gpu_freq/controller.ts
@@ -37,9 +37,9 @@
 
     if (!this.setup) {
       const result = await this.query(`
-      select max(value) from
-        counters where name = 'gpufreq'
-        and ref = ${this.config.gpu}`);
+        select max(value)
+        from counter
+        where track_id = ${this.config.trackId}`);
       this.maximumValueSeen = +result.columns[0].doubleValues![0];
 
       await this.query(
@@ -49,25 +49,21 @@
           as select
             ts,
             lead(ts) over (order by ts) - ts as dur,
-            ref as gpu,
-            name as freq_name,
             value as freq_value
-          from counters
-          where name = 'gpufreq'
-            and ref = ${this.config.gpu}
-            and ref_type = 'gpu';
+          from counter
+          where track_id = ${this.config.trackId};
       `);
 
       await this.query(`create virtual table ${this.tableName('span_activity')}
-      using span_join(${this.tableName('freq')} PARTITIONED gpu,
-                      ${this.tableName('window')});`);
+        using span_join(${this.tableName('freq')}, ${
+          this.tableName('window')});`);
 
-      await this.query(`create view ${this.tableName('activity')}
-      as select
-        ts,
-        dur,
-        quantum_ts,
-        freq_value as freq
+      await this.query(`create view ${this.tableName('activity')} as
+        select
+          ts,
+          dur,
+          quantum_ts,
+          freq_value as freq
         from ${this.tableName('span_activity')};
       `);
 
@@ -75,9 +71,9 @@
     }
 
     this.query(`update ${this.tableName('window')} set
-    window_start = ${startNs},
-    window_dur = ${Math.max(1, endNs - startNs)},
-    quantum = 0`);
+      window_start = ${startNs},
+      window_dur = ${Math.max(1, endNs - startNs)},
+      quantum = 0`);
 
     const result = await this.engine.queryOneRow(`select count(*)
       from ${this.tableName('activity')}`);