Merge "Add parser for proguard maps."
diff --git a/Android.bp b/Android.bp
index b7a3a33..469fec7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -27,7 +27,6 @@
     "src/trace_processor/metrics/android/android_mem_unagg.sql",
     "src/trace_processor/metrics/android/android_package_list.sql",
     "src/trace_processor/metrics/android/android_powrails.sql",
-    "src/trace_processor/metrics/android/android_process_growth.sql",
     "src/trace_processor/metrics/android/android_startup.sql",
     "src/trace_processor/metrics/android/android_startup_cpu.sql",
     "src/trace_processor/metrics/android/android_startup_launches.sql",
@@ -36,6 +35,7 @@
     "src/trace_processor/metrics/android/java_heap_stats.sql",
     "src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql",
     "src/trace_processor/metrics/android/process_mem.sql",
+    "src/trace_processor/metrics/android/process_metadata.sql",
     "src/trace_processor/metrics/android/process_unagg_mem_view.sql",
     "src/trace_processor/metrics/android/span_view_stats.sql",
     "src/trace_processor/metrics/android/unsymbolized_frames.sql",
@@ -95,14 +95,14 @@
     ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_zero_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
     ":perfetto_protos_perfetto_trace_chrome_zero_gen",
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
     ":perfetto_protos_perfetto_trace_gpu_zero_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
-    ":perfetto_protos_perfetto_trace_minimal_lite_gen",
     ":perfetto_protos_perfetto_trace_minimal_zero_gen",
     ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
     ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
@@ -111,7 +111,6 @@
     ":perfetto_protos_perfetto_trace_ps_zero_gen",
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
-    ":perfetto_protos_perfetto_trace_trusted_lite_gen",
     ":perfetto_src_base_base",
     ":perfetto_src_base_unix_socket",
     ":perfetto_src_ipc_ipc",
@@ -168,14 +167,14 @@
     "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_zero_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
     "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
     "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
     "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
@@ -184,7 +183,6 @@
     "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
   ],
   defaults: [
     "perfetto_defaults",
@@ -304,14 +302,14 @@
     ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_zero_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
     ":perfetto_protos_perfetto_trace_chrome_zero_gen",
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
     ":perfetto_protos_perfetto_trace_gpu_zero_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
-    ":perfetto_protos_perfetto_trace_minimal_lite_gen",
     ":perfetto_protos_perfetto_trace_minimal_zero_gen",
     ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
     ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
@@ -320,7 +318,6 @@
     ":perfetto_protos_perfetto_trace_ps_zero_gen",
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
-    ":perfetto_protos_perfetto_trace_trusted_lite_gen",
     ":perfetto_src_android_internal_headers",
     ":perfetto_src_android_internal_lazy_library_loader",
     ":perfetto_src_base_base",
@@ -386,14 +383,14 @@
     "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_zero_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
     "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
     "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
     "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
@@ -402,7 +399,6 @@
     "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
   ],
   defaults: [
     "perfetto_defaults",
@@ -492,14 +488,14 @@
     ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_zero_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
     ":perfetto_protos_perfetto_trace_chrome_zero_gen",
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
     ":perfetto_protos_perfetto_trace_gpu_zero_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
-    ":perfetto_protos_perfetto_trace_minimal_lite_gen",
     ":perfetto_protos_perfetto_trace_minimal_zero_gen",
     ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
     ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
@@ -508,7 +504,6 @@
     ":perfetto_protos_perfetto_trace_ps_zero_gen",
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
-    ":perfetto_protos_perfetto_trace_trusted_lite_gen",
     ":perfetto_src_base_base",
     ":perfetto_src_base_unix_socket",
     ":perfetto_src_ipc_ipc",
@@ -558,14 +553,14 @@
     "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_zero_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
     "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
     "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
     "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
@@ -574,7 +569,6 @@
     "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
   ],
   export_generated_headers: [
     "perfetto_protos_perfetto_common_cpp_gen_headers",
@@ -608,14 +602,14 @@
     "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_zero_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
     "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
     "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
     "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
@@ -624,7 +618,6 @@
     "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
   ],
   defaults: [
     "perfetto_defaults",
@@ -679,14 +672,14 @@
     ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_zero_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
     ":perfetto_protos_perfetto_trace_chrome_zero_gen",
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
     ":perfetto_protos_perfetto_trace_gpu_zero_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
-    ":perfetto_protos_perfetto_trace_minimal_lite_gen",
     ":perfetto_protos_perfetto_trace_minimal_zero_gen",
     ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
     ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
@@ -695,7 +688,6 @@
     ":perfetto_protos_perfetto_trace_ps_zero_gen",
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
-    ":perfetto_protos_perfetto_trace_trusted_lite_gen",
     ":perfetto_src_android_internal_headers",
     ":perfetto_src_android_internal_lazy_library_loader",
     ":perfetto_src_base_base",
@@ -747,14 +739,14 @@
     "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_zero_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
     "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
     "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
     "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
@@ -763,7 +755,6 @@
     "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
     "perfetto_src_perfetto_cmd_protos_gen_headers",
   ],
   defaults: [
@@ -937,7 +928,8 @@
     ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_zero_gen",
     ":perfetto_protos_perfetto_trace_android_lite_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
     ":perfetto_protos_perfetto_trace_chrome_lite_gen",
@@ -966,7 +958,6 @@
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_lite_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
-    ":perfetto_protos_perfetto_trace_trusted_lite_gen",
     ":perfetto_src_android_internal_headers",
     ":perfetto_src_android_internal_lazy_library_loader",
     ":perfetto_src_base_base",
@@ -1049,7 +1040,8 @@
     "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_zero_gen_headers",
     "perfetto_protos_perfetto_trace_android_lite_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
@@ -1078,7 +1070,6 @@
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
   ],
   defaults: [
     "perfetto_defaults",
@@ -2361,33 +2352,71 @@
   ],
 }
 
-// GN: //protos/perfetto/ipc:wire_protocol
+// GN: //protos/perfetto/ipc:wire_protocol_cpp
 genrule {
-  name: "perfetto_protos_perfetto_ipc_wire_protocol_gen",
+  name: "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
   srcs: [
     "protos/perfetto/ipc/wire_protocol.proto",
   ],
   tools: [
     "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/ipc/wire_protocol.pb.cc",
+    "external/perfetto/protos/perfetto/ipc/wire_protocol.gen.cc",
   ],
 }
 
-// GN: //protos/perfetto/ipc:wire_protocol
+// GN: //protos/perfetto/ipc:wire_protocol_cpp
 genrule {
-  name: "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
+  name: "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
   srcs: [
     "protos/perfetto/ipc/wire_protocol.proto",
   ],
   tools: [
     "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
   out: [
-    "external/perfetto/protos/perfetto/ipc/wire_protocol.pb.h",
+    "external/perfetto/protos/perfetto/ipc/wire_protocol.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
+  ],
+}
+
+// GN: //protos/perfetto/ipc:wire_protocol_zero
+genrule {
+  name: "perfetto_protos_perfetto_ipc_wire_protocol_zero_gen",
+  srcs: [
+    "protos/perfetto/ipc/wire_protocol.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "protozero_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/ipc/wire_protocol.pbzero.cc",
+  ],
+}
+
+// GN: //protos/perfetto/ipc:wire_protocol_zero
+genrule {
+  name: "perfetto_protos_perfetto_ipc_wire_protocol_zero_gen_headers",
+  srcs: [
+    "protos/perfetto/ipc/wire_protocol.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "protozero_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/ipc/wire_protocol.pbzero.h",
   ],
   export_include_dirs: [
     ".",
@@ -2409,7 +2438,7 @@
     "protos/perfetto/metrics/android/mem_unagg_metric.proto",
     "protos/perfetto/metrics/android/package_list.proto",
     "protos/perfetto/metrics/android/powrails_metric.proto",
-    "protos/perfetto/metrics/android/process_growth.proto",
+    "protos/perfetto/metrics/android/process_metadata.proto",
     "protos/perfetto/metrics/android/startup_metric.proto",
     "protos/perfetto/metrics/android/unsymbolized_frames.proto",
   ],
@@ -2429,7 +2458,7 @@
     "external/perfetto/protos/perfetto/metrics/android/mem_unagg_metric.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/package_list.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/powrails_metric.pbzero.cc",
-    "external/perfetto/protos/perfetto/metrics/android/process_growth.pbzero.cc",
+    "external/perfetto/protos/perfetto/metrics/android/process_metadata.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/startup_metric.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/unsymbolized_frames.pbzero.cc",
   ],
@@ -2449,7 +2478,7 @@
     "protos/perfetto/metrics/android/mem_unagg_metric.proto",
     "protos/perfetto/metrics/android/package_list.proto",
     "protos/perfetto/metrics/android/powrails_metric.proto",
-    "protos/perfetto/metrics/android/process_growth.proto",
+    "protos/perfetto/metrics/android/process_metadata.proto",
     "protos/perfetto/metrics/android/startup_metric.proto",
     "protos/perfetto/metrics/android/unsymbolized_frames.proto",
   ],
@@ -2469,7 +2498,7 @@
     "external/perfetto/protos/perfetto/metrics/android/mem_unagg_metric.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/package_list.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/powrails_metric.pbzero.h",
-    "external/perfetto/protos/perfetto/metrics/android/process_growth.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/process_metadata.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/startup_metric.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/unsymbolized_frames.pbzero.h",
   ],
@@ -3971,40 +4000,6 @@
   ],
 }
 
-// GN: //protos/perfetto/trace:trusted_lite
-genrule {
-  name: "perfetto_protos_perfetto_trace_trusted_lite_gen",
-  srcs: [
-    "protos/perfetto/trace/trusted_packet.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/trusted_packet.pb.cc",
-  ],
-}
-
-// GN: //protos/perfetto/trace:trusted_lite
-genrule {
-  name: "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
-  srcs: [
-    "protos/perfetto/trace/trusted_packet.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/trusted_packet.pb.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
 // GN: //protos/third_party/pprof:lite
 genrule {
   name: "perfetto_protos_third_party_pprof_lite_gen",
@@ -4419,6 +4414,7 @@
 filegroup {
   name: "perfetto_src_protozero_protozero",
   srcs: [
+    "src/protozero/field.cc",
     "src/protozero/message.cc",
     "src/protozero/message_handle.cc",
     "src/protozero/packed_repeated_fields.cc",
@@ -4426,6 +4422,55 @@
     "src/protozero/scattered_heap_buffer.cc",
     "src/protozero/scattered_stream_null_delegate.cc",
     "src/protozero/scattered_stream_writer.cc",
+    "src/protozero/static_buffer.cc",
+  ],
+}
+
+// GN: //src/protozero:testing_messages_cpp
+genrule {
+  name: "perfetto_src_protozero_testing_messages_cpp_gen",
+  srcs: [
+    "src/protozero/test/example_proto/library.proto",
+    "src/protozero/test/example_proto/library_internals/galaxies.proto",
+    "src/protozero/test/example_proto/test_messages.proto",
+    "src/protozero/test/example_proto/upper_import.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/src/protozero/test/example_proto/library.gen.cc",
+    "external/perfetto/src/protozero/test/example_proto/library_internals/galaxies.gen.cc",
+    "external/perfetto/src/protozero/test/example_proto/test_messages.gen.cc",
+    "external/perfetto/src/protozero/test/example_proto/upper_import.gen.cc",
+  ],
+}
+
+// GN: //src/protozero:testing_messages_cpp
+genrule {
+  name: "perfetto_src_protozero_testing_messages_cpp_gen_headers",
+  srcs: [
+    "src/protozero/test/example_proto/library.proto",
+    "src/protozero/test/example_proto/library_internals/galaxies.proto",
+    "src/protozero/test/example_proto/test_messages.proto",
+    "src/protozero/test/example_proto/upper_import.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/src/protozero/test/example_proto/library.gen.h",
+    "external/perfetto/src/protozero/test/example_proto/library_internals/galaxies.gen.h",
+    "external/perfetto/src/protozero/test/example_proto/test_messages.gen.h",
+    "external/perfetto/src/protozero/test/example_proto/upper_import.gen.h",
+  ],
+  export_include_dirs: [
+    ".",
+    "protos",
   ],
 }
 
@@ -4533,6 +4578,7 @@
     "src/protozero/proto_decoder_unittest.cc",
     "src/protozero/proto_utils_unittest.cc",
     "src/protozero/scattered_stream_writer_unittest.cc",
+    "src/protozero/test/cppgen_conformance_unittest.cc",
     "src/protozero/test/fake_scattered_buffer.cc",
     "src/protozero/test/protozero_conformance_unittest.cc",
   ],
@@ -4577,6 +4623,7 @@
     "src/trace_processor/counter_values_table.cc",
     "src/trace_processor/cpu_profile_stack_sample_table.cc",
     "src/trace_processor/filtered_row_index.cc",
+    "src/trace_processor/gfp_flags.cc",
     "src/trace_processor/heap_profile_allocation_table.cc",
     "src/trace_processor/instants_table.cc",
     "src/trace_processor/metadata_table.cc",
@@ -5017,6 +5064,7 @@
   name: "perfetto_src_tracing_client_api",
   srcs: [
     "src/tracing/data_source.cc",
+    "src/tracing/event_context.cc",
     "src/tracing/internal/in_process_tracing_backend.cc",
     "src/tracing/internal/system_tracing_backend.cc",
     "src/tracing/internal/tracing_muxer_impl.cc",
@@ -5024,7 +5072,6 @@
     "src/tracing/platform.cc",
     "src/tracing/tracing.cc",
     "src/tracing/track_event_category_registry.cc",
-    "src/tracing/track_event_context.cc",
     "src/tracing/virtual_destructors.cc",
   ],
 }
@@ -5389,7 +5436,8 @@
     ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_zero_gen",
     ":perfetto_protos_perfetto_metrics_android_zero_gen",
     ":perfetto_protos_perfetto_metrics_zero_gen",
     ":perfetto_protos_perfetto_trace_android_lite_gen",
@@ -5421,7 +5469,6 @@
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_lite_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
-    ":perfetto_protos_perfetto_trace_trusted_lite_gen",
     ":perfetto_src_android_internal_headers",
     ":perfetto_src_android_internal_lazy_library_loader",
     ":perfetto_src_base_base",
@@ -5446,6 +5493,7 @@
     ":perfetto_src_profiling_memory_wire_protocol",
     ":perfetto_src_profiling_unittests",
     ":perfetto_src_protozero_protozero",
+    ":perfetto_src_protozero_testing_messages_cpp_gen",
     ":perfetto_src_protozero_testing_messages_lite_gen",
     ":perfetto_src_protozero_testing_messages_zero_gen",
     ":perfetto_src_protozero_unittests",
@@ -5536,7 +5584,8 @@
     "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_zero_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",
@@ -5568,9 +5617,9 @@
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
     "perfetto_src_ipc_test_messages_gen_headers",
     "perfetto_src_perfetto_cmd_protos_gen_headers",
+    "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_lite_gen_headers",
@@ -5958,14 +6007,14 @@
     ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
+    ":perfetto_protos_perfetto_ipc_wire_protocol_zero_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
     ":perfetto_protos_perfetto_trace_chrome_zero_gen",
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
     ":perfetto_protos_perfetto_trace_gpu_zero_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
-    ":perfetto_protos_perfetto_trace_minimal_lite_gen",
     ":perfetto_protos_perfetto_trace_minimal_zero_gen",
     ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
     ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
@@ -5974,7 +6023,6 @@
     ":perfetto_protos_perfetto_trace_ps_zero_gen",
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
-    ":perfetto_protos_perfetto_trace_trusted_lite_gen",
     ":perfetto_src_base_base",
     ":perfetto_src_base_unix_socket",
     ":perfetto_src_ipc_ipc",
@@ -6023,14 +6071,14 @@
     "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+    "perfetto_protos_perfetto_ipc_wire_protocol_zero_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
     "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
     "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
     "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
@@ -6039,7 +6087,6 @@
     "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
     "perfetto_src_perfetto_cmd_protos_gen_headers",
   ],
   defaults: [
diff --git a/BUILD b/BUILD
index 57831e6..3da09d1 100644
--- a/BUILD
+++ b/BUILD
@@ -66,7 +66,8 @@
         ":include_perfetto_ext_ipc_ipc",
     ],
     deps = [
-        ":protos_perfetto_ipc_wire_protocol",
+        ":protos_perfetto_ipc_wire_protocol_cpp",
+        ":protos_perfetto_ipc_wire_protocol_zero",
     ] + PERFETTO_CONFIG.deps.protobuf_lite,
 )
 
@@ -182,14 +183,14 @@
         ":protos_perfetto_config_sys_stats_zero",
         ":protos_perfetto_config_zero",
         ":protos_perfetto_ipc_ipc",
-        ":protos_perfetto_ipc_wire_protocol",
+        ":protos_perfetto_ipc_wire_protocol_cpp",
+        ":protos_perfetto_ipc_wire_protocol_zero",
         ":protos_perfetto_trace_android_zero",
         ":protos_perfetto_trace_chrome_zero",
         ":protos_perfetto_trace_filesystem_zero",
         ":protos_perfetto_trace_ftrace_zero",
         ":protos_perfetto_trace_gpu_zero",
         ":protos_perfetto_trace_interned_data_zero",
-        ":protos_perfetto_trace_minimal_lite",
         ":protos_perfetto_trace_minimal_zero",
         ":protos_perfetto_trace_non_minimal_zero",
         ":protos_perfetto_trace_perfetto_zero",
@@ -198,7 +199,6 @@
         ":protos_perfetto_trace_ps_zero",
         ":protos_perfetto_trace_sys_stats_zero",
         ":protos_perfetto_trace_track_event_zero",
-        ":protos_perfetto_trace_trusted_lite",
     ] + PERFETTO_CONFIG.deps.protobuf_lite,
 )
 
@@ -354,6 +354,7 @@
         "include/perfetto/protozero/scattered_heap_buffer.h",
         "include/perfetto/protozero/scattered_stream_null_delegate.h",
         "include/perfetto/protozero/scattered_stream_writer.h",
+        "include/perfetto/protozero/static_buffer.h",
     ],
 )
 
@@ -409,6 +410,7 @@
     srcs = [
         "include/perfetto/tracing/buffer_exhausted_policy.h",
         "include/perfetto/tracing/data_source.h",
+        "include/perfetto/tracing/event_context.h",
         "include/perfetto/tracing/internal/basic_types.h",
         "include/perfetto/tracing/internal/data_source_internal.h",
         "include/perfetto/tracing/internal/tracing_muxer.h",
@@ -423,7 +425,6 @@
         "include/perfetto/tracing/tracing_backend.h",
         "include/perfetto/tracing/track_event.h",
         "include/perfetto/tracing/track_event_category_registry.h",
-        "include/perfetto/tracing/track_event_context.h",
         "include/perfetto/tracing/track_event_interned_data_index.h",
     ],
 )
@@ -528,6 +529,7 @@
 filegroup(
     name = "src_protozero_protozero",
     srcs = [
+        "src/protozero/field.cc",
         "src/protozero/message.cc",
         "src/protozero/message_handle.cc",
         "src/protozero/packed_repeated_fields.cc",
@@ -535,6 +537,7 @@
         "src/protozero/scattered_heap_buffer.cc",
         "src/protozero/scattered_stream_null_delegate.cc",
         "src/protozero/scattered_stream_writer.cc",
+        "src/protozero/static_buffer.cc",
     ],
 )
 
@@ -569,7 +572,6 @@
         "src/trace_processor/metrics/android/android_mem_unagg.sql",
         "src/trace_processor/metrics/android/android_package_list.sql",
         "src/trace_processor/metrics/android/android_powrails.sql",
-        "src/trace_processor/metrics/android/android_process_growth.sql",
         "src/trace_processor/metrics/android/android_startup.sql",
         "src/trace_processor/metrics/android/android_startup_cpu.sql",
         "src/trace_processor/metrics/android/android_startup_launches.sql",
@@ -578,6 +580,7 @@
         "src/trace_processor/metrics/android/java_heap_stats.sql",
         "src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql",
         "src/trace_processor/metrics/android/process_mem.sql",
+        "src/trace_processor/metrics/android/process_metadata.sql",
         "src/trace_processor/metrics/android/process_unagg_mem_view.sql",
         "src/trace_processor/metrics/android/span_view_stats.sql",
         "src/trace_processor/metrics/android/unsymbolized_frames.sql",
@@ -685,6 +688,8 @@
         "src/trace_processor/cpu_profile_stack_sample_table.h",
         "src/trace_processor/filtered_row_index.cc",
         "src/trace_processor/filtered_row_index.h",
+        "src/trace_processor/gfp_flags.cc",
+        "src/trace_processor/gfp_flags.h",
         "src/trace_processor/heap_profile_allocation_table.cc",
         "src/trace_processor/heap_profile_allocation_table.h",
         "src/trace_processor/instants_table.cc",
@@ -998,6 +1003,7 @@
     name = "src_tracing_client_api",
     srcs = [
         "src/tracing/data_source.cc",
+        "src/tracing/event_context.cc",
         "src/tracing/internal/in_process_tracing_backend.cc",
         "src/tracing/internal/in_process_tracing_backend.h",
         "src/tracing/internal/system_tracing_backend.cc",
@@ -1008,7 +1014,6 @@
         "src/tracing/platform.cc",
         "src/tracing/tracing.cc",
         "src/tracing/track_event_category_registry.cc",
-        "src/tracing/track_event_context.cc",
         "src/tracing/virtual_destructors.cc",
     ],
 )
@@ -1156,7 +1161,7 @@
     name = "protos_perfetto_common_cpp",
     deps = [
         ":protos_perfetto_common_protos",
-        ":protos_perfetto_common_lite",
+        ":protos_perfetto_common_zero",
     ],
 )
 
@@ -1183,6 +1188,9 @@
         "protos/perfetto/common/tracing_service_state.proto",
         "protos/perfetto/common/track_event_descriptor.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/common:zero
@@ -1198,8 +1206,8 @@
     name = "protos_perfetto_config_android_cpp",
     deps = [
         ":protos_perfetto_config_android_protos",
-        ":protos_perfetto_common_lite",
-        ":protos_perfetto_config_android_lite",
+        ":protos_perfetto_config_android_zero",
+        ":protos_perfetto_common_zero",
         ":protos_perfetto_common_cpp",
     ],
 )
@@ -1219,6 +1227,9 @@
         "protos/perfetto/config/android/android_log_config.proto",
         "protos/perfetto/config/android/packages_list_config.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
     deps = [
         ":protos_perfetto_common_protos",
     ],
@@ -1237,23 +1248,23 @@
     name = "protos_perfetto_config_cpp",
     deps = [
         ":protos_perfetto_config_protos",
-        ":protos_perfetto_config_inode_file_cpp",
+        ":protos_perfetto_config_gpu_zero",
+        ":protos_perfetto_config_profiling_zero",
         ":protos_perfetto_config_android_cpp",
-        ":protos_perfetto_config_lite",
-        ":protos_perfetto_config_android_lite",
+        ":protos_perfetto_config_sys_stats_zero",
         ":protos_perfetto_common_cpp",
-        ":protos_perfetto_config_gpu_lite",
-        ":protos_perfetto_common_lite",
-        ":protos_perfetto_config_profiling_lite",
         ":protos_perfetto_config_process_stats_cpp",
+        ":protos_perfetto_config_power_zero",
+        ":protos_perfetto_config_ftrace_zero",
         ":protos_perfetto_config_power_cpp",
-        ":protos_perfetto_config_process_stats_lite",
-        ":protos_perfetto_config_power_lite",
+        ":protos_perfetto_config_inode_file_cpp",
+        ":protos_perfetto_config_zero",
         ":protos_perfetto_config_profiling_cpp",
-        ":protos_perfetto_config_inode_file_lite",
         ":protos_perfetto_config_gpu_cpp",
-        ":protos_perfetto_config_ftrace_lite",
-        ":protos_perfetto_config_sys_stats_lite",
+        ":protos_perfetto_config_inode_file_zero",
+        ":protos_perfetto_config_android_zero",
+        ":protos_perfetto_config_process_stats_zero",
+        ":protos_perfetto_common_zero",
         ":protos_perfetto_config_ftrace_cpp",
         ":protos_perfetto_config_sys_stats_cpp",
     ],
@@ -1264,7 +1275,7 @@
     name = "protos_perfetto_config_ftrace_cpp",
     deps = [
         ":protos_perfetto_config_ftrace_protos",
-        ":protos_perfetto_config_ftrace_lite",
+        ":protos_perfetto_config_ftrace_zero",
     ],
 )
 
@@ -1282,6 +1293,9 @@
     srcs = [
         "protos/perfetto/config/ftrace/ftrace_config.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/config/ftrace:zero
@@ -1297,7 +1311,7 @@
     name = "protos_perfetto_config_gpu_cpp",
     deps = [
         ":protos_perfetto_config_gpu_protos",
-        ":protos_perfetto_config_gpu_lite",
+        ":protos_perfetto_config_gpu_zero",
     ],
 )
 
@@ -1315,6 +1329,9 @@
     srcs = [
         "protos/perfetto/config/gpu/gpu_counter_config.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/config/gpu:zero
@@ -1330,7 +1347,7 @@
     name = "protos_perfetto_config_inode_file_cpp",
     deps = [
         ":protos_perfetto_config_inode_file_protos",
-        ":protos_perfetto_config_inode_file_lite",
+        ":protos_perfetto_config_inode_file_zero",
     ],
 )
 
@@ -1348,6 +1365,9 @@
     srcs = [
         "protos/perfetto/config/inode_file/inode_file_config.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/config/inode_file:zero
@@ -1390,7 +1410,7 @@
     name = "protos_perfetto_config_power_cpp",
     deps = [
         ":protos_perfetto_config_power_protos",
-        ":protos_perfetto_config_power_lite",
+        ":protos_perfetto_config_power_zero",
     ],
 )
 
@@ -1408,6 +1428,9 @@
     srcs = [
         "protos/perfetto/config/power/android_power_config.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/config/power:zero
@@ -1423,7 +1446,7 @@
     name = "protos_perfetto_config_process_stats_cpp",
     deps = [
         ":protos_perfetto_config_process_stats_protos",
-        ":protos_perfetto_config_process_stats_lite",
+        ":protos_perfetto_config_process_stats_zero",
     ],
 )
 
@@ -1441,6 +1464,9 @@
     srcs = [
         "protos/perfetto/config/process_stats/process_stats_config.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/config/process_stats:zero
@@ -1456,7 +1482,7 @@
     name = "protos_perfetto_config_profiling_cpp",
     deps = [
         ":protos_perfetto_config_profiling_protos",
-        ":protos_perfetto_config_profiling_lite",
+        ":protos_perfetto_config_profiling_zero",
     ],
 )
 
@@ -1475,6 +1501,9 @@
         "protos/perfetto/config/profiling/heapprofd_config.proto",
         "protos/perfetto/config/profiling/java_hprof_config.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/config/profiling:zero
@@ -1494,6 +1523,9 @@
         "protos/perfetto/config/test_config.proto",
         "protos/perfetto/config/trace_config.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
     deps = [
         ":protos_perfetto_common_protos",
         ":protos_perfetto_config_android_protos",
@@ -1512,8 +1544,8 @@
     name = "protos_perfetto_config_sys_stats_cpp",
     deps = [
         ":protos_perfetto_config_sys_stats_protos",
-        ":protos_perfetto_common_lite",
-        ":protos_perfetto_config_sys_stats_lite",
+        ":protos_perfetto_config_sys_stats_zero",
+        ":protos_perfetto_common_zero",
         ":protos_perfetto_common_cpp",
     ],
 )
@@ -1532,6 +1564,9 @@
     srcs = [
         "protos/perfetto/config/sys_stats/sys_stats_config.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
     deps = [
         ":protos_perfetto_common_protos",
     ],
@@ -1557,17 +1592,20 @@
 perfetto_cc_ipc_library(
     name = "protos_perfetto_ipc_ipc",
     deps = [
-        ":protos_perfetto_ipc_ipc_protos",
+        ":protos_perfetto_ipc_protos",
     ],
 )
 
 # GN target: //protos/perfetto/ipc:ipc
 perfetto_proto_library(
-    name = "protos_perfetto_ipc_ipc_protos",
+    name = "protos_perfetto_ipc_protos",
     srcs = [
         "protos/perfetto/ipc/consumer_port.proto",
         "protos/perfetto/ipc/producer_port.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
     deps = [
         ":protos_perfetto_common_protos",
         ":protos_perfetto_config_android_protos",
@@ -1579,24 +1617,35 @@
         ":protos_perfetto_config_profiling_protos",
         ":protos_perfetto_config_protos",
         ":protos_perfetto_config_sys_stats_protos",
-        ":protos_perfetto_ipc_wire_protocol_protos",
     ],
 )
 
-# GN target: //protos/perfetto/ipc:wire_protocol
-perfetto_cc_proto_library(
-    name = "protos_perfetto_ipc_wire_protocol",
+# GN target: //protos/perfetto/ipc:wire_protocol_cpp
+perfetto_cc_protocpp_library(
+    name = "protos_perfetto_ipc_wire_protocol_cpp",
     deps = [
         ":protos_perfetto_ipc_wire_protocol_protos",
+        ":protos_perfetto_ipc_wire_protocol_zero",
     ],
 )
 
-# GN target: //protos/perfetto/ipc:wire_protocol
+# GN target: //protos/perfetto/ipc:wire_protocol_zero
 perfetto_proto_library(
     name = "protos_perfetto_ipc_wire_protocol_protos",
     srcs = [
         "protos/perfetto/ipc/wire_protocol.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
+)
+
+# GN target: //protos/perfetto/ipc:wire_protocol_zero
+perfetto_cc_protozero_library(
+    name = "protos_perfetto_ipc_wire_protocol_zero",
+    deps = [
+        ":protos_perfetto_ipc_wire_protocol_protos",
+    ],
 )
 
 # GN target: //protos/perfetto/metrics/android:lite
@@ -1621,10 +1670,13 @@
         "protos/perfetto/metrics/android/mem_unagg_metric.proto",
         "protos/perfetto/metrics/android/package_list.proto",
         "protos/perfetto/metrics/android/powrails_metric.proto",
-        "protos/perfetto/metrics/android/process_growth.proto",
+        "protos/perfetto/metrics/android/process_metadata.proto",
         "protos/perfetto/metrics/android/startup_metric.proto",
         "protos/perfetto/metrics/android/unsymbolized_frames.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/metrics/android:zero
@@ -1649,6 +1701,9 @@
     srcs = [
         "protos/perfetto/metrics/metrics.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
     deps = [
         ":protos_perfetto_metrics_android_protos",
     ],
@@ -1678,6 +1733,9 @@
         "protos/perfetto/trace/android/graphics_frame_event.proto",
         "protos/perfetto/trace/android/packages_list.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
     deps = [
         ":protos_perfetto_common_protos",
     ],
@@ -1707,6 +1765,9 @@
         "protos/perfetto/trace/chrome/chrome_metadata.proto",
         "protos/perfetto/trace/chrome/chrome_trace_event.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/trace/chrome:zero
@@ -1731,6 +1792,9 @@
     srcs = [
         "protos/perfetto/trace/filesystem/inode_file_map.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/trace/filesystem:zero
@@ -1787,6 +1851,9 @@
         "protos/perfetto/trace/ftrace/vmscan.proto",
         "protos/perfetto/trace/ftrace/workqueue.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/trace/ftrace:zero
@@ -1814,6 +1881,9 @@
         "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
         "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
     deps = [
         ":protos_perfetto_common_protos",
     ],
@@ -1841,6 +1911,9 @@
     srcs = [
         "protos/perfetto/trace/interned_data/interned_data.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
     deps = [
         ":protos_perfetto_trace_profiling_protos",
         ":protos_perfetto_trace_track_event_protos",
@@ -1890,6 +1963,9 @@
         "protos/perfetto/trace/system_info.proto",
         "protos/perfetto/trace/trigger.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
     deps = [
         ":protos_perfetto_common_protos",
         ":protos_perfetto_config_android_protos",
@@ -1929,6 +2005,9 @@
         "protos/perfetto/trace/trace_packet.proto",
         "protos/perfetto/trace/trace_packet_defaults.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
     deps = [
         ":protos_perfetto_common_protos",
         ":protos_perfetto_config_android_protos",
@@ -1978,6 +2057,9 @@
     srcs = [
         "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/trace/perfetto:zero
@@ -2003,6 +2085,9 @@
         "protos/perfetto/trace/power/battery_counters.proto",
         "protos/perfetto/trace/power/power_rails.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/trace/power:zero
@@ -2019,6 +2104,9 @@
     srcs = [
         "protos/perfetto/trace_processor/metrics_impl.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/trace_processor:metrics_impl_zero
@@ -2035,6 +2123,9 @@
     srcs = [
         "protos/perfetto/trace_processor/trace_processor.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/trace_processor:zero
@@ -2061,6 +2152,9 @@
         "protos/perfetto/trace/profiling/profile_common.proto",
         "protos/perfetto/trace/profiling/profile_packet.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/trace/profiling:zero
@@ -2086,6 +2180,9 @@
         "protos/perfetto/trace/ps/process_stats.proto",
         "protos/perfetto/trace/ps/process_tree.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/trace/ps:zero
@@ -2110,6 +2207,9 @@
     srcs = [
         "protos/perfetto/trace/sys_stats/sys_stats.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
     deps = [
         ":protos_perfetto_common_protos",
     ],
@@ -2144,6 +2244,9 @@
         "protos/perfetto/trace/track_event/track_descriptor.proto",
         "protos/perfetto/trace/track_event/track_event.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //protos/perfetto/trace/track_event:zero
@@ -2154,35 +2257,6 @@
     ],
 )
 
-# GN target: //protos/perfetto/trace:trusted_lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_trusted_lite",
-    deps = [
-        ":protos_perfetto_trace_trusted_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace:trusted_lite
-perfetto_proto_library(
-    name = "protos_perfetto_trace_trusted_protos",
-    srcs = [
-        "protos/perfetto/trace/trusted_packet.proto",
-    ],
-    deps = [
-        ":protos_perfetto_common_protos",
-        ":protos_perfetto_config_android_protos",
-        ":protos_perfetto_config_ftrace_protos",
-        ":protos_perfetto_config_gpu_protos",
-        ":protos_perfetto_config_inode_file_protos",
-        ":protos_perfetto_config_power_protos",
-        ":protos_perfetto_config_process_stats_protos",
-        ":protos_perfetto_config_profiling_protos",
-        ":protos_perfetto_config_protos",
-        ":protos_perfetto_config_sys_stats_protos",
-        ":protos_perfetto_trace_minimal_protos",
-    ],
-)
-
 # GN target: //protos/third_party/pprof:lite
 perfetto_cc_proto_library(
     name = "protos_third_party_pprof_lite",
@@ -2197,6 +2271,9 @@
     srcs = [
         "protos/third_party/pprof/profile.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # GN target: //src/perfetto_cmd:protos
@@ -2213,6 +2290,9 @@
     srcs = [
         "src/perfetto_cmd/perfetto_cmd_state.proto",
     ],
+    visibility = [
+        PERFETTO_CONFIG.proto_library_visibility,
+    ],
 )
 
 # ##############################################################################
@@ -2279,14 +2359,14 @@
         ":protos_perfetto_config_sys_stats_zero",
         ":protos_perfetto_config_zero",
         ":protos_perfetto_ipc_ipc",
-        ":protos_perfetto_ipc_wire_protocol",
+        ":protos_perfetto_ipc_wire_protocol_cpp",
+        ":protos_perfetto_ipc_wire_protocol_zero",
         ":protos_perfetto_trace_android_zero",
         ":protos_perfetto_trace_chrome_zero",
         ":protos_perfetto_trace_filesystem_zero",
         ":protos_perfetto_trace_ftrace_zero",
         ":protos_perfetto_trace_gpu_zero",
         ":protos_perfetto_trace_interned_data_zero",
-        ":protos_perfetto_trace_minimal_lite",
         ":protos_perfetto_trace_minimal_zero",
         ":protos_perfetto_trace_non_minimal_zero",
         ":protos_perfetto_trace_perfetto_zero",
@@ -2295,7 +2375,6 @@
         ":protos_perfetto_trace_ps_zero",
         ":protos_perfetto_trace_sys_stats_zero",
         ":protos_perfetto_trace_track_event_zero",
-        ":protos_perfetto_trace_trusted_lite",
     ] + PERFETTO_CONFIG.deps.protobuf_lite,
 )
 
@@ -2360,14 +2439,14 @@
                ":protos_perfetto_config_sys_stats_zero",
                ":protos_perfetto_config_zero",
                ":protos_perfetto_ipc_ipc",
-               ":protos_perfetto_ipc_wire_protocol",
+               ":protos_perfetto_ipc_wire_protocol_cpp",
+               ":protos_perfetto_ipc_wire_protocol_zero",
                ":protos_perfetto_trace_android_zero",
                ":protos_perfetto_trace_chrome_zero",
                ":protos_perfetto_trace_filesystem_zero",
                ":protos_perfetto_trace_ftrace_zero",
                ":protos_perfetto_trace_gpu_zero",
                ":protos_perfetto_trace_interned_data_zero",
-               ":protos_perfetto_trace_minimal_lite",
                ":protos_perfetto_trace_minimal_zero",
                ":protos_perfetto_trace_non_minimal_zero",
                ":protos_perfetto_trace_perfetto_zero",
@@ -2376,7 +2455,6 @@
                ":protos_perfetto_trace_ps_zero",
                ":protos_perfetto_trace_sys_stats_zero",
                ":protos_perfetto_trace_track_event_zero",
-               ":protos_perfetto_trace_trusted_lite",
                ":src_perfetto_cmd_protos",
            ] + PERFETTO_CONFIG.deps.protobuf_lite +
            PERFETTO_CONFIG.deps.zlib,
diff --git a/bazel/standalone/perfetto_cfg.bzl b/bazel/standalone/perfetto_cfg.bzl
index 1ee8e52..1e8f6d0 100644
--- a/bazel/standalone/perfetto_cfg.bzl
+++ b/bazel/standalone/perfetto_cfg.bzl
@@ -55,6 +55,11 @@
         sqlite = [],
     ),
 
+    # Allow Bazel embedders to change the visibility of the proto targets.
+    # This variable has been introduced to limit the change to Bazel and avoid
+    # making the targets public in the google internal tree.
+    proto_library_visibility = "//visibility:private",
+
     # This struct allows the embedder to customize copts and other args passed
     # to rules like cc_binary. Prefixed rules (e.g. perfetto_cc_binary) will
     # look into this struct before falling back on native.cc_binary().
diff --git a/docs/security-model.md b/docs/security-model.md
index bff44a9..369e6cc 100644
--- a/docs/security-model.md
+++ b/docs/security-model.md
@@ -51,10 +51,9 @@
 untrusted-and-unprivileged and trusted-and-more-privileged entities).
 
 **Attestation of trace contents**  
-The tracing service guarantees that the `TracePacket` fields defined also in
-[trusted_packet.proto](/protos/perfetto/trace/trusted_packet.proto) cannot be
-spoofed by the Producer(s). Packets that try to define those fields are rejected
-(modulo the clock snapshots).  
+The tracing service guarantees that the `TracePacket` fields written by the
+Service cannot be spoofed by the Producer(s).  
+Packets that try to define those fields are rejected, modulo clock snapshots.  
 See [PacketStreamValidator](/src/tracing/core/packet_stream_validator.cc) and
 [its unit test](/src/tracing/core/packet_stream_validator_unittest.cc) for more
 details.  
diff --git a/docs/trace-format.md b/docs/trace-format.md
index ca5db49..ec6c3eb 100644
--- a/docs/trace-format.md
+++ b/docs/trace-format.md
@@ -9,9 +9,9 @@
 (see [trace_packet.proto](/protos/perfetto/trace/trace_packet.proto)).
 
 As a key part of the Perfetto design, the tracing service is agnostic of the
-content of TracePacket, modulo the few fields defined in
-[trusted_packet.proto](/protos/perfetto/trace/trusted_packet.proto) that are
-produced by the service itself.
+content of TracePacket, modulo few fields (e.g., `trusted_packed_*`,
+clock snapshots, copy of the original config) that are produced by the service
+itself.
 
 Each data source can extend the trace with their app-specific protobuf schema.
 *** aside
diff --git a/gn/proto_library.gni b/gn/proto_library.gni
index c7af114..3e96c4d 100644
--- a/gn/proto_library.gni
+++ b/gn/proto_library.gni
@@ -182,11 +182,11 @@
         forward_variables_from(invoker, vars_to_forward)
       }
     } else if (gen_type == "cpp") {
-      lite_target_name_ = string_replace(target_name, expansion_token, "lite")
+      zero_target_name_ = string_replace(target_name, expansion_token, "zero")
       protozero_cpp_library(target_name_) {
         proto_in_dir = proto_path
         proto_out_dir = proto_path
-        deps = deps_ + [ ":$lite_target_name_" ]
+        deps = deps_ + [ ":$zero_target_name_" ]
         forward_variables_from(invoker, vars_to_forward)
       }
     } else if (gen_type == "lite") {
diff --git a/gn/standalone/toolchain/BUILD.gn b/gn/standalone/toolchain/BUILD.gn
index 7394802..4f38ceb 100644
--- a/gn/standalone/toolchain/BUILD.gn
+++ b/gn/standalone/toolchain/BUILD.gn
@@ -179,7 +179,7 @@
         command = "rm -f {{output}} && libtool -static {{arflags}} -o {{output}} -filelist $rspfile"
       } else {
         rspfile_content = "{{inputs}}"
-        command = "$ar rcsD {{output}} @$rspfile"
+        command = "rm -f {{output}} && $ar rcsD {{output}} @$rspfile"
       }
       outputs = [
         "{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
diff --git a/include/perfetto/protozero/BUILD.gn b/include/perfetto/protozero/BUILD.gn
index 994ff60..7afe1b9 100644
--- a/include/perfetto/protozero/BUILD.gn
+++ b/include/perfetto/protozero/BUILD.gn
@@ -28,5 +28,6 @@
     "scattered_heap_buffer.h",
     "scattered_stream_null_delegate.h",
     "scattered_stream_writer.h",
+    "static_buffer.h",
   ]
 }
diff --git a/include/perfetto/protozero/field.h b/include/perfetto/protozero/field.h
index f76fe84..69b2a15 100644
--- a/include/perfetto/protozero/field.h
+++ b/include/perfetto/protozero/field.h
@@ -182,6 +182,10 @@
     *val = static_cast<T>(as_int32());
   }
 
+  // Serializes the field back into a proto-encoded byte stream and appends it
+  // to |dst|. |dst| is resized accordingly.
+  void SerializeAndAppendTo(std::string* dst);
+
  private:
   // Fields are deliberately not initialized to keep the class trivially
   // constructible. It makes a large perf difference for ProtoDecoder.
diff --git a/include/perfetto/protozero/message.h b/include/perfetto/protozero/message.h
index 213a436..c3fdfd6 100644
--- a/include/perfetto/protozero/message.h
+++ b/include/perfetto/protozero/message.h
@@ -171,6 +171,16 @@
 
   ScatteredStreamWriter* stream_writer_for_testing() { return stream_writer_; }
 
+  // Appends some raw bytes to the message. The use-case for this is preserving
+  // unknown fields in the decode -> re-encode path of xxx.gen.cc classes
+  // generated by the cppgen_plugin.cc.
+  // The caller needs to guarantee that the appended data is properly
+  // proto-encoded and each field has a proto preamble.
+  void AppendRawProtoBytes(const void* data, size_t size) {
+    const uint8_t* src = reinterpret_cast<const uint8_t*>(data);
+    WriteToStream(src, src + size);
+  }
+
  private:
   Message(const Message&) = delete;
   Message& operator=(const Message&) = delete;
diff --git a/include/perfetto/protozero/proto_utils.h b/include/perfetto/protozero/proto_utils.h
index 8a93951..d8f0592 100644
--- a/include/perfetto/protozero/proto_utils.h
+++ b/include/perfetto/protozero/proto_utils.h
@@ -225,20 +225,22 @@
 // buffer.
 inline const uint8_t* ParseVarInt(const uint8_t* start,
                                   const uint8_t* end,
-                                  uint64_t* value) {
+                                  uint64_t* out_value) {
   const uint8_t* pos = start;
-  uint64_t shift = 0;
-  *value = 0;
-  do {
-    if (PERFETTO_UNLIKELY(pos >= end)) {
-      *value = 0;
-      return start;
+  uint64_t value = 0;
+  for (uint32_t shift = 0; pos < end && shift < 64u; shift += 7) {
+    // Cache *pos into |cur_byte| to prevent that the compiler dereferences the
+    // pointer twice (here and in the if() below) due to char* aliasing rules.
+    uint8_t cur_byte = *pos++;
+    value |= static_cast<uint64_t>(cur_byte & 0x7f) << shift;
+    if ((cur_byte & 0x80) == 0) {
+      // In valid cases we get here.
+      *out_value = value;
+      return pos;
     }
-    PERFETTO_DCHECK(shift < 64ull);
-    *value |= static_cast<uint64_t>(*pos & 0x7f) << shift;
-    shift += 7;
-  } while (*pos++ & 0x80);
-  return pos;
+  }
+  *out_value = 0;
+  return start;
 }
 
 }  // namespace proto_utils
diff --git a/include/perfetto/protozero/static_buffer.h b/include/perfetto/protozero/static_buffer.h
new file mode 100644
index 0000000..6f5924f
--- /dev/null
+++ b/include/perfetto/protozero/static_buffer.h
@@ -0,0 +1,101 @@
+/*
+ * 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 INCLUDE_PERFETTO_PROTOZERO_STATIC_BUFFER_H_
+#define INCLUDE_PERFETTO_PROTOZERO_STATIC_BUFFER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "perfetto/base/export.h"
+#include "perfetto/protozero/scattered_stream_writer.h"
+
+namespace protozero {
+
+class Message;
+
+// A simple implementation of ScatteredStreamWriter::Delegate backed by a
+// fixed-size buffer. It doesn't support expansion. The caller needs to ensure
+// to never write more than the size of the buffer. Will CHECK() otherwise.
+class PERFETTO_EXPORT StaticBufferDelegate
+    : public ScatteredStreamWriter::Delegate {
+ public:
+  StaticBufferDelegate(uint8_t* buf, size_t len) : range_{buf, buf + len} {}
+  ~StaticBufferDelegate() override;
+
+  // ScatteredStreamWriter::Delegate implementation.
+  ContiguousMemoryRange GetNewBuffer() override;
+
+  ContiguousMemoryRange const range_;
+  bool get_new_buffer_called_once_ = false;
+};
+
+// Helper function to create protozero messages backed by a fixed-size buffer
+// in one line. You can write:
+//   protozero::Static<protozero::MyMessage> msg(buf.data(), buf.size());
+//   msg->set_stuff(...);
+//   size_t bytes_encoded = msg.Finalize();
+template <typename T /* protozero::Message */>
+class StaticBuffered {
+ public:
+  StaticBuffered(void* buf, size_t len)
+      : delegate_(reinterpret_cast<uint8_t*>(buf), len), writer_(&delegate_) {
+    msg_.Reset(&writer_);
+  }
+
+  // This can't be neither copied nor moved because Message hands out pointers
+  // to itself when creating submessages.
+  StaticBuffered(const StaticBuffered&) = delete;
+  StaticBuffered& operator=(const StaticBuffered&) = delete;
+  StaticBuffered(StaticBuffered&&) = delete;
+  StaticBuffered& operator=(StaticBuffered&&) = delete;
+
+  T* get() { return &msg_; }
+  T* operator->() { return &msg_; }
+
+  // The lack of a size() method is deliberate. It's to prevent that one
+  // accidentally calls size() before Finalize().
+
+  // Returns the number of encoded bytes (<= the size passed in the ctor).
+  size_t Finalize() {
+    msg_.Finalize();
+    return static_cast<size_t>(writer_.write_ptr() - delegate_.range_.begin);
+  }
+
+ private:
+  StaticBufferDelegate delegate_;
+  ScatteredStreamWriter writer_;
+  T msg_;
+};
+
+// Helper function to create stack-based protozero messages in one line.
+// You can write:
+//   protozero::StackBuffered<protozero::MyMessage, 16> msg;
+//   msg->set_stuff(...);
+//   size_t bytes_encoded = msg.Finalize();
+template <typename T /* protozero::Message */, size_t N>
+class StackBuffered : public StaticBuffered<T> {
+ public:
+  StackBuffered() : StaticBuffered<T>(&buf_[0], N) {}
+
+ private:
+  uint8_t buf_[N];  // Deliberately not initialized.
+};
+
+}  // namespace protozero
+
+#endif  // INCLUDE_PERFETTO_PROTOZERO_STATIC_BUFFER_H_
diff --git a/include/perfetto/tracing/BUILD.gn b/include/perfetto/tracing/BUILD.gn
index e40d43f..57d8619 100644
--- a/include/perfetto/tracing/BUILD.gn
+++ b/include/perfetto/tracing/BUILD.gn
@@ -26,6 +26,7 @@
   sources = [
     "buffer_exhausted_policy.h",
     "data_source.h",
+    "event_context.h",
     "internal/basic_types.h",
     "internal/data_source_internal.h",
     "internal/tracing_muxer.h",
@@ -40,7 +41,6 @@
     "tracing_backend.h",
     "track_event.h",
     "track_event_category_registry.h",
-    "track_event_context.h",
     "track_event_interned_data_index.h",
   ]
 }
diff --git a/include/perfetto/tracing/track_event_context.h b/include/perfetto/tracing/event_context.h
similarity index 68%
rename from include/perfetto/tracing/track_event_context.h
rename to include/perfetto/tracing/event_context.h
index 5cf657a..da1607b 100644
--- a/include/perfetto/tracing/track_event_context.h
+++ b/include/perfetto/tracing/event_context.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef INCLUDE_PERFETTO_TRACING_TRACK_EVENT_CONTEXT_H_
-#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_CONTEXT_H_
+#ifndef INCLUDE_PERFETTO_TRACING_EVENT_CONTEXT_H_
+#define INCLUDE_PERFETTO_TRACING_EVENT_CONTEXT_H_
 
 #include "perfetto/protozero/message_handle.h"
 #include "perfetto/tracing/internal/track_event_internal.h"
@@ -29,18 +29,18 @@
 // Allows adding custom arguments into track events. Example:
 //
 //   TRACE_EVENT_BEGIN("category", "Title",
-//                     [](perfetto::TrackEventContext ctx) {
-//                       auto* dbg = ctx.track_event()->add_debug_annotations();
+//                     [](perfetto::EventContext ctx) {
+//                       auto* dbg = ctx.event()->add_debug_annotations();
 //                       dbg->set_name("name");
 //                       dbg->set_int_value(1234);
 //                     });
 //
-class TrackEventContext {
+class EventContext {
  public:
-  TrackEventContext(TrackEventContext&&) = default;
-  ~TrackEventContext();
+  EventContext(EventContext&&) = default;
+  ~EventContext();
 
-  protos::pbzero::TrackEvent* track_event() const { return track_event_; }
+  protos::pbzero::TrackEvent* event() const { return event_; }
 
  private:
   template <typename, size_t, typename, typename>
@@ -50,14 +50,14 @@
   using TracePacketHandle =
       ::protozero::MessageHandle<protos::pbzero::TracePacket>;
 
-  TrackEventContext(TracePacketHandle, internal::TrackEventIncrementalState*);
-  TrackEventContext(const TrackEventContext&) = delete;
+  EventContext(TracePacketHandle, internal::TrackEventIncrementalState*);
+  EventContext(const EventContext&) = delete;
 
   TracePacketHandle trace_packet_;
-  protos::pbzero::TrackEvent* track_event_;
+  protos::pbzero::TrackEvent* event_;
   internal::TrackEventIncrementalState* incremental_state_;
 };
 
 }  // namespace perfetto
 
-#endif  // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_CONTEXT_H_
+#endif  // INCLUDE_PERFETTO_TRACING_EVENT_CONTEXT_H_
diff --git a/include/perfetto/tracing/internal/track_event_data_source.h b/include/perfetto/tracing/internal/track_event_data_source.h
index ec5e632..6a2ae69 100644
--- a/include/perfetto/tracing/internal/track_event_data_source.h
+++ b/include/perfetto/tracing/internal/track_event_data_source.h
@@ -20,9 +20,9 @@
 #include "perfetto/base/compiler.h"
 #include "perfetto/protozero/message_handle.h"
 #include "perfetto/tracing/data_source.h"
+#include "perfetto/tracing/event_context.h"
 #include "perfetto/tracing/internal/track_event_internal.h"
 #include "perfetto/tracing/track_event_category_registry.h"
-#include "perfetto/tracing/track_event_context.h"
 #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
 
 #include <unordered_map>
@@ -81,13 +81,12 @@
   // TODO(skyostil): Investigate whether this should be fully outlined to reduce
   // binary size.
   template <size_t CategoryIndex,
-            typename ArgumentFunction = void (*)(TrackEventContext)>
+            typename ArgumentFunction = void (*)(EventContext)>
   static void TraceForCategory(
       uint32_t instances,
       const char* event_name,
       perfetto::protos::pbzero::TrackEvent::Type type,
-      ArgumentFunction arg_function = [](TrackEventContext) {
-      }) PERFETTO_NO_INLINE {
+      ArgumentFunction arg_function = [](EventContext) {}) PERFETTO_NO_INLINE {
     Base::template TraceWithInstances<CategoryTracePointTraits<CategoryIndex>>(
         instances, [&](typename Base::TraceContext ctx) {
           // TODO(skyostil): Intern categories at compile time.
diff --git a/include/perfetto/tracing/internal/track_event_internal.h b/include/perfetto/tracing/internal/track_event_internal.h
index c303938..a1465e5 100644
--- a/include/perfetto/tracing/internal/track_event_internal.h
+++ b/include/perfetto/tracing/internal/track_event_internal.h
@@ -25,9 +25,9 @@
 #include <unordered_map>
 
 namespace perfetto {
+class EventContext;
 class DataSourceConfig;
 class DataSourceDescriptor;
-class TrackEventContext;
 
 namespace internal {
 class TrackEventCategoryRegistry;
@@ -49,10 +49,10 @@
   // A heap-allocated message for storing newly seen interned data while we are
   // in the middle of writing a track event. When a track event wants to write
   // new interned data into the trace, it is first serialized into this message
-  // and then flushed to the real trace in TrackEventContext when the packet
-  // ends. The message is cached here as a part of incremental state so that we
-  // can reuse the underlying buffer allocation for subsequently written
-  // interned data.
+  // and then flushed to the real trace in EventContext when the packet ends.
+  // The message is cached here as a part of incremental state so that we can
+  // reuse the underlying buffer allocation for subsequently written interned
+  // data.
   protozero::HeapBuffered<protos::pbzero::InternedData>
       serialized_interned_data;
 
@@ -81,7 +81,7 @@
   static void DisableTracing(const TrackEventCategoryRegistry& registry,
                              uint32_t instance_index);
 
-  static perfetto::TrackEventContext WriteEvent(
+  static perfetto::EventContext WriteEvent(
       TraceWriterBase*,
       TrackEventIncrementalState*,
       const char* category,
diff --git a/include/perfetto/tracing/track_event.h b/include/perfetto/tracing/track_event.h
index 5b909be..2b7d1dd 100644
--- a/include/perfetto/tracing/track_event.h
+++ b/include/perfetto/tracing/track_event.h
@@ -71,7 +71,7 @@
 //      event   |     '--------------------------------'     |  arguments
 //              V                                            V
 //  .----------------------------------.    .-----------------------------.
-//  | TrackEvent                       |    | TrackEventContext           |
+//  | TrackEvent                       |    | EventContext                |
 //  |  - Registry of event categories  |    |  - One track event instance |
 //  '----------------------------------'    '-----------------------------'
 //              |                                            |
diff --git a/include/perfetto/tracing/track_event_interned_data_index.h b/include/perfetto/tracing/track_event_interned_data_index.h
index e1ef7ee..9d8935a 100644
--- a/include/perfetto/tracing/track_event_interned_data_index.h
+++ b/include/perfetto/tracing/track_event_interned_data_index.h
@@ -55,8 +55,8 @@
 // string will only be emitted the first time the trace point is hit.
 //
 //   TRACE_EVENT_BEGIN(
-//      "category", "Event", [&](perfetto::TrackEventContext ctx) {
-//        auto my_message = ctx.track_event()->set_my_message();
+//      "category", "Event", [&](perfetto::EventContext ctx) {
+//        auto my_message = ctx.event()->set_my_message();
 //        size_t iid = MyInternedData::Get(&ctx, "Some data");
 //        my_message->set_iid(iid);
 //      });
@@ -170,7 +170,7 @@
  public:
   // Return an interning id for |value|. The returned id can be immediately
   // written to the trace.
-  static size_t Get(TrackEventContext* ctx, const ValueType& value) {
+  static size_t Get(EventContext* ctx, const ValueType& value) {
     // First check if the value exists in the dictionary.
     auto index_for_field = GetOrCreateIndexForField(ctx->incremental_state_);
     size_t iid;
diff --git a/protos/perfetto/ipc/BUILD.gn b/protos/perfetto/ipc/BUILD.gn
index 48f54a1..c65b9f4 100644
--- a/protos/perfetto/ipc/BUILD.gn
+++ b/protos/perfetto/ipc/BUILD.gn
@@ -30,8 +30,11 @@
   ]
 }
 
-perfetto_proto_library("wire_protocol") {
-  proto_generators = [ "lite" ]
+perfetto_proto_library("wire_protocol_@TYPE@") {
+  proto_generators = [
+    "zero",
+    "cpp",
+  ]
   sources = [
     "wire_protocol.proto",
   ]
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index 41353b0..3f8571c 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -26,7 +26,7 @@
     "mem_unagg_metric.proto",
     "package_list.proto",
     "powrails_metric.proto",
-    "process_growth.proto",
+    "process_metadata.proto",
     "startup_metric.proto",
     "unsymbolized_frames.proto",
   ]
diff --git a/protos/perfetto/metrics/android/heap_profile_callsites.proto b/protos/perfetto/metrics/android/heap_profile_callsites.proto
index d19bba3..df1a516 100644
--- a/protos/perfetto/metrics/android/heap_profile_callsites.proto
+++ b/protos/perfetto/metrics/android/heap_profile_callsites.proto
@@ -18,6 +18,8 @@
 
 package perfetto.protos;
 
+import "protos/perfetto/metrics/android/process_metadata.proto";
+
 message HeapProfileCallsites {
   message Frame {
     optional string name = 1;
@@ -51,10 +53,12 @@
   }
 
   // Callsites per process instance.
-  // Next id: 6
+  // Next id: 7
   message InstanceStats {
     optional uint32 pid = 1;
+    // TODO(ilkos): Remove process_name in favour of the metadata.
     optional string process_name = 2;
+    optional AndroidProcessMetadata process = 6;
     repeated Callsite callsites = 3;
 
     // Bytes allocated via malloc but not freed.
diff --git a/protos/perfetto/metrics/android/java_heap_stats.proto b/protos/perfetto/metrics/android/java_heap_stats.proto
index a5e1513..e07190b 100644
--- a/protos/perfetto/metrics/android/java_heap_stats.proto
+++ b/protos/perfetto/metrics/android/java_heap_stats.proto
@@ -18,6 +18,8 @@
 
 package perfetto.protos;
 
+import "protos/perfetto/metrics/android/process_metadata.proto";
+
 message JavaHeapStats {
   message Sample {
     optional int64 ts = 1;
@@ -29,7 +31,7 @@
   // dump is enabled).
   message InstanceStats {
     optional uint32 upid = 1;
-    optional string process_name = 2;
+    optional AndroidProcessMetadata process = 2;
     repeated Sample samples = 3;
   }
 
diff --git a/protos/perfetto/metrics/android/process_growth.proto b/protos/perfetto/metrics/android/process_growth.proto
deleted file mode 100644
index 50fcec5..0000000
--- a/protos/perfetto/metrics/android/process_growth.proto
+++ /dev/null
@@ -1,39 +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.
- */
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-message AndroidProcessGrowth {
-  // Next id: 7
-  message InstanceMetrics {
-    optional uint32 pid = 1;
-    optional string process_name = 2;
-
-    optional int64 anon_and_swap_start_value = 5;
-    optional int64 anon_and_swap_change_bytes = 3;
-
-    // Bytes allocated via malloc but not freed.
-    // Only applicable with a heap profile.
-    optional int64 malloc_memory_change_bytes = 4;
-    // Total bytes allocated via malloc. Only applicable with a heap profile.
-    optional int64 malloc_memory_total_allocated_bytes = 6;
-  }
-
-  // Process memory per process instance.
-  repeated InstanceMetrics instance_metrics = 1;
-}
diff --git a/protos/perfetto/metrics/android/process_metadata.proto b/protos/perfetto/metrics/android/process_metadata.proto
new file mode 100644
index 0000000..9c35812
--- /dev/null
+++ b/protos/perfetto/metrics/android/process_metadata.proto
@@ -0,0 +1,27 @@
+/*
+ * 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 AndroidProcessMetadata {
+  optional string name = 1;
+  optional int64 uid = 2;
+  optional string package_name = 3;
+  optional int64 apk_version_code = 4;
+  optional bool debuggable = 5;
+}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index 508e830..6225559 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -23,7 +23,6 @@
 import "protos/perfetto/metrics/android/cpu_metric.proto";
 import "protos/perfetto/metrics/android/mem_metric.proto";
 import "protos/perfetto/metrics/android/mem_unagg_metric.proto";
-import "protos/perfetto/metrics/android/process_growth.proto";
 import "protos/perfetto/metrics/android/ion_metric.proto";
 import "protos/perfetto/metrics/android/lmk_metric.proto";
 import "protos/perfetto/metrics/android/powrails_metric.proto";
@@ -51,7 +50,7 @@
 //
 // Next id: 18
 message TraceMetrics {
-  reserved 4, 13, 14;
+  reserved 4, 10, 13, 14;
 
   // Battery counters metric on Android.
   optional AndroidBatteryMetric android_batt = 5;
@@ -71,9 +70,6 @@
   // Package list.
   optional AndroidPackageList android_package_list = 12;
 
-  // Per-process memory growth metrics.
-  optional AndroidProcessGrowth android_process_growth = 10;
-
   // ion buffer memory metrics.
   optional AndroidIonMetric android_ion = 9;
 
diff --git a/protos/perfetto/trace/BUILD.gn b/protos/perfetto/trace/BUILD.gn
index ca76396..bc312e0 100644
--- a/protos/perfetto/trace/BUILD.gn
+++ b/protos/perfetto/trace/BUILD.gn
@@ -39,9 +39,6 @@
   "system_info.proto",
 ]
 
-# Used only for packet_stream_validator.cc (in the service).
-proto_sources_trusted = [ "trusted_packet.proto" ]
-
 # Most targets should either depend on :zero (writers) / :lite (readers)
 # or ":minimal_zero" / :minimal_lite (mostly for chrome).
 
@@ -95,17 +92,6 @@
   sources = proto_sources_minimal
 }
 
-# Used by the traced service for packet sanitization.
-perfetto_proto_library("trusted_@TYPE@") {
-  proto_generators = [ "lite" ]
-  deps = [
-    ":minimal_@TYPE@",
-    "../common:@TYPE@",
-    "../config:@TYPE@",
-  ]
-  sources = proto_sources_trusted
-}
-
 # This target is not used in the tree and is built only to guarantee that the
 # autogenerated merged proto has a valid syntax.
 perfetto_proto_library("merged_trace") {
diff --git a/protos/perfetto/trace/trusted_packet.proto b/protos/perfetto/trace/trusted_packet.proto
deleted file mode 100644
index 8316994..0000000
--- a/protos/perfetto/trace/trusted_packet.proto
+++ /dev/null
@@ -1,63 +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.
- */
-
-// Use proto3 syntax as an optimization. The difference is that proto2 stores
-// unknown fields seen while decoding in an internal buffer (std::string) while
-// proto3 completely drops them. Since during validation we only need to check
-// for the presence of the trusted fields below, we can use proto3 as a way to
-// speed up this process.
-//
-// See https://developers.google.com/protocol-buffers/docs/proto3#unknowns and
-// https://android-review.googlesource.com/c/platform/external/perfetto/+/
-// 591673#17 for details.
-syntax = "proto3";
-option optimize_for = LITE_RUNTIME;
-
-import "protos/perfetto/common/trace_stats.proto";
-import "protos/perfetto/config/trace_config.proto";
-import "protos/perfetto/trace/clock_snapshot.proto";
-import "protos/perfetto/trace/system_info.proto";
-import "protos/perfetto/trace/trigger.proto";
-
-package perfetto.protos;
-
-// This proto contains trusted fields of TracePacket which may only be generated
-// by the service (as opposed to the untrusted producers). Note that the field
-// ids here must be kept in sync with TracePacket.
-// This protobuf serves two purposes:
-// 1. Security validation of packets (see packet_stream_validator.cc)
-// 2. Avoid bloating the service binary with symbols for all possible trace
-//    protos. The service doesn't really care about all the protos in the trace,
-//    is just passes them through.
-message TrustedPacket {
-  // User id of the producer which generated this packet.
-  // The oneof boilerplate here is required to tell the difference between
-  // uid == 0 and uid not set (the writer uses proto2).
-  oneof optional_trusted_uid { int32 trusted_uid = 3; };
-
-  oneof optional_trusted_packet_sequence_id {
-    uint32 trusted_packet_sequence_id = 10;
-  }
-
-  ClockSnapshot clock_snapshot = 6;
-  uint64 timestamp = 8;
-  TraceConfig trace_config = 33;
-  TraceStats trace_stats = 35;
-  bytes synchronization_marker = 36;
-  bool previous_packet_dropped = 42;
-  SystemInfo system_info = 45;
-  Trigger trigger = 46;
-}
diff --git a/src/ipc/BUILD.gn b/src/ipc/BUILD.gn
index ed0ecd2..bf2b1af 100644
--- a/src/ipc/BUILD.gn
+++ b/src/ipc/BUILD.gn
@@ -31,7 +31,7 @@
   deps = [
     "../../gn:default_deps",
     "../../gn:protobuf_lite",
-    "../../protos/perfetto/ipc:wire_protocol",
+    "../../protos/perfetto/ipc:wire_protocol_cpp",
     "../base",
   ]
   sources = [
@@ -54,7 +54,7 @@
   deps = [
     ":ipc",
     "../../gn:default_deps",
-    "../../protos/perfetto/ipc:wire_protocol",
+    "../../protos/perfetto/ipc:wire_protocol_cpp",
   ]
 }
 
@@ -65,7 +65,7 @@
     ":test_messages",
     "../../gn:default_deps",
     "../../gn:gtest_and_gmock",
-    "../../protos/perfetto/ipc:wire_protocol",
+    "../../protos/perfetto/ipc:wire_protocol_cpp",
     "../base",
     "../base:test_support",
   ]
diff --git a/src/ipc/buffered_frame_deserializer.cc b/src/ipc/buffered_frame_deserializer.cc
index dc107f7..9ef22eb 100644
--- a/src/ipc/buffered_frame_deserializer.cc
+++ b/src/ipc/buffered_frame_deserializer.cc
@@ -25,7 +25,7 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/ext/base/utils.h"
 
-#include "protos/perfetto/ipc/wire_protocol.pb.h"
+#include "protos/perfetto/ipc/wire_protocol.gen.h"
 
 namespace perfetto {
 namespace ipc {
@@ -166,23 +166,18 @@
   if (size == 0)
     return;
   std::unique_ptr<Frame> frame(new Frame);
-  if (frame->ParseFromArray(data, static_cast<int>(size)))
+  if (frame->ParseFromArray(data, size))
     decoded_frames_.push_back(std::move(frame));
 }
 
 // static
 std::string BufferedFrameDeserializer::Serialize(const Frame& frame) {
+  std::vector<uint8_t> payload = frame.SerializeAsArray();
+  const uint32_t payload_size = static_cast<uint32_t>(payload.size());
   std::string buf;
-  buf.reserve(1024);  // Just an educated guess to avoid trivial expansions.
-  buf.insert(0, kHeaderSize, 0);  // Reserve the space for the header.
-  frame.AppendToString(&buf);
-  const uint32_t payload_size = static_cast<uint32_t>(buf.size() - kHeaderSize);
-  PERFETTO_DCHECK(payload_size == static_cast<uint32_t>(frame.GetCachedSize()));
-  // Don't send messages larger than what the receiver can handle.
-  PERFETTO_DCHECK(kHeaderSize + payload_size <= kIPCBufferSize);
-  char header[kHeaderSize];
-  memcpy(header, base::AssumeLittleEndian(&payload_size), kHeaderSize);
-  buf.replace(0, kHeaderSize, header, kHeaderSize);
+  buf.resize(kHeaderSize + payload_size);
+  memcpy(&buf[0], base::AssumeLittleEndian(&payload_size), kHeaderSize);
+  memcpy(&buf[kHeaderSize], payload.data(), payload.size());
   return buf;
 }
 
diff --git a/src/ipc/buffered_frame_deserializer.h b/src/ipc/buffered_frame_deserializer.h
index 3aeee1f..92988e6 100644
--- a/src/ipc/buffered_frame_deserializer.h
+++ b/src/ipc/buffered_frame_deserializer.h
@@ -31,7 +31,7 @@
 namespace perfetto {
 namespace ipc {
 
-class Frame;  // Defined in the protobuf autogenerated wire_protocol.pb.h.
+class Frame;  // Defined in the protobuf autogenerated wire_protocol.gen.h.
 
 // Deserializes incoming frames, taking care of buffering and tokenization.
 // Used by both host and client to decode incoming frames.
diff --git a/src/ipc/buffered_frame_deserializer_unittest.cc b/src/ipc/buffered_frame_deserializer_unittest.cc
index 792365b..9ddf8d8 100644
--- a/src/ipc/buffered_frame_deserializer_unittest.cc
+++ b/src/ipc/buffered_frame_deserializer_unittest.cc
@@ -23,7 +23,7 @@
 #include "perfetto/ext/base/utils.h"
 #include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/ipc/wire_protocol.pb.h"
+#include "protos/perfetto/ipc/wire_protocol.gen.h"
 
 namespace perfetto {
 namespace ipc {
@@ -60,15 +60,16 @@
       padding_char = padding_char == 'z' ? '0' : padding_char + 1;
       padding[i] = padding_char;
     }
-    frame.add_data_for_testing(padding.data(), padding_size);
+    frame.add_data_for_testing(std::string(padding.data(), padding_size));
   }
-  PERFETTO_CHECK(frame.ByteSize() == static_cast<int>(payload_size));
+  PERFETTO_CHECK(frame.SerializeAsString().size() == payload_size);
   std::vector<char> encoded_frame;
   encoded_frame.resize(size);
   char* enc_buf = encoded_frame.data();
-  PERFETTO_CHECK(frame.SerializeToArray(enc_buf + kHeaderSize,
-                                        static_cast<int>(payload_size)));
+
+  std::string payload = frame.SerializeAsString();
   memcpy(enc_buf, base::AssumeLittleEndian(&payload_size), kHeaderSize);
+  memcpy(enc_buf + kHeaderSize, payload.data(), payload.size());
   PERFETTO_CHECK(encoded_frame.size() == size);
   return encoded_frame;
 }
@@ -108,8 +109,7 @@
     // Excactly one frame should be decoded, with no leftover buffer.
     auto decoded_frame = bfd.PopNextFrame();
     ASSERT_TRUE(decoded_frame);
-    ASSERT_EQ(static_cast<int32_t>(size - kHeaderSize),
-              decoded_frame->ByteSize());
+    ASSERT_EQ(size - kHeaderSize, decoded_frame->SerializeAsString().size());
     ASSERT_FALSE(bfd.PopNextFrame());
     ASSERT_EQ(0u, bfd.size());
   }
@@ -132,11 +132,11 @@
   method->set_id(0x424242);
   method->set_name("foo");
   std::vector<char> serialized_frame;
-  uint32_t payload_size = static_cast<uint32_t>(frame.ByteSize());
 
+  std::string payload = frame.SerializeAsString();
+  uint32_t payload_size = static_cast<uint32_t>(payload.size());
   serialized_frame.resize(kHeaderSize + payload_size);
-  ASSERT_TRUE(frame.SerializeToArray(serialized_frame.data() + kHeaderSize,
-                                     static_cast<int>(payload_size)));
+  memcpy(serialized_frame.data() + kHeaderSize, payload.data(), payload_size);
   memcpy(serialized_frame.data(), base::AssumeLittleEndian(&payload_size),
          kHeaderSize);
 
@@ -163,8 +163,8 @@
   // Validate the received frame2.
   std::unique_ptr<Frame> decoded_simple_frame = bfd.PopNextFrame();
   ASSERT_TRUE(decoded_simple_frame);
-  ASSERT_EQ(static_cast<int32_t>(simple_frame.size() - kHeaderSize),
-            decoded_simple_frame->ByteSize());
+  ASSERT_EQ(simple_frame.size() - kHeaderSize,
+            decoded_simple_frame->SerializeAsString().size());
 
   std::unique_ptr<Frame> decoded_frame = bfd.PopNextFrame();
   ASSERT_TRUE(decoded_frame);
@@ -238,8 +238,7 @@
     for (size_t expected_size : batch) {
       auto frame = bfd.PopNextFrame();
       ASSERT_TRUE(frame);
-      ASSERT_EQ(static_cast<int32_t>(expected_size - kHeaderSize),
-                frame->ByteSize());
+      ASSERT_EQ(expected_size - kHeaderSize, frame->SerializeAsString().size());
     }
     ASSERT_FALSE(bfd.PopNextFrame());
     ASSERT_EQ(0u, bfd.size());
@@ -301,8 +300,7 @@
       ASSERT_FALSE(decoded_frame);
     } else {
       ASSERT_TRUE(decoded_frame);
-      ASSERT_EQ(static_cast<int32_t>(size - kHeaderSize),
-                decoded_frame->ByteSize());
+      ASSERT_EQ(size - kHeaderSize, decoded_frame->SerializeAsString().size());
     }
     ASSERT_EQ(0u, bfd.size());
   }
diff --git a/src/ipc/client_impl.h b/src/ipc/client_impl.h
index 71c211f..35dea50 100644
--- a/src/ipc/client_impl.h
+++ b/src/ipc/client_impl.h
@@ -23,7 +23,7 @@
 #include "perfetto/ext/ipc/client.h"
 #include "src/ipc/buffered_frame_deserializer.h"
 
-#include "protos/perfetto/ipc/wire_protocol.pb.h"
+#include "protos/perfetto/ipc/wire_protocol.gen.h"
 
 #include <list>
 #include <map>
diff --git a/src/ipc/host_impl.cc b/src/ipc/host_impl.cc
index 1158fb8..7784305 100644
--- a/src/ipc/host_impl.cc
+++ b/src/ipc/host_impl.cc
@@ -26,7 +26,7 @@
 #include "perfetto/ext/ipc/service.h"
 #include "perfetto/ext/ipc/service_descriptor.h"
 
-#include "protos/perfetto/ipc/wire_protocol.pb.h"
+#include "protos/perfetto/ipc/wire_protocol.gen.h"
 
 // TODO(primiano): put limits on #connections/uid and req. queue (b/69093705).
 
diff --git a/src/ipc/host_impl_unittest.cc b/src/ipc/host_impl_unittest.cc
index 4e9216b..61a77dd 100644
--- a/src/ipc/host_impl_unittest.cc
+++ b/src/ipc/host_impl_unittest.cc
@@ -30,7 +30,7 @@
 #include "src/ipc/test/test_socket.h"
 #include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/ipc/wire_protocol.pb.h"
+#include "protos/perfetto/ipc/wire_protocol.gen.h"
 #include "src/ipc/test/client_unittest_messages.pb.h"
 
 namespace perfetto {
diff --git a/src/profiling/memory/CHANGELOG.md b/src/profiling/memory/CHANGELOG.md
index 56f64b5..31a35bb 100644
--- a/src/profiling/memory/CHANGELOG.md
+++ b/src/profiling/memory/CHANGELOG.md
@@ -10,3 +10,4 @@
 
 ## Bugfixes
 * Fixed heapprofd on x86.
+* Fixed issue with calloc being incorrectly sampled.
diff --git a/src/profiling/memory/malloc_hooks.cc b/src/profiling/memory/malloc_hooks.cc
index 7f6d1c3..c53f79f 100644
--- a/src/profiling/memory/malloc_hooks.cc
+++ b/src/profiling/memory/malloc_hooks.cc
@@ -477,7 +477,7 @@
 void* HEAPPROFD_ADD_PREFIX(_calloc)(size_t nmemb, size_t size) {
   const MallocDispatch* dispatch = GetDispatch();
   void* addr = dispatch->calloc(nmemb, size);
-  MaybeSampleAllocation(size, addr);
+  MaybeSampleAllocation(nmemb * size, addr);
   return addr;
 }
 
diff --git a/src/protozero/BUILD.gn b/src/protozero/BUILD.gn
index b2cc13a..23469d8 100644
--- a/src/protozero/BUILD.gn
+++ b/src/protozero/BUILD.gn
@@ -28,6 +28,7 @@
     "../../include/perfetto/ext/base",  # TODO(primiano): remove this
   ]
   sources = [
+    "field.cc",
     "message.cc",
     "message_handle.cc",
     "packed_repeated_fields.cc",
@@ -35,6 +36,7 @@
     "scattered_heap_buffer.cc",
     "scattered_stream_null_delegate.cc",
     "scattered_stream_writer.cc",
+    "static_buffer.cc",
   ]
 }
 
@@ -49,6 +51,7 @@
   testonly = true
   deps = [
     ":protozero",
+    ":testing_messages_cpp",
     ":testing_messages_lite",
     ":testing_messages_zero",
     "../../gn:default_deps",
@@ -63,6 +66,7 @@
     "proto_decoder_unittest.cc",
     "proto_utils_unittest.cc",
     "scattered_stream_writer_unittest.cc",
+    "test/cppgen_conformance_unittest.cc",
     "test/fake_scattered_buffer.cc",
     "test/fake_scattered_buffer.h",
     "test/protozero_conformance_unittest.cc",
@@ -72,10 +76,6 @@
 # Generates both xxx.pbzero.h and xxx.pb.h (official proto).
 
 perfetto_proto_library("testing_messages_@TYPE@") {
-  proto_generators = [
-    "lite",
-    "zero",
-  ]
   sources = [
     "test/example_proto/library.proto",
     "test/example_proto/library_internals/galaxies.proto",
diff --git a/src/protozero/field.cc b/src/protozero/field.cc
new file mode 100644
index 0000000..c92f7ce
--- /dev/null
+++ b/src/protozero/field.cc
@@ -0,0 +1,71 @@
+/*
+ * 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/protozero/field.h"
+
+#include "perfetto/base/logging.h"
+
+#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
+// The memcpy() for fixed32/64 below needs to be adjusted if we want to
+// support big endian CPUs. There doesn't seem to be a compelling need today.
+#error Unimplemented for big endian archs.
+#endif
+
+namespace protozero {
+
+void Field::SerializeAndAppendTo(std::string* dst) {
+  namespace pu = proto_utils;
+  size_t initial_size = dst->size();
+  dst->resize(initial_size + pu::kMaxSimpleFieldEncodedSize + size_);
+  uint8_t* start = reinterpret_cast<uint8_t*>(&(*dst)[initial_size]);
+  uint8_t* wptr = start;
+  switch (type_) {
+    case static_cast<int>(pu::ProtoWireType::kVarInt): {
+      wptr = pu::WriteVarInt(pu::MakeTagVarInt(id_), wptr);
+      wptr = pu::WriteVarInt(int_value_, wptr);
+      break;
+    }
+    case static_cast<int>(pu::ProtoWireType::kFixed32): {
+      wptr = pu::WriteVarInt(pu::MakeTagFixed<uint32_t>(id_), wptr);
+      uint32_t value32 = static_cast<uint32_t>(int_value_);
+      memcpy(wptr, &value32, sizeof(value32));
+      wptr += sizeof(uint32_t);
+      break;
+    }
+    case static_cast<int>(pu::ProtoWireType::kFixed64): {
+      wptr = pu::WriteVarInt(pu::MakeTagFixed<uint64_t>(id_), wptr);
+      memcpy(wptr, &int_value_, sizeof(int_value_));
+      wptr += sizeof(uint64_t);
+      break;
+    }
+    case static_cast<int>(pu::ProtoWireType::kLengthDelimited): {
+      ConstBytes payload = as_bytes();
+      wptr = pu::WriteVarInt(pu::MakeTagLengthDelimited(id_), wptr);
+      wptr = pu::WriteVarInt(payload.size, wptr);
+      memcpy(wptr, payload.data, payload.size);
+      wptr += payload.size;
+      break;
+    }
+    default:
+      PERFETTO_FATAL("Unknown field type %u", type_);
+  }
+  size_t written_size = static_cast<size_t>(wptr - start);
+  PERFETTO_DCHECK(written_size > 0 && written_size < pu::kMaxMessageLength);
+  PERFETTO_DCHECK(initial_size + written_size <= dst->size());
+  dst->resize(initial_size + written_size);
+}
+
+}  // namespace protozero
diff --git a/src/protozero/proto_decoder.cc b/src/protozero/proto_decoder.cc
index a5f1b95..9bf9ca5 100644
--- a/src/protozero/proto_decoder.cc
+++ b/src/protozero/proto_decoder.cc
@@ -60,7 +60,10 @@
   if (PERFETTO_LIKELY(*pos < 0x80)) {  // Fastpath for fields with ID < 16.
     preamble = *(pos++);
   } else {
-    pos = ParseVarInt(pos, end, &preamble);
+    const uint8_t* next = ParseVarInt(pos, end, &preamble);
+    if (PERFETTO_UNLIKELY(pos == next))
+      return res;
+    pos = next;
   }
 
   uint32_t field_id = static_cast<uint32_t>(preamble >> kFieldTypeNumBits);
diff --git a/src/protozero/proto_utils_unittest.cc b/src/protozero/proto_utils_unittest.cc
index a724189..9124490 100644
--- a/src/protozero/proto_utils_unittest.cc
+++ b/src/protozero/proto_utils_unittest.cc
@@ -194,6 +194,8 @@
   }
 }
 
+// ParseVarInt() must fail gracefully if we hit the |end| without seeing the
+// MSB == 0 (i.e. end-of-sequence).
 TEST(ProtoUtilsTest, VarIntDecodingOutOfBounds) {
   uint8_t buf[] = {0xff, 0xff, 0xff, 0xff};
   for (size_t i = 0; i < 5; i++) {
@@ -204,6 +206,27 @@
   }
 }
 
+// Even if we see a valid end-of-sequence, ParseVarInt() must fail if the number
+// is larger than 10 bytes. That would cause subtl bugs when trying to shift
+// left by more than 64 bits.
+TEST(ProtoUtilsTest, RejectVarIntTooBig) {
+  // This is the biggest valid varint we support (2**64 - 1).
+  uint8_t good[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01};
+
+  // Parsing this value must succeed.
+  uint64_t value = static_cast<uint64_t>(-1);
+  const uint8_t* res = ParseVarInt(&good[0], &good[sizeof(good)], &value);
+  EXPECT_EQ(&good[sizeof(good)], res);
+  EXPECT_EQ(value, static_cast<uint64_t>(-1ULL));
+
+  uint8_t bad[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                   0xff, 0xff, 0xff, 0xff, 0x01};
+  value = static_cast<uint64_t>(-1);
+  res = ParseVarInt(&bad[0], &bad[sizeof(bad)], &value);
+  EXPECT_EQ(&bad[0], res);
+  EXPECT_EQ(0u, value);
+}
+
 }  // namespace
 }  // namespace proto_utils
 }  // namespace protozero
diff --git a/src/protozero/protoc_plugin/cppgen_plugin.cc b/src/protozero/protoc_plugin/cppgen_plugin.cc
index bbd2b23..51fb707 100644
--- a/src/protozero/protoc_plugin/cppgen_plugin.cc
+++ b/src/protozero/protoc_plugin/cppgen_plugin.cc
@@ -19,6 +19,7 @@
 
 #include <fstream>
 #include <iostream>
+#include <map>
 #include <set>
 #include <stack>
 #include <vector>
@@ -46,16 +47,26 @@
 using perfetto::base::ToUpper;
 
 static constexpr auto TYPE_MESSAGE = FieldDescriptor::TYPE_MESSAGE;
+static constexpr auto TYPE_ENUM = FieldDescriptor::TYPE_ENUM;
+static constexpr auto TYPE_SINT32 = FieldDescriptor::TYPE_SINT32;
+static constexpr auto TYPE_SINT64 = FieldDescriptor::TYPE_SINT64;
 
 static const char kHeader[] =
     "// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin\n";
 
-std::string GetProtoHeader(const FileDescriptor* file) {
-  return StripSuffix(file->name(), ".proto") + ".pb.h";
+// TODO(primiano): this is temporary to avoid clashes between libprotobuf
+// and protozero-cpp classes. Effectively this causes messages like
+// perfetto.protos.DataSourceDescriptor to be generated as
+// perfetto::DataSourceDescriptor. Once libprotobuf is gone we'll be able to
+// move this back into the protos namespace.
+std::string StripPackage(const std::string& pkg) {
+  return StripSuffix(pkg, ".protos");
 }
 
 template <typename T = Descriptor>
-std::string GetFullName(const T* msg, bool with_namespace = false) {
+std::string GetFullName(const T* msg,
+                        bool with_namespace = false,
+                        const std::string& extra_namespace = "") {
   std::string full_type;
   full_type.append(msg->name());
   for (const Descriptor* par = msg->containing_type(); par;
@@ -63,8 +74,9 @@
     full_type.insert(0, par->name() + "_");
   }
   if (with_namespace) {
-    std::vector<std::string> namespaces =
-        SplitString(msg->file()->package(), ".");
+    std::string pkg = msg->file()->package();
+    pkg = extra_namespace == "" ? StripPackage(pkg) : pkg;
+    auto namespaces = SplitString(pkg + extra_namespace, ".");
     for (auto it = namespaces.rbegin(); it != namespaces.rend(); it++) {
       full_type.insert(0, *it + "::");
     }
@@ -85,6 +97,9 @@
 
  private:
   std::string GetCppType(const FieldDescriptor* field, bool constref) const;
+  std::string GetPackedBuffer(const FieldDescriptor* field) const;
+  std::string GetPackedWireType(const FieldDescriptor* field) const;
+
   void GenEnum(const EnumDescriptor*, Printer*) const;
   void GenEnumAliases(const EnumDescriptor*, Printer*) const;
   void GenClassDecl(const Descriptor*, Printer*) const;
@@ -118,12 +133,14 @@
   h_printer.Print(kHeader);
   h_printer.Print("#ifndef $g$\n#define $g$\n\n", "g", include_guard);
   h_printer.Print("#include <stdint.h>\n");
+  h_printer.Print("#include <bitset>\n");
   h_printer.Print("#include <vector>\n");
   h_printer.Print("#include <string>\n");
   h_printer.Print("#include <type_traits>\n\n");
   h_printer.Print("#include \"perfetto/protozero/copyable_ptr.h\"\n");
   h_printer.Print("#include \"perfetto/base/export.h\"\n\n");
 
+  cc_printer.Print("#include \"perfetto/protozero/scattered_heap_buffer.h\"\n");
   cc_printer.Print(kHeader);
   cc_printer.Print("#pragma GCC diagnostic push\n");
   cc_printer.Print("#pragma GCC diagnostic ignored \"-Wfloat-equal\"\n");
@@ -148,8 +165,9 @@
     }
   }
 
-  // Include the .pb.h for the current file.
-  cc_printer.Print("\n#include \"$f$\"\n", "f", GetProtoHeader(file));
+  // Include the .pbzero.h for the current file.
+  std::string inc_base_name = StripSuffix(file->name(), ".proto");
+  cc_printer.Print("\n#include \"$f$.pbzero.h\"\n", "f", inc_base_name);
 
   // Recursively traverse all imports and turn them into #include(s).
   std::vector<const FileDescriptor*> imports_to_visit;
@@ -160,7 +178,9 @@
     const FileDescriptor* cur = imports_to_visit.back();
     imports_to_visit.pop_back();
     imports_visited.insert(cur);
-    cc_printer.Print("#include \"$f$.h\"\n", "f", get_file_name(cur));
+    std::string base_name = StripSuffix(cur->name(), ".proto");
+    cc_printer.Print("#include \"$f$.gen.h\"\n", "f", base_name);
+    cc_printer.Print("#include \"$f$.pbzero.h\"\n", "f", base_name);
     for (int i = 0; i < cur->dependency_count(); i++) {
       const FileDescriptor* dep = cur->dependency(i);
       if (imports_visited.count(dep) || lazy_imports.count(dep->name()))
@@ -233,27 +253,66 @@
   }  //  while (!recursion_stack.empty())
 
   // Generate forward declarations in the header for proto types.
-  h_printer.Print("// Forward declarations for protobuf types.\n");
-  std::vector<std::string> namespaces = SplitString(file->package(), ".");
-  for (size_t i = 0; i < namespaces.size(); i++)
-    h_printer.Print("namespace $n$ {\n", "n", namespaces[i]);
+  // Note: do NOT add #includes to other generated headers (either .gen.h or
+  // .pbzero.h). Doing so is extremely hard to handle at the build-system level
+  // and requires propagating public_deps everywhere.
+  cc_printer.Print("\n");
 
-  for (const Descriptor* msg : all_types)
-    h_printer.Print("class $n$;\n", "n", GetFullName(msg));
+  // -- Begin of fwd declarations.
 
-  for (size_t i = 0; i < namespaces.size(); i++)
-    h_printer.Print("}\n");
+  // Build up the map of forward declarations.
+  std::multimap<std::string /*namespace*/, std::string /*decl*/> fwd_decls;
+  enum FwdType { kClass, kEnum };
+  auto add_fwd_decl = [&fwd_decls](FwdType cpp_type,
+                                   const std::string& full_name) {
+    auto dot = full_name.rfind("::");
+    PERFETTO_CHECK(dot != std::string::npos);
+    auto package = full_name.substr(0, dot);
+    auto name = full_name.substr(dot + 2);
+    if (cpp_type == kClass) {
+      fwd_decls.emplace(package, "class " + name + ";");
+    } else {
+      PERFETTO_CHECK(cpp_type == kEnum);
+      fwd_decls.emplace(package, "enum " + name + " : int;");
+    }
+  };
 
-  h_printer.Print("\nnamespace perfetto {\n");
-  cc_printer.Print("\nnamespace perfetto {\n");
-
-  // Generate fwd declarations for C++ types.
+  for (const Descriptor* msg : all_types) {
+    add_fwd_decl(kClass, GetFullName(msg, true));
+    add_fwd_decl(kClass, GetFullName(msg, true, ".pbzero"));
+  }
   for (const EnumDescriptor* enm : all_enums) {
-    h_printer.Print("enum $n$ : int;\n", "n", GetFullName(enm));
+    add_fwd_decl(kEnum, GetFullName(enm, true));
   }
 
-  for (const Descriptor* msg : all_types)
-    h_printer.Print("class $n$;\n", "n", GetFullName(msg));
+  // Emit forward declarations grouping by package.
+  std::string last_package;
+  auto close_last_package = [&last_package, &h_printer] {
+    if (!last_package.empty()) {
+      for (const std::string& ns : SplitString(last_package, "::"))
+        h_printer.Print("}  // namespace $ns$\n", "ns", ns);
+      h_printer.Print("\n");
+    }
+  };
+  for (const auto& kv : fwd_decls) {
+    const std::string& package = kv.first;
+    if (package != last_package) {
+      close_last_package();
+      last_package = package;
+      for (const std::string& ns : SplitString(package, "::"))
+        h_printer.Print("namespace $ns$ {\n", "ns", ns);
+    }
+    h_printer.Print("$decl$\n", "decl", kv.second);
+  }
+  close_last_package();
+
+  // -- End of fwd declarations.
+
+  auto namespaces = SplitString(StripPackage(file->package()), ".");
+  for (size_t i = 0; i < namespaces.size(); i++) {
+    h_printer.Print("namespace $n$ {\n", "n", namespaces[i]);
+    cc_printer.Print("namespace $n$ {\n", "n", namespaces[i]);
+  }
 
   // Generate declarations and definitions.
   for (const EnumDescriptor* enm : local_enums)
@@ -264,10 +323,12 @@
     GenClassDef(msg, &cc_printer);
   }
 
-  cc_printer.Print("}  // namespace perfetto\n");
-  cc_printer.Print("#pragma GCC diagnostic pop\n");
+  for (size_t i = 0; i < namespaces.size(); i++) {
+    h_printer.Print("}  // namespace $n$\n", "n", namespaces[i]);
+    cc_printer.Print("}  // namespace $n$\n", "n", namespaces[i]);
+  }
 
-  h_printer.Print("}  // namespace perfetto\n");
+  cc_printer.Print("#pragma GCC diagnostic pop\n");
   h_printer.Print("\n#endif  // $g$\n", "g", include_guard);
 
   return true;
@@ -311,6 +372,68 @@
   abort();  // for gcc
 }
 
+std::string CppObjGenerator::GetPackedBuffer(
+    const FieldDescriptor* field) const {
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_FIXED32:
+      return "::protozero::PackedFixedSizeInt<uint32_t>";
+    case FieldDescriptor::TYPE_SFIXED32:
+      return "::protozero::PackedFixedSizeInt<int32_t>";
+    case FieldDescriptor::TYPE_FIXED64:
+      return "::protozero::PackedFixedSizeInt<uint64_t>";
+    case FieldDescriptor::TYPE_SFIXED64:
+      return "::protozero::PackedFixedSizeInt<int64_t>";
+    case FieldDescriptor::TYPE_DOUBLE:
+      return "::protozero::PackedFixedSizeInt<double>";
+    case FieldDescriptor::TYPE_FLOAT:
+      return "::protozero::PackedFixedSizeInt<float>";
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_BOOL:
+      return "::protozero::PackedVarInt";
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES:
+    case FieldDescriptor::TYPE_MESSAGE:
+    case FieldDescriptor::TYPE_ENUM:
+    case FieldDescriptor::TYPE_GROUP:
+      break;  // Will abort()
+  }
+  abort();
+}
+
+std::string CppObjGenerator::GetPackedWireType(
+    const FieldDescriptor* field) const {
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_FLOAT:
+      return "::protozero::proto_utils::ProtoWireType::kFixed32";
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_SFIXED64:
+    case FieldDescriptor::TYPE_DOUBLE:
+      return "::protozero::proto_utils::ProtoWireType::kFixed64";
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_BOOL:
+      return "::protozero::proto_utils::ProtoWireType::kVarInt";
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES:
+    case FieldDescriptor::TYPE_MESSAGE:
+    case FieldDescriptor::TYPE_ENUM:
+    case FieldDescriptor::TYPE_GROUP:
+      break;  // Will abort()
+  }
+  abort();
+}
+
 void CppObjGenerator::GenEnum(const EnumDescriptor* enum_desc,
                               Printer* p) const {
   std::string full_name = GetFullName(enum_desc);
@@ -368,6 +491,17 @@
     GenEnumAliases(nested_enum, p);
   }
 
+  // Generate constants with field numbers.
+  p->Print("enum FieldNumbers {\n");
+  for (int i = 0; i < msg->field_count(); i++) {
+    const FieldDescriptor* field = msg->field(i);
+    std::string name = field->camelcase_name();
+    name[0] = perfetto::base::Uppercase(name[0]);
+    p->Print("  k$n$FieldNumber = $num$,\n", "n", name, "num",
+             std::to_string(field->number()));
+  }
+  p->Print("};\n\n");
+
   p->Print("$n$();\n", "n", full_name);
   p->Print("~$n$();\n", "n", full_name);
   p->Print("$n$($n$&&) noexcept;\n", "n", full_name);
@@ -382,36 +516,58 @@
 
   std::string proto_type = GetFullName(msg, true);
   p->Print("// Raw proto decoding.\n");
-  p->Print("void ParseRawProto(const std::string&);\n");
-  p->Print("// Conversion methods from/to the corresponding protobuf types.\n");
-  p->Print("void FromProto(const $p$&);\n", "p", proto_type);
-  p->Print("void ToProto($p$*) const;\n", "p", proto_type);
+  p->Print("bool ParseFromArray(const void*, size_t);\n");
+  p->Print("bool ParseRawProto(const std::string& str) {\n");
+  p->Print("  return ParseFromArray(str.data(), str.size());\n");
+  p->Print("}\n");
+
+  p->Print("std::string SerializeAsString() const;\n");
+  p->Print("std::vector<uint8_t> SerializeAsArray() const;\n");
+  p->Print("void Serialize($p$*) const;\n", "p",
+           GetFullName(msg, true, ".pbzero"));
+
+  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) { "
+      "ParseRawProto(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);
+    auto set_bit = "_has_field_.set(" + std::to_string(field->number()) + ")";
     p->Print("\n");
     if (field->options().lazy()) {
       p->Print("const std::string& $n$_raw() const { return $n$_; }\n", "n",
                field->lowercase_name());
-      p->Print("void set_$n$_raw(const std::string& raw) { $n$_ = raw; }\n",
-               "n", field->lowercase_name());
+      p->Print(
+          "void set_$n$_raw(const std::string& raw) { $n$_ = raw; $s$; }\n",
+          "n", field->lowercase_name(), "s", set_bit);
     } else if (!field->is_repeated()) {
+      p->Print("bool has_$n$() const { return _has_field_[$bit$]; }\n", "n",
+               field->lowercase_name(), "bit", std::to_string(field->number()));
       if (field->type() == TYPE_MESSAGE) {
         p->Print("$t$ $n$() const { return *$n$_; }\n", "t",
                  GetCppType(field, true), "n", field->lowercase_name());
-        p->Print("$t$* mutable_$n$() { return $n$_.get(); }\n", "t",
-                 GetCppType(field, false), "n", field->lowercase_name());
+        p->Print("$t$* mutable_$n$() { $s$; return $n$_.get(); }\n", "t",
+                 GetCppType(field, false), "n", field->lowercase_name(), "s",
+                 set_bit);
       } else {
         p->Print("$t$ $n$() const { return $n$_; }\n", "t",
                  GetCppType(field, true), "n", field->lowercase_name());
-        p->Print("void set_$n$($t$ value) { $n$_ = value; }\n", "t",
-                 GetCppType(field, true), "n", field->lowercase_name());
+        p->Print("void set_$n$($t$ value) { $n$_ = value; $s$; }\n", "t",
+                 GetCppType(field, true), "n", field->lowercase_name(), "s",
+                 set_bit);
         if (field->type() == FieldDescriptor::TYPE_BYTES) {
           p->Print(
               "void set_$n$(const void* p, size_t s) { "
-              "$n$_.assign(reinterpret_cast<const char*>(p), s); }\n",
-              "n", field->lowercase_name());
+              "$n$_.assign(reinterpret_cast<const char*>(p), s); $s$; }\n",
+              "n", field->lowercase_name(), "s", set_bit);
         }
       }
     } else {  // is_repeated()
@@ -424,6 +580,13 @@
                GetCppType(field, false), "n", field->lowercase_name());
       p->Print("void clear_$n$() { $n$_.clear(); }\n", "n",
                field->lowercase_name());
+      if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
+        p->Print("void add_$n$($t$ value) { $n$_.emplace_back(value); }\n", "t",
+                 GetCppType(field, false), "n", field->lowercase_name());
+      }
+      // TODO(primiano): this should be done only for TYPE_MESSAGE. Unfortuntely
+      // we didn't realize before and now we have a bunch of code that does:
+      // *msg->add_int_value() = 42 instead of msg->add_int_value(42).
       p->Print("$t$* add_$n$() { $n$_.emplace_back(); return &$n$_.back(); }\n",
                "t", GetCppType(field, false), "n", field->lowercase_name());
     }
@@ -433,8 +596,10 @@
   p->Indent();
 
   // Generate fields.
+  int max_field_id = 1;
   for (int i = 0; i < msg->field_count(); i++) {
     const FieldDescriptor* field = msg->field(i);
+    max_field_id = std::max(max_field_id, field->number());
     if (field->options().lazy()) {
       p->Print("std::string $n$_;  // [lazy=true]\n", "n",
                field->lowercase_name());
@@ -455,6 +620,10 @@
   p->Print("// Allows to preserve unknown protobuf fields for compatibility\n");
   p->Print("// with future versions of .proto files.\n");
   p->Print("std::string unknown_fields_;\n");
+
+  p->Print("\nstd::bitset<$id$> _has_field_{};\n", "id",
+           std::to_string(max_field_id + 1));
+
   p->Outdent();
   p->Print("};\n\n");
 }
@@ -485,104 +654,156 @@
 
   std::string proto_type = GetFullName(msg, true);
 
-  // Genrate the ParseRawProto() method definition.
-  p->Print("void $f$::ParseRawProto(const std::string& raw) {\n", "f",
+  // Generate the ParseRawProto() method definition.
+  p->Print("bool $f$::ParseFromArray(const void* raw, size_t size) {\n", "f",
            full_name);
   p->Indent();
-  p->Print("$p$ proto;\n", "p", proto_type);
-  p->Print("proto.ParseFromString(raw);\n");
-  p->Print("FromProto(proto);\n");
-  p->Outdent();
-  p->Print("}\n\n");
-
-  // Genrate the FromProto() method definition.
-  p->Print("void $f$::FromProto(const $p$& proto) {\n", "f", full_name, "p",
-           proto_type);
-  p->Indent();
   for (int i = 0; i < msg->field_count(); i++) {
-    p->Print("\n");
     const FieldDescriptor* field = msg->field(i);
-    if (field->options().lazy()) {
-      p->Print("$n$_ = proto.$n$().SerializeAsString();\n", "n",
-               field->lowercase_name());
-    } else if (!field->is_repeated()) {
-      if (field->type() == TYPE_MESSAGE) {
-        p->Print("$n$_->FromProto(proto.$n$());\n", "n",
-                 field->lowercase_name());
-      } else {
-        p->Print(
-            "static_assert(sizeof($n$_) == sizeof(proto.$n$()), \"size "
-            "mismatch\");\n",
-            "n", field->lowercase_name());
-        p->Print("$n$_ = static_cast<decltype($n$_)>(proto.$n$());\n", "n",
-                 field->lowercase_name());
-      }
-    } else {  // is_repeated()
+    if (field->is_repeated())
       p->Print("$n$_.clear();\n", "n", field->lowercase_name());
-      p->Print("for (const auto& field : proto.$n$()) {\n", "n",
-               field->lowercase_name());
-      p->Print("  $n$_.emplace_back();\n", "n", field->lowercase_name());
-      if (field->type() == TYPE_MESSAGE) {
-        p->Print("  $n$_.back().FromProto(field);\n", "n",
-                 field->lowercase_name());
-      } else {
-        p->Print(
-            "static_assert(sizeof($n$_.back()) == sizeof(proto.$n$(0)), \"size "
-            "mismatch\");\n",
-            "n", field->lowercase_name());
-        p->Print(
-            "  $n$_.back() = static_cast<decltype($n$_)::value_type>(field);\n",
-            "n", field->lowercase_name());
-      }
-      p->Print("}\n");
-    }
   }
-  p->Print("unknown_fields_ = proto.unknown_fields();\n");
+  p->Print("unknown_fields_.clear();\n");
+  p->Print("bool packed_error = false;\n");
+  p->Print("\n");
+  p->Print("::protozero::ProtoDecoder dec(raw, size);\n");
+  p->Print("for (auto field = dec.ReadField(); field.valid(); ");
+  p->Print("field = dec.ReadField()) {\n");
+  p->Indent();
+  p->Print("if (field.id() < _has_field_.size()) {\n");
+  p->Print("  _has_field_.set(field.id());\n");
+  p->Print("}\n");
+  p->Print("switch (field.id()) {\n");
+  p->Indent();
+  for (int i = 0; i < msg->field_count(); i++) {
+    const FieldDescriptor* field = msg->field(i);
+    p->Print("case $id$ /* $n$ */:\n", "id", std::to_string(field->number()),
+             "n", field->lowercase_name());
+    p->Indent();
+    if (field->options().lazy()) {
+      p->Print("$n$_ = field.as_std_string();\n", "n", field->lowercase_name());
+    } else {
+      std::string statement;
+      if (field->type() == TYPE_MESSAGE) {
+        statement = "$rval$.ParseRawProto(field.as_std_string());\n";
+      } else {
+        if (field->type() == TYPE_SINT32 || field->type() == TYPE_SINT64) {
+          // sint32/64 fields are special and need to be zig-zag-decoded.
+          statement = "field.get_signed(&$rval$);\n";
+        } else {
+          statement = "field.get(&$rval$);\n";
+        }
+      }
+      if (field->is_packed()) {
+        PERFETTO_CHECK(field->is_repeated());
+        if (field->type() == TYPE_SINT32 || field->type() == TYPE_SINT64) {
+          PERFETTO_FATAL("packed signed (zigzag) fields are not supported");
+        }
+        p->Print(
+            "for (::protozero::PackedRepeatedFieldIterator<$w$, $c$> "
+            "rep(field.data(), field.size(), &packed_error); rep; ++rep) {\n",
+            "w", GetPackedWireType(field), "c", GetCppType(field, false));
+        p->Print("  $n$_.emplace_back(*rep);\n", "n", field->lowercase_name());
+        p->Print("}\n");
+      } else if (field->is_repeated()) {
+        p->Print("$n$_.emplace_back();\n", "n", field->lowercase_name());
+        p->Print(statement.c_str(), "rval",
+                 field->lowercase_name() + "_.back()");
+      } else if (field->type() == TYPE_MESSAGE) {
+        p->Print(statement.c_str(), "rval",
+                 "(*" + field->lowercase_name() + "_)");
+      } else {
+        p->Print(statement.c_str(), "rval", field->lowercase_name() + "_");
+      }
+    }
+    p->Print("break;\n");
+    p->Outdent();
+  }  // for (field)
+  p->Print("default:\n");
+  p->Print("  field.SerializeAndAppendTo(&unknown_fields_);\n");
+  p->Print("  break;\n");
+  p->Outdent();
+  p->Print("}\n");  // switch(field.id)
+  p->Outdent();
+  p->Print("}\n");                                           // for(field)
+  p->Print("return !packed_error && !dec.bytes_left();\n");  // for(field)
   p->Outdent();
   p->Print("}\n\n");
 
-  // Genrate the ToProto() method definition.
-  p->Print("void $f$::ToProto($p$* proto) const {\n", "f", full_name, "p",
-           proto_type);
+  // Generate the SerializeAsString() method definition.
+  p->Print("std::string $f$::SerializeAsString() const {\n", "f", full_name);
   p->Indent();
-  p->Print("proto->Clear();\n");
+  p->Print("::protozero::HeapBuffered<$p$> msg;\n", "p",
+           GetFullName(msg, true, ".pbzero"));
+  p->Print("Serialize(msg.get());\n");
+  p->Print("return msg.SerializeAsString();\n");
+  p->Outdent();
+  p->Print("}\n\n");
+
+  // Generate the SerializeAsArray() method definition.
+  p->Print("std::vector<uint8_t> $f$::SerializeAsArray() const {\n", "f",
+           full_name);
+  p->Indent();
+  p->Print("::protozero::HeapBuffered<$p$> msg;\n", "p",
+           GetFullName(msg, true, ".pbzero"));
+  p->Print("Serialize(msg.get());\n");
+  p->Print("return msg.SerializeAsArray();\n");
+  p->Outdent();
+  p->Print("}\n\n");
+
+  // Generaate the Serialize() method that writes the fields into the passed
+  // protozero |msg| write-only interface |msg|.
+  p->Print("void $f$::Serialize($p$* msg) const {\n", "f", full_name, "p",
+           GetFullName(msg, true, ".pbzero"));
+  p->Indent();
   for (int i = 0; i < msg->field_count(); i++) {
-    p->Print("\n");
     const FieldDescriptor* field = msg->field(i);
+    std::string fld_name = field->lowercase_name();
     if (field->options().lazy()) {
-      p->Print("proto->mutable_$n$()->ParseFromString($n$_);\n", "n",
-               field->lowercase_name());
-    } else if (!field->is_repeated()) {
-      if (field->type() == TYPE_MESSAGE) {
-        p->Print("$n$_->ToProto(proto->mutable_$n$());\n", "n",
-                 field->lowercase_name());
-      } else {
-        p->Print(
-            "static_assert(sizeof($n$_) == sizeof(proto->$n$()), \"size "
-            "mismatch\");\n",
-            "n", field->lowercase_name());
-        p->Print("proto->set_$n$(static_cast<decltype(proto->$n$())>($n$_));\n",
-                 "n", field->lowercase_name());
+      p->Print("msg->set_$n$_raw($n$_);\n", "n", fld_name);
+    } else {
+      std::string enum_type;
+      if (field->type() == TYPE_ENUM)
+        enum_type = GetFullName(field->enum_type(), true, ".pbzero");
+      if (field->is_packed()) {
+        PERFETTO_CHECK(field->is_repeated());
+        p->Print("{\n");
+        p->Indent();
+        p->Print("$p$ pack;\n", "p", GetPackedBuffer(field));
+        p->Print("for (auto& it : $n$_)\n", "n", fld_name);
+        p->Print("  pack.Append(it);\n");
+        p->Print("msg->set_$n$(pack);\n", "n", fld_name);
+        p->Outdent();
+        p->Print("}\n");
+      } else if (field->is_repeated()) {
+        p->Print("for (auto& it : $n$_) {\n", "n", fld_name);
+        if (field->type() == TYPE_MESSAGE) {
+          p->Print("  it.Serialize(msg->add_$n$());\n", "n", fld_name);
+        } else if (field->type() == TYPE_ENUM) {
+          p->Print("  msg->add_$n$(static_cast<::$e$>(it));\n", "n", fld_name,
+                   "e", enum_type);
+        } else {
+          p->Print("  msg->add_$n$(it);\n", "n", fld_name);
+        }
+        p->Print("}\n");
+      } else {  // repeated = false
+        p->Print("if (_has_field_[$id$]) { ", "id",
+                 std::to_string(field->number()));
+        if (field->type() == TYPE_MESSAGE) {
+          p->Print("$n$_->Serialize(msg->set_$n$());", "n", fld_name);
+        } else if (field->type() == TYPE_ENUM) {
+          p->Print("msg->set_$n$(static_cast<::$e$>($n$_));", "n", fld_name,
+                   "e", enum_type);
+        } else {
+          p->Print("msg->set_$n$($n$_);", "n", fld_name);
+        }
+        p->Print(" }\n");
       }
-    } else {  // is_repeated()
-      p->Print("for (const auto& it : $n$_) {\n", "n", field->lowercase_name());
-      if (field->type() == TYPE_MESSAGE) {
-        p->Print("  auto* entry = proto->add_$n$();\n", "n",
-                 field->lowercase_name());
-        p->Print("  it.ToProto(entry);\n");
-      } else {
-        p->Print(
-            "  proto->add_$n$(static_cast<decltype(proto->$n$(0))>(it));\n",
-            "n", field->lowercase_name());
-        p->Print(
-            "static_assert(sizeof(it) == sizeof(proto->$n$(0)), \"size "
-            "mismatch\");\n",
-            "n", field->lowercase_name());
-      }
-      p->Print("}\n");
     }
-  }
-  p->Print("*(proto->mutable_unknown_fields()) = unknown_fields_;\n");
+  }  // for (field)
+  p->Print(
+      "msg->AppendRawProtoBytes(unknown_fields_.data(), "
+      "unknown_fields_.size());\n");
   p->Outdent();
   p->Print("}\n\n");
 }
diff --git a/src/protozero/static_buffer.cc b/src/protozero/static_buffer.cc
new file mode 100644
index 0000000..cb4737b
--- /dev/null
+++ b/src/protozero/static_buffer.cc
@@ -0,0 +1,35 @@
+/*
+ * 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/protozero/static_buffer.h"
+
+#include "perfetto/base/logging.h"
+
+namespace protozero {
+
+StaticBufferDelegate::~StaticBufferDelegate() = default;
+
+ContiguousMemoryRange StaticBufferDelegate::GetNewBuffer() {
+  if (get_new_buffer_called_once_) {
+    // This is the 2nd time GetNewBuffer is called. The estimate is wrong. We
+    // shouldn't try to grow the buffer after the initial call.
+    PERFETTO_FATAL("Static buffer too small");
+  }
+  get_new_buffer_called_once_ = true;
+  return range_;
+}
+
+}  // namespace protozero
diff --git a/src/protozero/test/cppgen_conformance_unittest.cc b/src/protozero/test/cppgen_conformance_unittest.cc
new file mode 100644
index 0000000..040b507
--- /dev/null
+++ b/src/protozero/test/cppgen_conformance_unittest.cc
@@ -0,0 +1,342 @@
+/*
+ * 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 <limits>
+#include <memory>
+#include <vector>
+
+#include "perfetto/protozero/message_handle.h"
+#include "perfetto/protozero/packed_repeated_fields.h"
+#include "test/gtest_and_gmock.h"
+
+// Autogenerated headers in out/*/gen/
+#include "src/protozero/test/example_proto/library.gen.h"
+#include "src/protozero/test/example_proto/test_messages.gen.h"
+#include "src/protozero/test/example_proto/test_messages.pb.h"
+
+// Generated by the cppgen compiler.
+namespace pbtest = protozero::test;
+
+// Generated by the official protobuf compiler.
+namespace pbgold = protozero::test::protos;
+
+namespace protozero {
+namespace {
+
+using testing::ElementsAreArray;
+
+// The two functions below are templated because they are re-used both on the
+// libprotobuf and protozero versions to check both libproto -> zero and
+// zero -> libproto compatibility.
+template <typename T>
+void SetTestingFields(T* msg) {
+  msg->set_field_int32(-1);
+  msg->set_field_int64(-333123456789ll);
+  msg->set_field_uint32(600);
+  msg->set_field_uint64(333123456789ll);
+  msg->set_field_sint32(-5);
+  msg->set_field_sint64(-9000);
+  msg->set_field_fixed32(12345);
+  msg->set_field_fixed64(444123450000ll);
+  msg->set_field_sfixed32(-69999);
+  msg->set_field_sfixed64(-200);
+  msg->set_field_float(3.14f);
+  msg->set_field_double(0.5555);
+  msg->set_field_bool(true);
+
+  msg->set_small_enum(decltype(msg->small_enum())::TO_BE);
+  msg->set_signed_enum(decltype(msg->signed_enum())::NEGATIVE);
+  msg->set_big_enum(decltype(msg->big_enum())::BEGIN);
+
+  msg->set_field_string("FizzBuzz");
+  msg->set_field_bytes(reinterpret_cast<const uint8_t*>("\x11\x00\xBE\xEF"), 4);
+  msg->add_repeated_int32(1);
+  msg->add_repeated_int32(-1);
+  msg->add_repeated_int32(100);
+  msg->add_repeated_int32(2000000);
+}
+
+template <typename T>
+void CheckTestingFields(const T& msg) {
+  EXPECT_EQ(-1, msg.field_int32());
+  EXPECT_EQ(-333123456789ll, msg.field_int64());
+  EXPECT_EQ(600u, msg.field_uint32());
+  EXPECT_EQ(333123456789ull, msg.field_uint64());
+  EXPECT_EQ(-5, msg.field_sint32());
+  EXPECT_EQ(-9000, msg.field_sint64());
+  EXPECT_EQ(12345u, msg.field_fixed32());
+  EXPECT_EQ(444123450000ull, msg.field_fixed64());
+  EXPECT_EQ(-69999, msg.field_sfixed32());
+  EXPECT_EQ(-200, msg.field_sfixed64());
+  EXPECT_FLOAT_EQ(3.14f, msg.field_float());
+  EXPECT_DOUBLE_EQ(0.5555, msg.field_double());
+  EXPECT_EQ(true, msg.field_bool());
+  EXPECT_EQ(decltype(msg.small_enum())::TO_BE, msg.small_enum());
+  EXPECT_EQ(decltype(msg.signed_enum())::NEGATIVE, msg.signed_enum());
+  EXPECT_EQ(decltype(msg.big_enum())::BEGIN, msg.big_enum());
+  EXPECT_EQ("FizzBuzz", msg.field_string());
+  EXPECT_EQ(std::string("\x11\x00\xBE\xEF", 4), msg.field_bytes());
+  ASSERT_THAT(msg.repeated_int32(), ElementsAreArray({1, -1, 100, 2000000}));
+}
+
+TEST(ProtoCppConformanceTest, GenEncode_GoldDecode) {
+  pbtest::EveryField msg;
+  SetTestingFields(&msg);
+  std::string serialized = msg.SerializeAsString();
+
+  pbgold::EveryField gold_msg;
+  gold_msg.ParseFromString(serialized);
+  CheckTestingFields(gold_msg);
+  EXPECT_EQ(serialized.size(), static_cast<size_t>(gold_msg.ByteSize()));
+}
+
+TEST(ProtoCppConformanceTest, GoldEncode_GenDecode) {
+  pbgold::EveryField gold_msg;
+  SetTestingFields(&gold_msg);
+  std::string serialized = gold_msg.SerializeAsString();
+
+  pbtest::EveryField msg;
+  EXPECT_TRUE(msg.ParseRawProto(serialized));
+  CheckTestingFields(msg);
+}
+
+TEST(ProtoCppConformanceTest, GenEncode_GenDecode) {
+  pbtest::EveryField msg;
+  SetTestingFields(&msg);
+  std::string serialized = msg.SerializeAsString();
+
+  pbtest::EveryField dec_msg;
+  dec_msg.ParseRawProto(serialized);
+  CheckTestingFields(dec_msg);
+  EXPECT_EQ(serialized.size(), dec_msg.SerializeAsString().size());
+}
+
+TEST(ProtoCppConformanceTest, NestedMessages) {
+  pbtest::NestedA msg_a;
+  pbtest::NestedA::NestedB* msg_b = msg_a.add_repeated_a();
+  pbtest::NestedA::NestedB::NestedC* msg_c = msg_b->mutable_value_b();
+  msg_c->set_value_c(321);
+  msg_b = msg_a.add_repeated_a();
+  msg_a.mutable_super_nested()->set_value_c(1000);
+  std::string serialized = msg_a.SerializeAsString();
+
+  pbgold::NestedA gold_msg_a;
+  gold_msg_a.ParseFromString(serialized);
+  EXPECT_EQ(2, gold_msg_a.repeated_a_size());
+  EXPECT_EQ(321, gold_msg_a.repeated_a(0).value_b().value_c());
+  EXPECT_FALSE(gold_msg_a.repeated_a(1).has_value_b());
+  EXPECT_EQ(gold_msg_a.repeated_a(1).value_b().value_c(), 0);
+  EXPECT_EQ(1000, gold_msg_a.super_nested().value_c());
+}
+
+// Tests that unknown fields are preserved when re-serializing. This test uses
+// the messages NestedA and NestedA_V2, where NestedA_V2 mimics a future
+// extension of NestedA. It starts filling the V2 version, than decodes it with
+// V1, then re-encodes V1 and decodes with V2 and finally check that all the V2
+// original fields have been preserved.
+TEST(ProtoCppConformanceTest, PreserveUnknownFields) {
+  std::string serialized;
+  {
+    pbtest::TestVersioning_V2 msg_v2;
+    msg_v2.set_root_int(10);
+    msg_v2.set_root_int_v2(11);
+    msg_v2.add_enumz(pbtest::TestVersioning_V2::ONE);
+    msg_v2.add_enumz(pbtest::TestVersioning_V2::TWO);
+    msg_v2.add_enumz(pbtest::TestVersioning_V2::THREE_V2);
+    msg_v2.set_root_string("root-string");
+    msg_v2.add_rep_string("root-rep-string-1");
+    msg_v2.add_rep_string("root-rep-string-2");
+    for (int i = 0; i < 3; i++) {
+      auto* sub1 = i == 0 ? msg_v2.mutable_sub1() : msg_v2.add_sub1_rep();
+      sub1->set_sub1_int(12);
+      sub1->set_sub1_string("sub1-string");
+      sub1->set_sub1_int_v2(13);
+      sub1->set_sub1_string_v2("sub1-string-v2");
+
+      auto* sub2 = i == 0 ? msg_v2.mutable_sub2() : msg_v2.add_sub2_rep();
+      sub2->set_sub2_int(14);
+      sub2->set_sub2_string("sub2-string");
+    }
+    {
+      pbtest::TestVersioning_V2::Sub1_V2 lazy;
+      lazy.set_sub1_int(15);
+      lazy.set_sub1_string("sub1-lazy-string");
+      lazy.set_sub1_int_v2(16);
+      lazy.set_sub1_string_v2("sub1-lazy-string-v2");
+      msg_v2.set_sub1_lazy_raw(lazy.SerializeAsString());
+    }
+    {
+      pbtest::TestVersioning_V2::Sub2_V2 lazy;
+      lazy.set_sub2_int(17);
+      lazy.set_sub2_string("sub2-v2-lazy-string");
+      msg_v2.set_sub2_lazy_raw(lazy.SerializeAsString());
+    }
+
+    serialized = msg_v2.SerializeAsString();
+  }
+
+  // Now decode with an earlier version that has less fields. Then re-serialize
+  // the v1 message.
+  {
+    pbtest::TestVersioning_V1 msg_v1;
+    EXPECT_TRUE(msg_v1.ParseRawProto(serialized));
+    EXPECT_EQ(msg_v1.root_int(), 10);
+    EXPECT_EQ(msg_v1.enumz_size(), 3);
+    // These are to workaround "ODR-usage" rules that would require that the
+    // constexpr in the .gen.h file have a matching symbol definition in the .cc
+    // file.
+    const auto ONE = pbtest::TestVersioning_V1::ONE;
+    const auto TWO = pbtest::TestVersioning_V1::TWO;
+    EXPECT_EQ(msg_v1.enumz()[0], ONE);
+    EXPECT_EQ(msg_v1.enumz()[1], TWO);
+    EXPECT_EQ(static_cast<int>(msg_v1.enumz()[2]), 3);
+    EXPECT_EQ(msg_v1.root_string(), "root-string");
+    EXPECT_EQ(msg_v1.rep_string_size(), 2);
+    EXPECT_EQ(msg_v1.rep_string()[0], "root-rep-string-1");
+    EXPECT_EQ(msg_v1.rep_string()[1], "root-rep-string-2");
+    EXPECT_EQ(msg_v1.sub1_rep_size(), 2);
+    for (size_t i = 0; i < 3; i++) {
+      auto* sub1 = i == 0 ? &msg_v1.sub1() : &msg_v1.sub1_rep()[i - 1];
+      EXPECT_EQ(sub1->sub1_int(), 12);
+      EXPECT_EQ(sub1->sub1_string(), "sub1-string");
+    }
+
+    // Append an extra field and change the valaue of an existing one before
+    // re-serializing.
+    msg_v1.set_root_int(101);
+    msg_v1.add_rep_string("extra-string");
+    serialized = msg_v1.SerializeAsString();
+  }
+
+  // Decode the re-serialized v1 message with with v2. Check that the _v2
+  // fields have been preserved in the double de/serializataion across versions.
+  {
+    pbtest::TestVersioning_V2 msg_v2;
+    EXPECT_TRUE(msg_v2.ParseRawProto(serialized));
+    EXPECT_EQ(msg_v2.root_int(), 101);
+    EXPECT_EQ(msg_v2.root_int_v2(), 11);
+    EXPECT_EQ(msg_v2.enumz_size(), 3);
+    const auto ONE = pbtest::TestVersioning_V2::ONE;
+    const auto TWO = pbtest::TestVersioning_V2::TWO;
+    const auto THREE_V2 = pbtest::TestVersioning_V2::THREE_V2;
+    EXPECT_EQ(msg_v2.enumz()[0], ONE);
+    EXPECT_EQ(msg_v2.enumz()[1], TWO);
+    EXPECT_EQ(msg_v2.enumz()[2], THREE_V2);
+    EXPECT_EQ(msg_v2.root_string(), "root-string");
+    EXPECT_EQ(msg_v2.rep_string_size(), 3);
+    EXPECT_EQ(msg_v2.rep_string()[0], "root-rep-string-1");
+    EXPECT_EQ(msg_v2.rep_string()[1], "root-rep-string-2");
+    EXPECT_EQ(msg_v2.rep_string()[2], "extra-string");
+    EXPECT_EQ(msg_v2.sub1_rep_size(), 2);
+    for (size_t i = 0; i < 3; i++) {
+      auto* sub1 = i == 0 ? &msg_v2.sub1() : &msg_v2.sub1_rep()[i - 1];
+      EXPECT_EQ(sub1->sub1_int(), 12);
+      EXPECT_EQ(sub1->sub1_string(), "sub1-string");
+      EXPECT_EQ(sub1->sub1_int_v2(), 13);
+      EXPECT_EQ(sub1->sub1_string_v2(), "sub1-string-v2");
+      auto* sub2 = i == 0 ? &msg_v2.sub2() : &msg_v2.sub2_rep()[i - 1];
+      EXPECT_EQ(sub2->sub2_int(), 14);
+      EXPECT_EQ(sub2->sub2_string(), "sub2-string");
+    }
+    {
+      pbtest::TestVersioning_V2::Sub1_V2 lazy;
+      EXPECT_TRUE(lazy.ParseRawProto(msg_v2.sub1_lazy_raw()));
+      EXPECT_EQ(lazy.sub1_int(), 15);
+      EXPECT_EQ(lazy.sub1_string(), "sub1-lazy-string");
+      EXPECT_EQ(lazy.sub1_int_v2(), 16);
+      EXPECT_EQ(lazy.sub1_string_v2(), "sub1-lazy-string-v2");
+    }
+    {
+      pbtest::TestVersioning_V2::Sub2_V2 lazy;
+      EXPECT_TRUE(lazy.ParseRawProto(msg_v2.sub2_lazy_raw()));
+      EXPECT_EQ(lazy.sub2_int(), 17);
+      EXPECT_EQ(lazy.sub2_string(), "sub2-v2-lazy-string");
+    }
+  }
+}
+
+// Checks that unset fields aren't zero-initialized in the decode -> re-encode
+// process.
+TEST(ProtoCppConformanceTest, DontDefaultInitialize) {
+  pbtest::EveryField msg;
+  EXPECT_FALSE(msg.has_field_int32());
+  msg.set_field_int32(0);
+  EXPECT_TRUE(msg.has_field_int32());
+
+  EXPECT_FALSE(msg.has_field_float());
+  msg.set_field_float(.0f);
+  EXPECT_TRUE(msg.has_field_float());
+
+  EXPECT_FALSE(msg.has_field_string());
+  msg.set_field_string("");
+  EXPECT_TRUE(msg.has_field_string());
+
+  pbtest::EveryField dec;
+  dec.ParseRawProto(msg.SerializeAsString());
+  std::string reserialized = dec.SerializeAsString();
+
+  pbgold::EveryField gold_msg;
+  gold_msg.ParseFromString(reserialized);
+  EXPECT_TRUE(gold_msg.has_field_int32());
+  EXPECT_EQ(gold_msg.field_int32(), 0);
+  EXPECT_TRUE(gold_msg.has_field_float());
+  EXPECT_FLOAT_EQ(gold_msg.field_float(), .0f);
+  EXPECT_TRUE(gold_msg.has_field_string());
+  EXPECT_EQ(gold_msg.field_string(), "");
+  EXPECT_FALSE(gold_msg.has_field_int64());
+  EXPECT_FALSE(gold_msg.has_field_uint64());
+  EXPECT_FALSE(gold_msg.has_field_bytes());
+}
+
+// Tests serialization and deserialization of packed encoding fields.
+TEST(ProtoCppConformanceTest, PackedRepeatedFields) {
+  std::string serialized;
+  {
+    pbtest::PackedRepeatedFields msg;
+
+    for (int i = -100; i < 100; i++)
+      msg.add_field_int32(i);
+
+    for (uint32_t i = 100; i < 200; i++)
+      msg.add_field_fixed32(i);
+
+    for (int64_t i = 5000000000; i < 5000001000; i++)
+      msg.add_field_sfixed64(i);
+
+    serialized = msg.SerializeAsString();
+  }
+  {
+    pbtest::PackedRepeatedFields msg;
+    EXPECT_TRUE(msg.ParseRawProto(serialized));
+
+    std::vector<int> exp_int32;
+    for (int i = -100; i < 100; i++)
+      exp_int32.emplace_back(i);
+    ASSERT_THAT(msg.field_int32(), ElementsAreArray(exp_int32));
+
+    std::vector<uint32_t> exp_fixed32;
+    for (uint32_t i = 100; i < 200; i++)
+      exp_fixed32.emplace_back(i);
+    ASSERT_THAT(msg.field_fixed32(), ElementsAreArray(exp_fixed32));
+
+    std::vector<int64_t> exp_sfixed64;
+    for (int64_t i = 5000000000; i < 5000001000; i++)
+      exp_sfixed64.emplace_back(i);
+    ASSERT_THAT(msg.field_sfixed64(), ElementsAreArray(exp_sfixed64));
+  }
+}
+}  // namespace
+}  // namespace protozero
diff --git a/src/protozero/test/example_proto/test_messages.proto b/src/protozero/test/example_proto/test_messages.proto
index db8212c..298b77f 100644
--- a/src/protozero/test/example_proto/test_messages.proto
+++ b/src/protozero/test/example_proto/test_messages.proto
@@ -104,3 +104,56 @@
   repeated fixed32 field_fixed32 = 2 [packed = true];
   repeated sfixed64 field_sfixed64 = 3 [packed = true];
 }
+
+// The following two messages are for testing that unknown fields being
+// preserved in the decode->reencode path.
+
+message TestVersioning_V1 {
+  enum Enumz_V1 {
+    ONE = 1;
+    TWO = 2;
+  }
+  message Sub1_V1 {
+    optional int32 sub1_int = 1;
+    optional string sub1_string = 2;
+  }
+  optional int32 root_int = 1;
+  repeated Enumz_V1 enumz = 2;
+  optional string root_string = 3;
+  repeated string rep_string = 4;
+  optional Sub1_V1 sub1 = 5;
+  repeated Sub1_V1 sub1_rep = 6;
+  optional Sub1_V1 sub1_lazy = 7 [lazy = true];
+}
+
+message TestVersioning_V2 {
+  enum Enumz_V2 {
+    ONE = 1;
+    TWO = 2;
+    THREE_V2 = 3;
+  }
+  message Sub1_V2 {
+    optional int32 sub1_int = 1;
+    optional string sub1_string = 2;
+    optional int32 sub1_int_v2 = 3;      // New in v2.
+    optional string sub1_string_v2 = 4;  // New in v2.
+  }
+  message Sub2_V2 {  // New in v2.
+    optional int32 sub2_int = 1;
+    optional string sub2_string = 2;
+  }
+
+  optional int32 root_int = 1;
+  repeated Enumz_V2 enumz = 2;
+  optional string root_string = 3;
+  repeated string rep_string = 4;
+  optional Sub1_V2 sub1 = 5;
+  repeated Sub1_V2 sub1_rep = 6;
+  optional Sub1_V2 sub1_lazy = 7 [lazy = true];
+
+  // New fields introduced in V2.
+  optional int32 root_int_v2 = 10;
+  optional Sub2_V2 sub2 = 11;
+  repeated Sub2_V2 sub2_rep = 12;
+  optional Sub2_V2 sub2_lazy = 13 [lazy = true];
+}
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index a096cd2..0cd6ff5 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -242,6 +242,8 @@
       "cpu_profile_stack_sample_table.h",
       "filtered_row_index.cc",
       "filtered_row_index.h",
+      "gfp_flags.cc",
+      "gfp_flags.h",
       "heap_profile_allocation_table.cc",
       "heap_profile_allocation_table.h",
       "instants_table.cc",
diff --git a/src/trace_processor/gfp_flags.cc b/src/trace_processor/gfp_flags.cc
new file mode 100644
index 0000000..2d5b587
--- /dev/null
+++ b/src/trace_processor/gfp_flags.cc
@@ -0,0 +1,253 @@
+/*
+ * 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/gfp_flags.h"
+#include <array>
+
+namespace perfetto {
+namespace trace_processor {
+
+namespace {
+
+struct Flag {
+  uint64_t mask;
+  const char* flag_name;
+};
+
+using FlagArray = std::array<Flag, 37>;
+
+constexpr FlagArray v3_4 = {
+    {{(((0x10u) | (0x40u) | (0x80u) | (0x20000u) | (0x02u) | (0x08u)) |
+       (0x4000u) | (0x10000u) | (0x1000u) | (0x200u) | (0x400000u)),
+      "GFP_TRANSHUGE"},
+     {((0x10u) | (0x40u) | (0x80u) | (0x20000u) | (0x02u) | (0x08u)),
+      "GFP_HIGHUSER_MOVABLE"},
+     {((0x10u) | (0x40u) | (0x80u) | (0x20000u) | (0x02u)), "GFP_HIGHUSER"},
+     {((0x10u) | (0x40u) | (0x80u) | (0x20000u)), "GFP_USER"},
+     {((0x10u) | (0x40u) | (0x80u) | (0x80000u)), "GFP_TEMPORARY"},
+     {((0x10u) | (0x40u) | (0x80u)), "GFP_KERNEL"},
+     {((0x10u) | (0x40u)), "GFP_NOFS"},
+     {((0x20u)), "GFP_ATOMIC"},
+     {((0x10u)), "GFP_NOIO"},
+     {(0x20u), "GFP_HIGH"},
+     {(0x10u), "GFP_WAIT"},
+     {(0x40u), "GFP_IO"},
+     {(0x100u), "GFP_COLD"},
+     {(0x200u), "GFP_NOWARN"},
+     {(0x400u), "GFP_REPEAT"},
+     {(0x800u), "GFP_NOFAIL"},
+     {(0x1000u), "GFP_NORETRY"},
+     {(0x4000u), "GFP_COMP"},
+     {(0x8000u), "GFP_ZERO"},
+     {(0x10000u), "GFP_NOMEMALLOC"},
+     {(0x20000u), "GFP_HARDWALL"},
+     {(0x40000u), "GFP_THISNODE"},
+     {(0x80000u), "GFP_RECLAIMABLE"},
+     {(0x08u), "GFP_MOVABLE"},
+     {(0), "GFP_NOTRACK"},
+     {(0x400000u), "GFP_NO_KSWAPD"},
+     {(0x800000u), "GFP_OTHER_NODE"},
+     {0, nullptr}}};
+
+constexpr FlagArray v3_10 = {
+    {{(((0x10u) | (0x40u) | (0x80u) | (0x20000u) | (0x02u) | (0x08u)) |
+       (0x4000u) | (0x10000u) | (0x1000u) | (0x200u) | (0x400000u)),
+      "GFP_TRANSHUGE"},
+     {((0x10u) | (0x40u) | (0x80u) | (0x20000u) | (0x02u) | (0x08u)),
+      "GFP_HIGHUSER_MOVABLE"},
+     {((0x10u) | (0x40u) | (0x80u) | (0x20000u) | (0x02u)), "GFP_HIGHUSER"},
+     {((0x10u) | (0x40u) | (0x80u) | (0x20000u)), "GFP_USER"},
+     {((0x10u) | (0x40u) | (0x80u) | (0x80000u)), "GFP_TEMPORARY"},
+     {((0x10u) | (0x40u) | (0x80u)), "GFP_KERNEL"},
+     {((0x10u) | (0x40u)), "GFP_NOFS"},
+     {((0x20u)), "GFP_ATOMIC"},
+     {((0x10u)), "GFP_NOIO"},
+     {(0x20u), "GFP_HIGH"},
+     {(0x10u), "GFP_WAIT"},
+     {(0x40u), "GFP_IO"},
+     {(0x100u), "GFP_COLD"},
+     {(0x200u), "GFP_NOWARN"},
+     {(0x400u), "GFP_REPEAT"},
+     {(0x800u), "GFP_NOFAIL"},
+     {(0x1000u), "GFP_NORETRY"},
+     {(0x4000u), "GFP_COMP"},
+     {(0x8000u), "GFP_ZERO"},
+     {(0x10000u), "GFP_NOMEMALLOC"},
+     {(0x2000u), "GFP_MEMALLOC"},
+     {(0x20000u), "GFP_HARDWALL"},
+     {(0x40000u), "GFP_THISNODE"},
+     {(0x80000u), "GFP_RECLAIMABLE"},
+     {(0x100000u), "GFP_KMEMCG"},
+     {(0x08u), "GFP_MOVABLE"},
+     {(0x200000u), "GFP_NOTRACK"},
+     {(0x400000u), "GFP_NO_KSWAPD"},
+     {(0x800000u), "GFP_OTHER_NODE"},
+     {0, nullptr}}};
+
+constexpr FlagArray v4_4 = {
+    {{(((((((0x400000u | 0x2000000u)) | (0x40u) | (0x80u) | (0x20000u)) |
+          (0x02u)) |
+         (0x08u)) |
+        (0x4000u) | (0x10000u) | (0x1000u) | (0x200u)) &
+       ~(0x2000000u)),
+      "GFP_TRANSHUGE"},
+     {(((((0x400000u | 0x2000000u)) | (0x40u) | (0x80u) | (0x20000u)) |
+        (0x02u)) |
+       (0x08u)),
+      "GFP_HIGHUSER_MOVABLE"},
+     {((((0x400000u | 0x2000000u)) | (0x40u) | (0x80u) | (0x20000u)) | (0x02u)),
+      "GFP_HIGHUSER"},
+     {(((0x400000u | 0x2000000u)) | (0x40u) | (0x80u) | (0x20000u)),
+      "GFP_USER"},
+     {(((0x400000u | 0x2000000u)) | (0x40u) | (0x80u) | (0x10u)),
+      "GFP_TEMPORARY"},
+     {(((0x400000u | 0x2000000u)) | (0x40u) | (0x80u)), "GFP_KERNEL"},
+     {(((0x400000u | 0x2000000u)) | (0x40u)), "GFP_NOFS"},
+     {((0x20u) | (0x80000u) | (0x2000000u)), "GFP_ATOMIC"},
+     {(((0x400000u | 0x2000000u))), "GFP_NOIO"},
+     {(0x20u), "GFP_HIGH"},
+     {(0x80000u), "GFP_ATOMIC"},
+     {(0x40u), "GFP_IO"},
+     {(0x100u), "GFP_COLD"},
+     {(0x200u), "GFP_NOWARN"},
+     {(0x400u), "GFP_REPEAT"},
+     {(0x800u), "GFP_NOFAIL"},
+     {(0x1000u), "GFP_NORETRY"},
+     {(0x4000u), "GFP_COMP"},
+     {(0x8000u), "GFP_ZERO"},
+     {(0x10000u), "GFP_NOMEMALLOC"},
+     {(0x2000u), "GFP_MEMALLOC"},
+     {(0x20000u), "GFP_HARDWALL"},
+     {(0x40000u), "GFP_THISNODE"},
+     {(0x10u), "GFP_RECLAIMABLE"},
+     {(0x08u), "GFP_MOVABLE"},
+     {(0x200000u), "GFP_NOTRACK"},
+     {(0x400000u), "GFP_DIRECT_RECLAIM"},
+     {(0x2000000u), "GFP_KSWAPD_RECLAIM"},
+     {(0x800000u), "GFP_OTHER_NODE"},
+     {0, nullptr}}};
+
+constexpr FlagArray v4_14 = {
+    {{((((((((0x400000u | 0x1000000u)) | (0x40u) | (0x80u) | (0x20000u)) |
+           (0x02u)) |
+          (0x08u)) |
+         (0x4000u) | (0x10000u) | (0x200u)) &
+        ~((0x400000u | 0x1000000u))) |
+       (0x400000u)),
+      "GFP_TRANSHUGE"},
+     {(((((((0x400000u | 0x1000000u)) | (0x40u) | (0x80u) | (0x20000u)) |
+          (0x02u)) |
+         (0x08u)) |
+        (0x4000u) | (0x10000u) | (0x200u)) &
+       ~((0x400000u | 0x1000000u))),
+      "GFP_TRANSHUGE_LIGHT"},
+     {(((((0x400000u | 0x1000000u)) | (0x40u) | (0x80u) | (0x20000u)) |
+        (0x02u)) |
+       (0x08u)),
+      "GFP_HIGHUSER_MOVABLE"},
+     {((((0x400000u | 0x1000000u)) | (0x40u) | (0x80u) | (0x20000u)) | (0x02u)),
+      "GFP_HIGHUSER"},
+     {(((0x400000u | 0x1000000u)) | (0x40u) | (0x80u) | (0x20000u)),
+      "GFP_USER"},
+     {((((0x400000u | 0x1000000u)) | (0x40u) | (0x80u)) | (0x100000u)),
+      "GFP_KERNEL_ACCOUNT"},
+     {(((0x400000u | 0x1000000u)) | (0x40u) | (0x80u)), "GFP_KERNEL"},
+     {(((0x400000u | 0x1000000u)) | (0x40u)), "GFP_NOFS"},
+     {((0x20u) | (0x80000u) | (0x1000000u)), "GFP_ATOMIC"},
+     {(((0x400000u | 0x1000000u))), "GFP_NOIO"},
+     {((0x1000000u)), "GFP_NOWAIT"},
+     {(0x01u), "GFP_DMA"},
+     {(0x02u), "__GFP_HIGHMEM"},
+     {(0x04u), "GFP_DMA32"},
+     {(0x20u), "__GFP_HIGH"},
+     {(0x80000u), "__GFP_ATOMIC"},
+     {(0x40u), "__GFP_IO"},
+     {(0x80u), "__GFP_FS"},
+     {(0x100u), "__GFP_COLD"},
+     {(0x200u), "__GFP_NOWARN"},
+     {(0x400u), "__GFP_RETRY_MAYFAIL"},
+     {(0x800u), "__GFP_NOFAIL"},
+     {(0x1000u), "__GFP_NORETRY"},
+     {(0x4000u), "__GFP_COMP"},
+     {(0x8000u), "__GFP_ZERO"},
+     {(0x10000u), "__GFP_NOMEMALLOC"},
+     {(0x2000u), "__GFP_MEMALLOC"},
+     {(0x20000u), "__GFP_HARDWALL"},
+     {(0x40000u), "__GFP_THISNODE"},
+     {(0x10u), "__GFP_RECLAIMABLE"},
+     {(0x08u), "__GFP_MOVABLE"},
+     {(0x100000u), "__GFP_ACCOUNT"},
+     {(0x800000u), "__GFP_WRITE"},
+     {((0x400000u | 0x1000000u)), "__GFP_RECLAIM"},
+     {(0x400000u), "__GFP_DIRECT_RECLAIM"},
+     {(0x1000000u), "__GFP_KSWAPD_RECLAIM"},
+     {0, nullptr}}};
+
+// Get the bitmask closest to the kernel version. For versions less than 3.4
+// and greater than 4.14 this may end up being inaccurate.
+const FlagArray* GetBitmaskVersion(std::tuple<int32_t, int32_t> version) {
+  if (version < std::make_tuple(3, 10)) {
+    return &v3_4;
+  } else if (version >= std::make_tuple(3, 10) &&
+             version < std::make_tuple(4, 4)) {
+    return &v3_10;
+  } else if (version >= std::make_tuple(4, 4) &&
+             version < std::make_tuple(4, 14)) {
+    return &v4_4;
+  } else {  // version >= 4.14
+    // TODO(taylori): Add newer kernel versions once we have access to them.
+    return &v4_14;
+  }
+}
+}  // namespace
+
+void WriteGfpFlag(uint64_t value,
+                  std::tuple<uint32_t, uint32_t> version,
+                  base::StringWriter* writer) {
+  // On all kernel versions if this flag is not set, return GFP_NOWAIT.
+  if (value == 0)
+    writer->AppendString("GFP_NOWAIT");
+
+  std::string result;
+  const FlagArray* bitmasks = GetBitmaskVersion(version);
+
+  // Based on trace_print_flags_seq() in the kernel.
+  size_t i = 0;
+  while (bitmasks->at(i).flag_name != nullptr) {
+    size_t current = i++;
+    uint64_t mask = bitmasks->at(current).mask;
+    const char* str = bitmasks->at(current).flag_name;
+
+    if ((value & mask) != mask)
+      continue;
+    value &= ~mask;
+
+    result += str;
+    result += "|";
+  }
+
+  // Add any leftover flags.
+  if (value) {
+    writer->AppendString(result.c_str(), result.size());
+    writer->AppendString("0x", 2);
+    writer->AppendHexInt(value);
+  } else {
+    writer->AppendString(result.c_str(), result.size() - 1);
+  }
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/gfp_flags.h b/src/trace_processor/gfp_flags.h
new file mode 100644
index 0000000..05e3bdf
--- /dev/null
+++ b/src/trace_processor/gfp_flags.h
@@ -0,0 +1,35 @@
+/*
+ * 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_GFP_FLAGS_H_
+#define SRC_TRACE_PROCESSOR_GFP_FLAGS_H_
+
+#include "perfetto/ext/base/string_writer.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// GFP flags in ftrace events should be parsed and read differently depending
+// the kernel version. This function writes a human readable version of the
+// flag.
+void WriteGfpFlag(uint64_t value,
+                  std::tuple<uint32_t, uint32_t> version,
+                  base::StringWriter* writer);
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_GFP_FLAGS_H_
diff --git a/src/trace_processor/importers/proto/system_probes_parser.cc b/src/trace_processor/importers/proto/system_probes_parser.cc
index e93578c..7efcc6e 100644
--- a/src/trace_processor/importers/proto/system_probes_parser.cc
+++ b/src/trace_processor/importers/proto/system_probes_parser.cc
@@ -20,6 +20,7 @@
 #include "perfetto/ext/traced/sys_stats_counters.h"
 #include "perfetto/protozero/proto_decoder.h"
 #include "src/trace_processor/event_tracker.h"
+#include "src/trace_processor/metadata.h"
 #include "src/trace_processor/process_tracker.h"
 #include "src/trace_processor/syscall_tracker.h"
 #include "src/trace_processor/trace_processor_context.h"
@@ -296,6 +297,24 @@
     } else {
       PERFETTO_ELOG("Unknown architecture %s", machine.ToStdString().c_str());
     }
+
+    StringPool::Id sysname_id =
+        context_->storage->InternString(utsname.sysname());
+    StringPool::Id version_id =
+        context_->storage->InternString(utsname.version());
+    StringPool::Id release_id =
+        context_->storage->InternString(utsname.release());
+    StringPool::Id machine_id =
+        context_->storage->InternString(utsname.machine());
+
+    context_->storage->SetMetadata(metadata::system_name,
+                                   Variadic::String(sysname_id));
+    context_->storage->SetMetadata(metadata::system_version,
+                                   Variadic::String(version_id));
+    context_->storage->SetMetadata(metadata::system_release,
+                                   Variadic::String(release_id));
+    context_->storage->SetMetadata(metadata::system_machine,
+                                   Variadic::String(machine_id));
   }
 }
 
diff --git a/src/trace_processor/metadata.h b/src/trace_processor/metadata.h
index b5bef83..7faa8bc 100644
--- a/src/trace_processor/metadata.h
+++ b/src/trace_processor/metadata.h
@@ -40,7 +40,11 @@
   F(benchmark_story_tags,                kMulti,   Variadic::kString), \
   F(android_packages_list,               kMulti,   Variadic::kInt),    \
   F(statsd_triggering_subscription_id,   kSingle,  Variadic::kInt),    \
-  F(trace_uuid,                          kSingle,   Variadic::kString)
+  F(trace_uuid,                          kSingle,  Variadic::kString), \
+  F(system_name,                         kSingle,  Variadic::kString), \
+  F(system_version,                      kSingle,  Variadic::kString), \
+  F(system_release,                      kSingle,  Variadic::kString), \
+  F(system_machine,                      kSingle,  Variadic::kString)
 // clang-format on
 
 enum KeyType {
diff --git a/src/trace_processor/metrics/BUILD.gn b/src/trace_processor/metrics/BUILD.gn
index 28d6f01..a5b92bc 100644
--- a/src/trace_processor/metrics/BUILD.gn
+++ b/src/trace_processor/metrics/BUILD.gn
@@ -22,7 +22,6 @@
   "android/android_cpu_agg.sql",
   "android/android_mem.sql",
   "android/android_mem_unagg.sql",
-  "android/android_process_growth.sql",
   "android/android_ion.sql",
   "android/android_lmk.sql",
   "android/android_powrails.sql",
@@ -35,6 +34,7 @@
   "android/java_heap_stats.sql",
   "android/process_unagg_mem_view.sql",
   "android/process_mem.sql",
+  "android/process_metadata.sql",
   "android/mem_stats_priority_breakdown.sql",
   "android/span_view_stats.sql",
   "android/upid_span_view.sql",
diff --git a/src/trace_processor/metrics/android/android_package_list.sql b/src/trace_processor/metrics/android/android_package_list.sql
index ff9bbfe..7ca9c15 100644
--- a/src/trace_processor/metrics/android/android_package_list.sql
+++ b/src/trace_processor/metrics/android/android_package_list.sql
@@ -15,30 +15,41 @@
 --
 
 -- Get distinct packages list
+DROP VIEW IF EXISTS package_arg_ids;
+
 CREATE VIEW package_arg_ids AS
 SELECT int_value AS arg_set_id
 FROM metadata WHERE name = 'android_packages_list';
 
 -- Generate a table mapping package names to their attributes
+DROP VIEW IF EXISTS package_args;
+
 CREATE VIEW package_args AS
 SELECT arg_set_id, key, string_value, int_value
 FROM package_arg_ids JOIN args USING(arg_set_id);
 
+DROP TABLE IF EXISTS package_list;
+
 CREATE TABLE package_list(
   package_name TEXT PRIMARY KEY,
   uid INT,
-  version_code INT
+  version_code INT,
+  debuggable INT
 );
 
 INSERT OR REPLACE INTO package_list
-SELECT names.name, uids.uid, versions.version
+SELECT names.name, uids.uid, versions.version, debuggable.is_debug
 FROM
   (SELECT arg_set_id, string_value name FROM package_args WHERE key = 'name')
     AS names
   JOIN (SELECT arg_set_id, int_value uid FROM package_args WHERE key = 'uid')
     AS uids USING (arg_set_id)
   JOIN (SELECT arg_set_id, int_value version FROM package_args WHERE key = 'version_code')
-    AS versions USING (arg_set_id);
+    AS versions USING (arg_set_id)
+  JOIN (SELECT arg_set_id, int_value is_debug FROM package_args WHERE key = 'debuggable')
+    AS debuggable USING (arg_set_id);
+
+DROP VIEW IF EXISTS android_package_list_output;
 
 CREATE VIEW android_package_list_output AS
 SELECT AndroidPackageList(
diff --git a/src/trace_processor/metrics/android/android_process_growth.sql b/src/trace_processor/metrics/android/android_process_growth.sql
deleted file mode 100644
index 956ce92..0000000
--- a/src/trace_processor/metrics/android/android_process_growth.sql
+++ /dev/null
@@ -1,69 +0,0 @@
---
--- Copyright 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
---
---     https://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.
---
-
-SELECT RUN_METRIC('android/process_mem.sql');
-
-CREATE VIEW malloc_memory_delta AS
-SELECT upid, SUM(size) AS delta
-FROM heap_profile_allocation
-GROUP BY 1;
-
-CREATE VIEW malloc_memory_allocated AS
-SELECT upid, SUM(size) AS total
-FROM heap_profile_allocation
-WHERE size > 0
-GROUP BY 1;
-
-CREATE VIEW anon_and_swap_delta AS
-SELECT DISTINCT
-  upid,
-  FIRST_VALUE(anon_and_swap_val) OVER upid_window AS start_val,
-  LAST_VALUE(anon_and_swap_val) OVER upid_window AS end_val
-FROM anon_and_swap_span
-WINDOW upid_window AS (
-  PARTITION BY upid
-  ORDER BY ts
-  ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
-);
-
-CREATE VIEW process_growth AS
-SELECT
-  process.pid AS pid,
-  process.name AS process_name,
-  CAST(asd.start_val AS BIG INT) AS anon_and_swap_start_value,
-  CAST(asd.end_val - asd.start_val AS BIG INT) AS anon_and_swap_change,
-  malloc_memory_delta.delta AS malloc_memory_delta,
-  malloc_memory_allocated.total AS malloc_memory_total
-FROM anon_and_swap_delta AS asd
-JOIN process USING (upid)
-LEFT JOIN malloc_memory_delta USING (upid)
-LEFT JOIN malloc_memory_allocated USING (upid);
-
-CREATE VIEW instance_metrics_proto AS
-SELECT AndroidProcessGrowth_InstanceMetrics(
-  'pid', pid,
-  'process_name', process_name,
-  'anon_and_swap_start_value', anon_and_swap_start_value,
-  'anon_and_swap_change_bytes', anon_and_swap_change,
-  'malloc_memory_change_bytes', malloc_memory_delta,
-  'malloc_memory_total_allocated_bytes', malloc_memory_total
-) AS instance_metric
-FROM process_growth;
-
-CREATE VIEW android_process_growth_output AS
-SELECT AndroidProcessGrowth(
-  'instance_metrics', (SELECT RepeatedField(instance_metric) FROM instance_metrics_proto)
-);
diff --git a/src/trace_processor/metrics/android/heap_profile_callsites.sql b/src/trace_processor/metrics/android/heap_profile_callsites.sql
index ce2aeb4..f84a8ca 100644
--- a/src/trace_processor/metrics/android/heap_profile_callsites.sql
+++ b/src/trace_processor/metrics/android/heap_profile_callsites.sql
@@ -14,6 +14,8 @@
 -- limitations under the License.
 --
 
+SELECT RUN_METRIC('android/process_metadata.sql');
+
 CREATE VIEW memory_delta AS
 SELECT upid, SUM(size) AS delta
 FROM heap_profile_allocation
@@ -216,6 +218,7 @@
 SELECT HeapProfileCallsites_InstanceStats(
     'pid', process.pid,
     'process_name', process.name,
+    'process', process_metadata.metadata,
     'callsites', repeated_callsite_proto,
     'profile_delta_bytes', memory_delta.delta,
     'profile_total_bytes', memory_total.total
@@ -223,7 +226,8 @@
 FROM process_callsite_proto
 JOIN memory_total USING (upid)
 JOIN memory_delta USING (upid)
-JOIN process USING (upid);
+JOIN process USING (upid)
+JOIN process_metadata USING (upid);
 
 CREATE VIEW heap_profile_callsites_output AS
 SELECT HeapProfileCallsites(
diff --git a/src/trace_processor/metrics/android/java_heap_stats.sql b/src/trace_processor/metrics/android/java_heap_stats.sql
index d8f2f34..e5d80b2 100644
--- a/src/trace_processor/metrics/android/java_heap_stats.sql
+++ b/src/trace_processor/metrics/android/java_heap_stats.sql
@@ -14,6 +14,8 @@
 -- limitations under the License.
 --
 
+SELECT RUN_METRIC('android/process_metadata.sql');
+
 CREATE VIEW total_size_samples AS
 SELECT upid, graph_sample_ts, SUM(self_size) AS total_size
 FROM heap_graph_object
@@ -43,16 +45,16 @@
 CREATE TABLE heap_graph_instance_stats AS
 SELECT
   upid,
-  process.name process_name,
+  process_metadata.metadata AS process_metadata,
   RepeatedField(sample_proto) AS sample_protos
-FROM heap_graph_sample_protos JOIN process USING (upid)
+FROM heap_graph_sample_protos JOIN process_metadata USING (upid)
 GROUP BY 1, 2;
 
 CREATE VIEW java_heap_stats_output AS
 SELECT JavaHeapStats(
   'instance_stats', RepeatedField(JavaHeapStats_InstanceStats(
     'upid', upid,
-    'process_name', process_name,
+    'process', process_metadata,
     'samples', sample_protos
   )))
 FROM heap_graph_instance_stats;
diff --git a/src/trace_processor/metrics/android/process_metadata.sql b/src/trace_processor/metrics/android/process_metadata.sql
new file mode 100644
index 0000000..59e86bd
--- /dev/null
+++ b/src/trace_processor/metrics/android/process_metadata.sql
@@ -0,0 +1,31 @@
+--
+-- Copyright 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
+--
+--     https://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.
+--
+
+SELECT RUN_METRIC('android/android_package_list.sql');
+
+DROP TABLE IF EXISTS process_metadata;
+
+CREATE TABLE process_metadata AS
+SELECT
+  process.upid,
+  AndroidProcessMetadata(
+    'name', process.name,
+    'uid', uid,
+    'package_name', plist.package_name,
+    'apk_version_code', plist.version_code,
+    'debuggable', plist.debuggable
+  ) AS metadata
+FROM process LEFT JOIN package_list plist USING (uid);
diff --git a/src/trace_processor/metrics/metrics.descriptor.h b/src/trace_processor/metrics/metrics.descriptor.h
index df7696c..9507204 100644
--- a/src/trace_processor/metrics/metrics.descriptor.h
+++ b/src/trace_processor/metrics/metrics.descriptor.h
@@ -12,14 +12,14 @@
 // SHA1(tools/gen_binary_descriptors)
 // 192b582ae52bb07b3d3ba66a94bcfd3127a5f42f
 // SHA1(protos/perfetto/metrics/metrics.proto)
-// 4279eeace6a7d9647e484e65b8265ea211a02b6c
+// fb0504ef20a790f031fc622ba1b9312cb97d67a6
 
 // This is the proto Metrics encoded as a ProtoFileDescriptor to allow
 // for reflection without libprotobuf full/non-lite protos.
 
 namespace perfetto {
 
-constexpr std::array<uint8_t, 10312> kMetricsDescriptor{
+constexpr std::array<uint8_t, 10105> kMetricsDescriptor{
     {0x0a, 0x98, 0x03, 0x0a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
      0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
      0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
@@ -262,470 +262,460 @@
      0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08,
      0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05,
      0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52,
-     0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x90,
-     0x04, 0x0a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
+     0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xaf,
+     0x02, 0x0a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
      0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x77, 0x74,
-     0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x22, 0xc2, 0x03, 0x0a, 0x14, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74,
-     0x68, 0x12, 0x60, 0x0a, 0x10, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
-     0x65, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x01, 0x20,
-     0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-     0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61,
-     0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x0f,
-     0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x73, 0x1a, 0xc7, 0x02, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x74,
-     0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12,
-     0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
-     0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f,
-     0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
-     0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-     0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x19, 0x61, 0x6e, 0x6f, 0x6e,
-     0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x73, 0x74,
-     0x61, 0x72, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20,
-     0x01, 0x28, 0x03, 0x52, 0x15, 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e, 0x64,
-     0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x72, 0x74, 0x56, 0x61, 0x6c,
-     0x75, 0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x61,
-     0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x63, 0x68, 0x61, 0x6e,
-     0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x16, 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x53,
-     0x77, 0x61, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x79, 0x74,
-     0x65, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63,
-     0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x63, 0x68, 0x61, 0x6e,
-     0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x17, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x4d, 0x65,
-     0x6d, 0x6f, 0x72, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x79,
-     0x74, 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x23, 0x6d, 0x61, 0x6c, 0x6c, 0x6f,
-     0x63, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x74, 0x6f, 0x74,
-     0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64,
-     0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
-     0x52, 0x1f, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x4d, 0x65, 0x6d, 0x6f,
-     0x72, 0x79, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
-     0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x02, 0x48,
-     0x03, 0x0a, 0xaf, 0x02, 0x0a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x2f, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 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,
-     0xe5, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49,
-     0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x40, 0x0a, 0x06,
-     0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
-     0x32, 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
-     0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x52, 0x06, 0x62, 0x75, 0x66, 0x66,
-     0x65, 0x72, 0x1a, 0x8e, 0x01, 0x0a, 0x06, 0x42, 0x75, 0x66, 0x66, 0x65,
-     0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
-     0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a,
-     0x0e, 0x61, 0x76, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79,
-     0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x61,
-     0x76, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12,
-     0x24, 0x0a, 0x0e, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f,
-     0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52,
-     0x0c, 0x6d, 0x69, 0x6e, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65,
-     0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x69, 0x7a,
-     0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
-     0x01, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79,
-     0x74, 0x65, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x95, 0x02, 0x0a, 0x30,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
-     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b, 0x5f,
-     0x6d, 0x65, 0x74, 0x72, 0x69, 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, 0xcb, 0x01, 0x0a, 0x10, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
-     0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
-     0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
-     0x4e, 0x0a, 0x0c, 0x62, 0x79, 0x5f, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63,
-     0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e,
+     0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x69,
+     0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 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, 0xe5, 0x01, 0x0a,
+     0x10, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x40, 0x0a, 0x06, 0x62, 0x75, 0x66,
+     0x66, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e,
      0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c,
-     0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x42, 0x79, 0x4f,
-     0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x0a, 0x62, 0x79, 0x4f,
-     0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x0a, 0x42,
-     0x79, 0x4f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x22, 0x0a,
-     0x0d, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x61,
-     0x64, 0x6a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6f,
-     0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12, 0x14, 0x0a,
-     0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
-     0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x02, 0x48, 0x03, 0x0a,
-     0xf4, 0x02, 0x0a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
-     0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6d, 0x65, 0x74,
+     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49,
+     0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x42, 0x75, 0x66,
+     0x66, 0x65, 0x72, 0x52, 0x06, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x1a,
+     0x8e, 0x01, 0x0a, 0x06, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x12, 0x12,
+     0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+     0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x76,
+     0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x61, 0x76, 0x67, 0x53,
+     0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e,
+     0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74,
+     0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x6d, 0x69,
+     0x6e, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x24,
+     0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62,
+     0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c,
+     0x6d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73,
+     0x42, 0x02, 0x48, 0x03, 0x0a, 0x95, 0x02, 0x0a, 0x30, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
+     0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b, 0x5f, 0x6d, 0x65, 0x74,
      0x72, 0x69, 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, 0xa5, 0x02, 0x0a, 0x11, 0x41, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73,
-     0x12, 0x4e, 0x0a, 0x0b, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x72, 0x61,
-     0x69, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
-     0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x50, 0x6f,
-     0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0a, 0x70, 0x6f,
-     0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x1a, 0x4e, 0x0a, 0x0a,
-     0x45, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x21,
-     0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f,
-     0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69,
-     0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x73, 0x12, 0x1d, 0x0a,
-     0x0a, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x5f, 0x75, 0x77, 0x73, 0x18,
-     0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x65, 0x6e, 0x65, 0x72, 0x67,
-     0x79, 0x55, 0x77, 0x73, 0x1a, 0x70, 0x0a, 0x0a, 0x50, 0x6f, 0x77, 0x65,
-     0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
-     0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
-     0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x0b, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79,
-     0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
-     0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x2e,
-     0x45, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0a,
-     0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x42, 0x02,
-     0x48, 0x03, 0x0a, 0xac, 0x0e, 0x0a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x2f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x6d,
-     0x65, 0x74, 0x72, 0x69, 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, 0xde, 0x0d, 0x0a, 0x14, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x47, 0x0a, 0x07, 0x73, 0x74, 0x61,
-     0x72, 0x74, 0x75, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d,
-     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x52, 0x07, 0x73,
-     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x1a, 0xe0, 0x01, 0x0a, 0x12, 0x54,
-     0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x72, 0x65, 0x61,
-     0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x75, 0x6e,
-     0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18,
-     0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x75, 0x6e, 0x6e, 0x69,
-     0x6e, 0x67, 0x44, 0x75, 0x72, 0x4e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x72,
-     0x75, 0x6e, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x5f,
-     0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x72, 0x75,
-     0x6e, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x4e, 0x73, 0x12,
-     0x3f, 0x0a, 0x1c, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75,
-     0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x6c, 0x65, 0x65, 0x70,
-     0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x03, 0x52, 0x19, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75,
-     0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x44,
-     0x75, 0x72, 0x4e, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x69, 0x6e, 0x74, 0x65,
-     0x72, 0x72, 0x75, 0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x6c,
-     0x65, 0x65, 0x70, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x04,
-     0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72,
-     0x75, 0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x53, 0x6c, 0x65, 0x65, 0x70,
-     0x44, 0x75, 0x72, 0x4e, 0x73, 0x1a, 0x1e, 0x0a, 0x05, 0x53, 0x6c, 0x69,
-     0x63, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x75, 0x72, 0x4e,
-     0x73, 0x1a, 0xbb, 0x08, 0x0a, 0x0c, 0x54, 0x6f, 0x46, 0x69, 0x72, 0x73,
-     0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x75,
-     0x72, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05,
-     0x64, 0x75, 0x72, 0x4e, 0x73, 0x12, 0x72, 0x0a, 0x19, 0x6d, 0x61, 0x69,
-     0x6e, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x79, 0x5f,
-     0x74, 0x61, 0x73, 0x6b, 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, 0x41,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75,
-     0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54, 0x61, 0x73, 0x6b,
-     0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f,
-     0x77, 0x6e, 0x52, 0x15, 0x6d, 0x61, 0x69, 0x6e, 0x54, 0x68, 0x72, 0x65,
-     0x61, 0x64, 0x42, 0x79, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74,
-     0x65, 0x12, 0x41, 0x0a, 0x1d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x70,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x73, 0x70, 0x61,
-     0x77, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03,
-     0x20, 0x01, 0x28, 0x0d, 0x52, 0x1a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x50,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x53, 0x70, 0x61, 0x77,
-     0x6e, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x5f, 0x0a, 0x15,
-     0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74,
-     0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x18, 0x04, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70,
-     0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65,
-     0x52, 0x13, 0x74, 0x69, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69,
-     0x74, 0x79, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x66, 0x0a,
-     0x19, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69,
-     0x74, 0x79, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6d, 0x61,
-     0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70,
+     0x6f, 0x73, 0x22, 0xcb, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+     0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12,
+     0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75,
+     0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x74, 0x6f,
+     0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x4e, 0x0a, 0x0c,
+     0x62, 0x79, 0x5f, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65,
+     0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x42, 0x79, 0x4f, 0x6f, 0x6d, 0x53,
+     0x63, 0x6f, 0x72, 0x65, 0x52, 0x0a, 0x62, 0x79, 0x4f, 0x6f, 0x6d, 0x53,
+     0x63, 0x6f, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x0a, 0x42, 0x79, 0x4f, 0x6f,
+     0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x6f,
+     0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x64, 0x6a, 0x18,
+     0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6f, 0x6d, 0x53, 0x63,
+     0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f,
+     0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63,
+     0x6f, 0x75, 0x6e, 0x74, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xf4, 0x02, 0x0a,
+     0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+     0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x6f, 0x77,
+     0x72, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 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,
+     0xa5, 0x02, 0x0a, 0x11, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
+     0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4e, 0x0a,
+     0x0b, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x72, 0x61, 0x69, 0x6c, 0x73,
+     0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65,
+     0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x50, 0x6f, 0x77, 0x65, 0x72,
+     0x52, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0a, 0x70, 0x6f, 0x77, 0x65, 0x72,
+     0x52, 0x61, 0x69, 0x6c, 0x73, 0x1a, 0x4e, 0x0a, 0x0a, 0x45, 0x6e, 0x65,
+     0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x74,
+     0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6d, 0x73, 0x18,
+     0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73,
+     0x74, 0x61, 0x6d, 0x70, 0x4d, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6e,
+     0x65, 0x72, 0x67, 0x79, 0x5f, 0x75, 0x77, 0x73, 0x18, 0x02, 0x20, 0x01,
+     0x28, 0x01, 0x52, 0x09, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x55, 0x77,
+     0x73, 0x1a, 0x70, 0x0a, 0x0a, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61,
+     0x69, 0x6c, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+     0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
+     0x4e, 0x0a, 0x0b, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x5f, 0x64, 0x61,
+     0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70,
      0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74,
-     0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
-     0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x41,
-     0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x68, 0x72, 0x65, 0x61,
-     0x64, 0x4d, 0x61, 0x69, 0x6e, 0x12, 0x5f, 0x0a, 0x15, 0x74, 0x69, 0x6d,
-     0x65, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69,
-     0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
+     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f,
+     0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x6e, 0x65,
+     0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0a, 0x65, 0x6e, 0x65,
+     0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x42, 0x02, 0x48, 0x03, 0x0a,
+     0xac, 0x0e, 0x0a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+     0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x72,
+     0x69, 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, 0xde, 0x0d, 0x0a, 0x14, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x12, 0x47, 0x0a, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75,
+     0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61,
+     0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53,
+     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x52, 0x07, 0x73, 0x74, 0x61, 0x72,
+     0x74, 0x75, 0x70, 0x1a, 0xe0, 0x01, 0x0a, 0x12, 0x54, 0x61, 0x73, 0x6b,
+     0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f,
+     0x77, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e,
+     0x67, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x0c, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x44,
+     0x75, 0x72, 0x4e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x72, 0x75, 0x6e, 0x6e,
+     0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18,
+     0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x72, 0x75, 0x6e, 0x6e, 0x61,
+     0x62, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x4e, 0x73, 0x12, 0x3f, 0x0a, 0x1c,
+     0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74, 0x69,
+     0x62, 0x6c, 0x65, 0x5f, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5f, 0x64, 0x75,
+     0x72, 0x5f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x19,
+     0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74, 0x69,
+     0x62, 0x6c, 0x65, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x44, 0x75, 0x72, 0x4e,
+     0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75,
+     0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x6c, 0x65, 0x65, 0x70,
+     0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
+     0x03, 0x52, 0x17, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74,
+     0x69, 0x62, 0x6c, 0x65, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x44, 0x75, 0x72,
+     0x4e, 0x73, 0x1a, 0x1e, 0x0a, 0x05, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x12,
+     0x15, 0x0a, 0x06, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x75, 0x72, 0x4e, 0x73, 0x1a, 0xbb,
+     0x08, 0x0a, 0x0c, 0x54, 0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72,
+     0x61, 0x6d, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x75, 0x72, 0x5f, 0x6e,
+     0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x75, 0x72,
+     0x4e, 0x73, 0x12, 0x72, 0x0a, 0x19, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x74,
+     0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x74, 0x61, 0x73,
+     0x6b, 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, 0x41, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65,
+     0x74, 0x72, 0x69, 0x63, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61,
+     0x74, 0x65, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x52,
+     0x15, 0x6d, 0x61, 0x69, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x42,
+     0x79, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x41,
+     0x0a, 0x1d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x73, 0x70, 0x61, 0x77, 0x6e, 0x65,
+     0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
+     0x0d, 0x52, 0x1a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x65, 0x73, 0x53, 0x70, 0x61, 0x77, 0x6e, 0x65, 0x64,
+     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x5f, 0x0a, 0x15, 0x74, 0x69, 0x6d,
+     0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x6d,
+     0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
      0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
      0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
      0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74,
      0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x13, 0x74,
-     0x69, 0x6d, 0x65, 0x42, 0x69, 0x6e, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69,
-     0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x13, 0x74, 0x69,
+     0x69, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x4d,
+     0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x66, 0x0a, 0x19, 0x74, 0x69,
      0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f,
-     0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
-     0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x11, 0x74, 0x69,
-     0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x74,
-     0x61, 0x72, 0x74, 0x12, 0x5d, 0x0a, 0x14, 0x74, 0x69, 0x6d, 0x65, 0x5f,
-     0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x73,
-     0x75, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
-     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x12, 0x74, 0x69, 0x6d, 0x65,
-     0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x75,
-     0x6d, 0x65, 0x12, 0x5a, 0x0a, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x63,
-     0x68, 0x6f, 0x72, 0x65, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72,
-     0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72,
-     0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c,
-     0x69, 0x63, 0x65, 0x52, 0x11, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x68, 0x6f,
-     0x72, 0x65, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72, 0x12, 0x66,
-     0x0a, 0x19, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72,
-     0x65, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63,
-     0x65, 0x73, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
-     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65,
-     0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x66, 0x0a, 0x19, 0x74, 0x69,
-     0x6d, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74,
-     0x61, 0x72, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18,
-     0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x18,
+     0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66,
      0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
      0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74,
      0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69,
-     0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x75, 0x72, 0x69,
-     0x6e, 0x67, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x12, 0x4b, 0x0a, 0x23, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f,
-     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x61,
-     0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x70, 0x75, 0x5f,
-     0x72, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52,
-     0x1e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
-     0x73, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x43,
-     0x70, 0x75, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x1a, 0xbb, 0x02, 0x0a, 0x07,
-     0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x73,
-     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
-     0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70,
-     0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
-     0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
-     0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d,
-     0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-     0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
-     0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65,
-     0x12, 0x2c, 0x0a, 0x12, 0x7a, 0x79, 0x67, 0x6f, 0x74, 0x65, 0x5f, 0x6e,
-     0x65, 0x77, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x04,
-     0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x7a, 0x79, 0x67, 0x6f, 0x74, 0x65,
-     0x4e, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x43,
-     0x0a, 0x1e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x68,
-     0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01,
-     0x28, 0x0d, 0x52, 0x1b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79,
-     0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x0e, 0x74,
-     0x6f, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d,
-     0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61,
-     0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54,
-     0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
-     0x0c, 0x74, 0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
-     0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xb7, 0x07, 0x0a, 0x3c, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70,
-     0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73,
-     0x69, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
+     0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69,
+     0x76, 0x69, 0x74, 0x79, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x4d, 0x61,
+     0x69, 0x6e, 0x12, 0x5f, 0x0a, 0x15, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x62,
+     0x69, 0x6e, 0x64, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74,
+     0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e,
      0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x22, 0xe1, 0x06, 0x0a, 0x14, 0x48, 0x65, 0x61, 0x70,
-     0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
-     0x69, 0x74, 0x65, 0x73, 0x12, 0x5a, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74,
-     0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01,
-     0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48,
-     0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61,
-     0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x73, 0x74,
-     0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x69,
-     0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73,
-     0x1a, 0x3e, 0x0a, 0x05, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a,
-     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
-     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x70,
-     0x70, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
-     0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67,
-     0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x8e, 0x01, 0x0a, 0x08, 0x43, 0x6f, 0x75,
-     0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74,
-     0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75,
-     0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
-     0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
-     0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12,
-     0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x63, 0x6f, 0x75,
-     0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65,
-     0x6c, 0x74, 0x61, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b,
-     0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18,
-     0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x74, 0x61,
-     0x42, 0x79, 0x74, 0x65, 0x73, 0x1a, 0xa6, 0x02, 0x0a, 0x08, 0x43, 0x61,
-     0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61,
-     0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x68, 0x61,
-     0x73, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
-     0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
-     0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12,
-     0x41, 0x0a, 0x05, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
+     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
+     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x13, 0x74, 0x69, 0x6d, 0x65,
+     0x42, 0x69, 0x6e, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74,
+     0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x13, 0x74, 0x69, 0x6d, 0x65, 0x5f,
+     0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x74, 0x61,
+     0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74,
+     0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+     0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x11, 0x74, 0x69, 0x6d, 0x65, 0x41,
+     0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74,
+     0x12, 0x5d, 0x0a, 0x14, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74,
+     0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65,
+     0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72,
+     0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c,
+     0x69, 0x63, 0x65, 0x52, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x41, 0x63, 0x74,
+     0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x12,
+     0x5a, 0x0a, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x63, 0x68, 0x6f, 0x72,
+     0x65, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72, 0x18, 0x09, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
+     0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70,
+     0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65,
+     0x52, 0x11, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x68, 0x6f, 0x72, 0x65, 0x6f,
+     0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72, 0x12, 0x66, 0x0a, 0x19, 0x74,
+     0x69, 0x6d, 0x65, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x73,
+     0x74, 0x61, 0x72, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+     0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72,
+     0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c,
+     0x69, 0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x42, 0x65, 0x66,
+     0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x12, 0x66, 0x0a, 0x19, 0x74, 0x69, 0x6d, 0x65, 0x5f,
+     0x64, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74,
+     0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x0b, 0x20, 0x01,
      0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61,
-     0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c,
-     0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
-     0x05, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x4f, 0x0a, 0x0b, 0x73, 0x65,
-     0x6c, 0x66, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x18, 0x04, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65,
-     0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c,
-     0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74,
-     0x65, 0x72, 0x73, 0x52, 0x0a, 0x73, 0x65, 0x6c, 0x66, 0x41, 0x6c, 0x6c,
-     0x6f, 0x63, 0x73, 0x12, 0x51, 0x0a, 0x0c, 0x63, 0x68, 0x69, 0x6c, 0x64,
-     0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70,
-     0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
-     0x69, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
-     0x73, 0x52, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x41, 0x6c, 0x6c, 0x6f,
-     0x63, 0x73, 0x1a, 0xf2, 0x01, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61,
-     0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03,
-     0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x70,
-     0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
-     0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
-     0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d,
-     0x65, 0x12, 0x4c, 0x0a, 0x09, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74,
-     0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
+     0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52,
+     0x16, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x53,
+     0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12,
+     0x4b, 0x0a, 0x23, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f,
+     0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69,
+     0x76, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x72, 0x61, 0x74,
+     0x69, 0x6f, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x1e, 0x6f, 0x74,
+     0x68, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f,
+     0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x43, 0x70, 0x75, 0x52,
+     0x61, 0x74, 0x69, 0x6f, 0x1a, 0xbb, 0x02, 0x0a, 0x07, 0x53, 0x74, 0x61,
+     0x72, 0x74, 0x75, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72,
+     0x74, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
+     0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x49, 0x64, 0x12,
+     0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e,
+     0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70,
+     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21,
+     0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61,
+     0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72,
+     0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2c, 0x0a,
+     0x12, 0x7a, 0x79, 0x67, 0x6f, 0x74, 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x10, 0x7a, 0x79, 0x67, 0x6f, 0x74, 0x65, 0x4e, 0x65, 0x77,
+     0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x43, 0x0a, 0x1e, 0x61,
+     0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x68, 0x6f, 0x73, 0x74,
+     0x69, 0x6e, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
+     0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52,
+     0x1b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x48, 0x6f, 0x73,
+     0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43,
+     0x6f, 0x75, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x0e, 0x74, 0x6f, 0x5f, 0x66,
+     0x69, 0x72, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x05,
+     0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75,
+     0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54, 0x6f, 0x46, 0x69,
+     0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x0c, 0x74, 0x6f,
+     0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x42, 0x02,
+     0x48, 0x03, 0x0a, 0xfb, 0x01, 0x0a, 0x36, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+     0x69, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d,
+     0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xab, 0x01, 0x0a, 0x16, 0x41,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
+     0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12,
+     0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e,
+     0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70,
+     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28,
+     0x0a, 0x10, 0x61, 0x70, 0x6b, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
+     0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x0e, 0x61, 0x70, 0x6b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+     0x43, 0x6f, 0x64, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x62, 0x75,
+     0x67, 0x67, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08,
+     0x52, 0x0a, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x61, 0x62, 0x6c, 0x65,
+     0x42, 0x02, 0x48, 0x03, 0x0a, 0xb2, 0x08, 0x0a, 0x3c, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
+     0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70, 0x72,
+     0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69,
+     0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x1a, 0x36, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61,
+     0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa4,
+     0x07, 0x0a, 0x14, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69,
+     0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x12,
+     0x5a, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f,
+     0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
+     0x33, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72,
+     0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74,
+     0x65, 0x73, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53,
+     0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e,
+     0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x1a, 0x3e, 0x0a, 0x05, 0x46,
+     0x72, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+     0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+     0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x5f,
+     0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
+     0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x1a,
+     0x8e, 0x01, 0x0a, 0x08, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73,
+     0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f,
+     0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74,
+     0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a,
+     0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61,
+     0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65,
+     0x6c, 0x74, 0x61, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f,
+     0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x74, 0x61,
+     0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x0a, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x42, 0x79, 0x74, 0x65, 0x73,
+     0x1a, 0xa6, 0x02, 0x0a, 0x08, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74,
+     0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x1f, 0x0a,
+     0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65,
+     0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x41, 0x0a, 0x05, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66,
+     0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73,
+     0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x05, 0x66, 0x72, 0x61, 0x6d,
+     0x65, 0x12, 0x4f, 0x0a, 0x0b, 0x73, 0x65, 0x6c, 0x66, 0x5f, 0x61, 0x6c,
+     0x6c, 0x6f, 0x63, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e,
+     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f,
+     0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
+     0x73, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0a,
+     0x73, 0x65, 0x6c, 0x66, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x12, 0x51,
+     0x0a, 0x0c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x6f,
+     0x63, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70,
      0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
      0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69,
      0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e,
-     0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x52, 0x09, 0x63, 0x61,
-     0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x70,
-     0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
-     0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
-     0x52, 0x11, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x6c,
-     0x74, 0x61, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x70,
-     0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c,
-     0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03,
-     0x52, 0x11, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x6f, 0x74,
-     0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a,
-     0x8c, 0x02, 0x0a, 0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
-     0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 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,
-     0xc0, 0x01, 0x0a, 0x12, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
-     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x47,
-     0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01,
-     0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67,
-     0x65, 0x4c, 0x69, 0x73, 0x74, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67,
-     0x65, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x1a,
-     0x61, 0x0a, 0x07, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x21,
-     0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61,
-     0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61,
-     0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a,
-     0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03,
-     0x75, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69,
-     0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x03, 0x52, 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f,
-     0x64, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x80, 0x02, 0x0a, 0x39, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x75, 0x6e, 0x73, 0x79, 0x6d,
-     0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d,
-     0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x22, 0xad, 0x01, 0x0a, 0x12, 0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62,
-     0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
-     0x12, 0x41, 0x0a, 0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01,
-     0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x55,
-     0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46,
-     0x72, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
-     0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x54, 0x0a, 0x05, 0x46,
-     0x72, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75,
-     0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f,
-     0x64, 0x75, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c,
-     0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
-     0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61,
-     0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
-     0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x02, 0x48,
-     0x03, 0x0a, 0xa4, 0x03, 0x0a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0b, 0x63, 0x68,
+     0x69, 0x6c, 0x64, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x1a, 0xb5, 0x02,
+     0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74,
+     0x61, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x01,
+     0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a,
+     0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d,
+     0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f,
+     0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x41, 0x0a, 0x07,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 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, 0x41, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65,
+     0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x12, 0x4c, 0x0a, 0x09, 0x63, 0x61, 0x6c, 0x6c, 0x73,
+     0x69, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e,
+     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f,
+     0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
+     0x73, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x52, 0x09,
+     0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x12, 0x2e, 0x0a,
+     0x13, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x6c,
+     0x74, 0x61, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x44,
+     0x65, 0x6c, 0x74, 0x61, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x2e, 0x0a,
+     0x13, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x74,
+     0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54,
+     0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x02, 0x48,
+     0x03, 0x0a, 0x8c, 0x02, 0x0a, 0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
      0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
      0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f,
-     0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
-     0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x22, 0xd5, 0x02, 0x0a, 0x0d, 0x4a, 0x61, 0x76,
-     0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x53,
-     0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73,
-     0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c,
-     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61,
-     0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61,
-     0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x69, 0x6e,
-     0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x1a,
-     0x65, 0x0a, 0x06, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x0e, 0x0a,
-     0x02, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x74,
-     0x73, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69,
-     0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x68, 0x65,
-     0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65,
-     0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x70,
-     0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52,
-     0x11, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x48, 0x65,
-     0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x87, 0x01, 0x0a, 0x0d, 0x49,
-     0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73,
-     0x12, 0x12, 0x0a, 0x04, 0x75, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
-     0x28, 0x0d, 0x52, 0x04, 0x75, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c,
-     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
-     0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63,
-     0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x07, 0x73,
-     0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
-     0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x48,
-     0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x53, 0x61, 0x6d,
-     0x70, 0x6c, 0x65, 0x52, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73,
-     0x42, 0x02, 0x48, 0x03, 0x0a, 0xed, 0x10, 0x0a, 0x25, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
+     0x64, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69,
+     0x73, 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, 0xc0, 0x01, 0x0a, 0x12, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74,
+     0x12, 0x47, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73,
+     0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b,
+     0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x2e, 0x50, 0x61, 0x63, 0x6b,
+     0x61, 0x67, 0x65, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
+     0x73, 0x1a, 0x61, 0x0a, 0x07, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
+     0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f,
+     0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
+     0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
+     0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x65, 0x72,
+     0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+     0x43, 0x6f, 0x64, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x80, 0x02, 0x0a,
+     0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+     0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x75, 0x6e, 0x73,
+     0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
      0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x1a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x2f, 0x62, 0x61, 0x74, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74,
+     0x74, 0x6f, 0x73, 0x22, 0xad, 0x01, 0x0a, 0x12, 0x55, 0x6e, 0x73, 0x79,
+     0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x73, 0x12, 0x41, 0x0a, 0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73,
+     0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65,
+     0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x52, 0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x54, 0x0a,
+     0x05, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f,
+     0x64, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
+     0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x75,
+     0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+     0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x18, 0x0a,
+     0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42,
+     0x02, 0x48, 0x03, 0x0a, 0xfc, 0x03, 0x0a, 0x35, 0x70, 0x72, 0x6f, 0x74,
      0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
      0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x2f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
-     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f,
-     0x75, 0x6e, 0x61, 0x67, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x34, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x69, 0x64, 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61,
+     0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x36, 0x70, 0x72, 0x6f, 0x74,
      0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
      0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
      0x6f, 0x69, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
-     0x67, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x22, 0xf5, 0x02, 0x0a, 0x0d, 0x4a, 0x61, 0x76, 0x61, 0x48,
+     0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x53, 0x0a, 0x0e,
+     0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61,
+     0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53,
+     0x74, 0x61, 0x74, 0x73, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
+     0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x69, 0x6e, 0x73, 0x74,
+     0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x1a, 0x65, 0x0a,
+     0x06, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x74,
+     0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x74, 0x73, 0x12,
+     0x1b, 0x0a, 0x09, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x68, 0x65, 0x61, 0x70,
+     0x53, 0x69, 0x7a, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65, 0x61, 0x63,
+     0x68, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73,
+     0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x72,
+     0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x48, 0x65, 0x61, 0x70,
+     0x53, 0x69, 0x7a, 0x65, 0x1a, 0xa7, 0x01, 0x0a, 0x0d, 0x49, 0x6e, 0x73,
+     0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x12,
+     0x0a, 0x04, 0x75, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
+     0x52, 0x04, 0x75, 0x70, 0x69, 0x64, 0x12, 0x41, 0x0a, 0x07, 0x70, 0x72,
+     0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
+     0x27, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x61,
+     0x64, 0x61, 0x74, 0x61, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
+     0x73, 0x12, 0x3f, 0x0a, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73,
+     0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x4a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61,
+     0x74, 0x73, 0x2e, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x07, 0x73,
+     0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xe0,
+     0x0f, 0x0a, 0x25, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+     0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x31, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x62, 0x61, 0x74, 0x74, 0x5f,
+     0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x63, 0x70,
+     0x75, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+     0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
+     0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x75, 0x6e, 0x61, 0x67, 0x67, 0x5f,
+     0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
      0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
      0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
      0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x69, 0x6f,
@@ -782,7 +772,7 @@
      0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x78,
      0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x69, 0x64, 0x78, 0x12,
      0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x80, 0x09,
+     0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xa9, 0x08,
      0x0a, 0x0c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69,
      0x63, 0x73, 0x12, 0x48, 0x0a, 0x0c, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
      0x64, 0x5f, 0x62, 0x61, 0x74, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
@@ -817,69 +807,62 @@
      0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
      0x4c, 0x69, 0x73, 0x74, 0x52, 0x12, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
      0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74,
-     0x12, 0x5b, 0x0a, 0x16, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f,
-     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x77,
-     0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72,
-     0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x52,
-     0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63,
-     0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x12, 0x42, 0x0a,
-     0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x69, 0x6f, 0x6e,
-     0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x49, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6d, 0x6b, 0x18, 0x08, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d,
-     0x6b, 0x12, 0x4d, 0x0a, 0x10, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x5f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x07, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61,
-     0x69, 0x6c, 0x73, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x50, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0f,
-     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72,
-     0x74, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e,
+     0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f,
+     0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e,
      0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
-     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x52, 0x0e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61,
-     0x72, 0x74, 0x75, 0x70, 0x12, 0x5b, 0x0a, 0x16, 0x68, 0x65, 0x61, 0x70,
-     0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c,
-     0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b,
-     0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50,
-     0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69,
-     0x74, 0x65, 0x73, 0x52, 0x14, 0x68, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f,
-     0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
-     0x73, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x6d,
-     0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63,
-     0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x74,
-     0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
-     0x12, 0x54, 0x0a, 0x13, 0x75, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
-     0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18,
-     0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49,
+     0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e,
+     0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0b,
+     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6d, 0x6b, 0x18,
+     0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66,
      0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64,
-     0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x12, 0x75, 0x6e, 0x73, 0x79,
-     0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d,
-     0x65, 0x73, 0x12, 0x46, 0x0a, 0x0f, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68,
-     0x65, 0x61, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x11, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61,
-     0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52,
-     0x0d, 0x6a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61,
-     0x74, 0x73, 0x2a, 0x06, 0x08, 0xc2, 0x03, 0x10, 0xf4, 0x03, 0x2a, 0x06,
-     0x08, 0xf4, 0x03, 0x10, 0xe9, 0x07, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05,
-     0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x4a, 0x04, 0x08, 0x0e, 0x10, 0x0f,
-     0x42, 0x02, 0x48, 0x03}};
+     0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65,
+     0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x4c, 0x6d, 0x6b, 0x12, 0x4d, 0x0a, 0x10, 0x61, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x5f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73,
+     0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65,
+     0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x12,
+     0x4e, 0x0a, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x73,
+     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
+     0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+     0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74,
+     0x72, 0x69, 0x63, 0x52, 0x0e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x5b, 0x0a, 0x16, 0x68,
+     0x65, 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f,
+     0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x18, 0x10, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65,
+     0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c,
+     0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x52, 0x14, 0x68, 0x65, 0x61, 0x70,
+     0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
+     0x69, 0x74, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x63,
+     0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03,
+     0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54,
+     0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+     0x52, 0x0d, 0x74, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64,
+     0x61, 0x74, 0x61, 0x12, 0x54, 0x0a, 0x13, 0x75, 0x6e, 0x73, 0x79, 0x6d,
+     0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d,
+     0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69,
+     0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x12, 0x75,
+     0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46,
+     0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x46, 0x0a, 0x0f, 0x6a, 0x61, 0x76,
+     0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73,
+     0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x4a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61,
+     0x74, 0x73, 0x52, 0x0d, 0x6a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70,
+     0x53, 0x74, 0x61, 0x74, 0x73, 0x2a, 0x06, 0x08, 0xc2, 0x03, 0x10, 0xf4,
+     0x03, 0x2a, 0x06, 0x08, 0xf4, 0x03, 0x10, 0xe9, 0x07, 0x4a, 0x04, 0x08,
+     0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x0a, 0x10, 0x0b, 0x4a, 0x04, 0x08,
+     0x0d, 0x10, 0x0e, 0x4a, 0x04, 0x08, 0x0e, 0x10, 0x0f, 0x42, 0x02, 0x48,
+     0x03}};
 
 }  // namespace perfetto
 
diff --git a/src/trace_processor/raw_table.cc b/src/trace_processor/raw_table.cc
index b4c2969..2b049f8 100644
--- a/src/trace_processor/raw_table.cc
+++ b/src/trace_processor/raw_table.cc
@@ -19,6 +19,8 @@
 #include <inttypes.h>
 
 #include "perfetto/base/compiler.h"
+#include "perfetto/ext/base/string_utils.h"
+#include "src/trace_processor/gfp_flags.h"
 #include "src/trace_processor/sqlite/sqlite_utils.h"
 #include "src/trace_processor/variadic.h"
 
@@ -33,6 +35,21 @@
 namespace perfetto {
 namespace trace_processor {
 
+namespace {
+std::tuple<uint32_t, uint32_t> ParseKernelReleaseVersion(
+    base::StringView system_release) {
+  size_t first_dot_pos = system_release.find(".");
+  size_t second_dot_pos = system_release.find(".", first_dot_pos + 1);
+  auto major_version = base::StringToUInt32(
+      system_release.substr(0, first_dot_pos).ToStdString());
+  auto minor_version = base::StringToUInt32(
+      system_release
+          .substr(first_dot_pos + 1, second_dot_pos - (first_dot_pos + 1))
+          .ToStdString());
+  return std::make_tuple(major_version.value(), minor_version.value());
+}
+}  // namespace
+
 RawTable::RawTable(sqlite3* db, const TraceStorage* storage)
     : storage_(storage) {
 #if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
@@ -83,6 +100,27 @@
 }
 
 #if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
+bool RawTable::ParseGfpFlags(Variadic value, base::StringWriter* writer) {
+  if (!storage_->metadata().MetadataExists(metadata::KeyIDs::system_name) ||
+      !storage_->metadata().MetadataExists(metadata::KeyIDs::system_release)) {
+    return false;
+  }
+
+  const Variadic& name =
+      storage_->metadata().GetScalarMetadata(metadata::KeyIDs::system_name);
+  base::StringView system_name = storage_->GetString(name.string_value);
+  if (system_name != "Linux")
+    return false;
+
+  const Variadic& release =
+      storage_->metadata().GetScalarMetadata(metadata::KeyIDs::system_release);
+  base::StringView system_release = storage_->GetString(release.string_value);
+  auto version = ParseKernelReleaseVersion(system_release);
+
+  WriteGfpFlag(value.uint_value, version, writer);
+  return true;
+}
+
 void RawTable::FormatSystraceArgs(NullTermStringView event_name,
                                   ArgSetId arg_set_id,
                                   base::StringWriter* writer) {
@@ -131,12 +169,17 @@
     uint32_t arg_row = start_row + arg_idx;
     const auto& args = storage_->args();
     const auto& key = storage_->GetString(args.keys()[arg_row]);
-    const auto& value = args.arg_values()[arg_row];
 
     writer->AppendChar(' ');
     writer->AppendString(key.c_str(), key.size());
     writer->AppendChar('=');
-    value_fn(value);
+
+    if (key == "gfp_flags" &&
+        ParseGfpFlags(args.arg_values()[arg_row], writer)) {
+      return;
+    }
+
+    value_fn(args.arg_values()[arg_row]);
   };
 
   if (event_name == "sched_switch") {
diff --git a/src/trace_processor/raw_table.h b/src/trace_processor/raw_table.h
index 690c0ac..480188c 100644
--- a/src/trace_processor/raw_table.h
+++ b/src/trace_processor/raw_table.h
@@ -41,6 +41,7 @@
                           ArgSetId arg_set_id,
                           base::StringWriter* writer);
   void ToSystrace(sqlite3_context* ctx, int argc, sqlite3_value** argv);
+  bool ParseGfpFlags(Variadic value, base::StringWriter* writer);
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
 
   const TraceStorage* const storage_;
diff --git a/src/trace_processor/span_join_operator_table.cc b/src/trace_processor/span_join_operator_table.cc
index 6067483..a786ba7 100644
--- a/src/trace_processor/span_join_operator_table.cc
+++ b/src/trace_processor/span_join_operator_table.cc
@@ -318,10 +318,14 @@
     res = next_stepped_->StepToPartition(step_now->partition());
     if (PERFETTO_UNLIKELY(res.is_err()))
       return res.err_code;
+  } else {
+    res = next_stepped_->Step();
+    if (PERFETTO_UNLIKELY(res.is_err()))
+      return res.err_code;
   }
 
   // Otherwise, find an overlapping span.
-  return Next();
+  return FindOverlappingSpan();
 }
 
 bool SpanJoinOperatorTable::Cursor::IsOverlappingSpan() {
@@ -329,10 +333,19 @@
     return false;
   } else if (t1_.partition() != t2_.partition()) {
     return false;
-  } else if (t1_.ts_end() <= t2_.ts_start() || t2_.ts_end() <= t1_.ts_start()) {
-    return false;
   }
-  return true;
+
+  // We consider all slices to be [start, end) - that is the range of
+  // timestamps has an open interval at the start but a closed interval
+  // at the end. (with the exception of dur == -1 which we treat as if
+  // end == start for the purpose of this function).
+  int64_t t1_start = t1_.ts_start();
+  int64_t t1_end = t1_.ts_end() - t1_start == -1 ? t1_start : t1_.ts_end();
+  int64_t t2_start = t2_.ts_start();
+  int64_t t2_end = t2_.ts_end() - t2_start == -1 ? t2_start : t2_.ts_end();
+  return (t1_start == t2_start && t1_.IsRealSlice() && t2_.IsRealSlice()) ||
+         (t1_start >= t2_start && t1_start < t2_end) ||
+         (t2_start >= t1_start && t2_start < t1_end);
 }
 
 int SpanJoinOperatorTable::Cursor::Next() {
@@ -340,7 +353,10 @@
   auto res = next_stepped_->Step();
   if (res.is_err())
     return res.err_code;
+  return FindOverlappingSpan();
+}
 
+int SpanJoinOperatorTable::Cursor::FindOverlappingSpan() {
   while (true) {
     if (t1_.Eof() || t2_.Eof()) {
       if (table_->partitioning_ != PartitioningType::kMixedPartitioning)
@@ -351,7 +367,7 @@
       if (partitioned->Eof())
         return SQLITE_OK;
 
-      res = partitioned->StepToNextPartition();
+      auto res = partitioned->StepToNextPartition();
       if (PERFETTO_UNLIKELY(res.is_err()))
         return res.err_code;
       else if (PERFETTO_UNLIKELY(res.is_eof()))
@@ -365,7 +381,7 @@
     }
 
     int64_t partition = std::max(t1_.partition(), t2_.partition());
-    res = t1_.StepToPartition(partition);
+    auto res = t1_.StepToPartition(partition);
     if (PERFETTO_UNLIKELY(res.is_err()))
       return res.err_code;
     else if (PERFETTO_UNLIKELY(res.is_eof()))
@@ -445,7 +461,6 @@
   } else if (N == Column::kDuration) {
     auto max_start = std::max(t1_.ts_start(), t2_.ts_start());
     auto min_end = std::min(t1_.ts_end(), t2_.ts_end());
-    PERFETTO_DCHECK(min_end > max_start);
     auto dur = min_end - max_start;
     sqlite3_result_int64(context, static_cast<sqlite3_int64>(dur));
   } else if (N == Column::kPartition &&
@@ -543,7 +558,7 @@
       // to do so. Otherwise, just emit the underlying slice.
       if (defn_->emit_shadow_slices()) {
         mode_ = Mode::kShadowSlice;
-        ts_start_ = ts_end_;
+        ts_start_ = ts_end_ - ts_start_ == -1 ? ts_start_ : ts_end_;
         ts_end_ = !defn_->IsPartitioned() || partition_ == CursorPartition()
                       ? CursorTs()
                       : std::numeric_limits<int64_t>::max();
@@ -561,12 +576,12 @@
 
       // Close off the remainder of this partition with a shadow slice.
       mode_ = Mode::kShadowSlice;
-      ts_start_ = ts_end_;
+      ts_start_ = ts_end_ - ts_start_ == -1 ? ts_start_ : ts_end_;
       ts_end_ = std::numeric_limits<int64_t>::max();
     } else {
       return StepRet(StepRet::Code::kError, res);
     }
-  } while (ts_start_ == ts_end_);
+  } while (ts_start_ == ts_end_ && !IsRealSlice());
 
   return StepRet(StepRet::Code::kRow);
 }
@@ -604,6 +619,9 @@
     int res = PrepareRawStmt();
     if (res != SQLITE_OK)
       return StepRet(StepRet::Code::kError, res);
+    auto ret = Step();
+    if (!ret.is_row())
+      return ret;
     partition_ = target_partition;
   }
   return StepRet(StepRet::Code::kRow);
@@ -613,7 +631,8 @@
     int64_t timestamp) {
   PERFETTO_DCHECK(!Eof());
   auto partition = partition_;
-  while (partition_ == partition && ts_end_ <= timestamp) {
+  while (partition_ == partition && ts_start_ < timestamp &&
+         ts_end_ <= timestamp) {
     auto res = Step();
     if (!res.is_row())
       return res;
diff --git a/src/trace_processor/span_join_operator_table.h b/src/trace_processor/span_join_operator_table.h
index dfc4439..1a1e9a1 100644
--- a/src/trace_processor/span_join_operator_table.h
+++ b/src/trace_processor/span_join_operator_table.h
@@ -241,6 +241,8 @@
     Cursor(Cursor&&) noexcept = default;
     Cursor& operator=(Cursor&&) = default;
 
+    int FindOverlappingSpan();
+
     bool IsOverlappingSpan();
     Query::StepRet StepUntilRealSlice();
 
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 2d40985..fbae94b 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -754,6 +754,15 @@
       return TraceStorage::CreateRowId(kMetadataTable, index);
     }
 
+    const Variadic& GetScalarMetadata(metadata::KeyIDs key) const {
+      PERFETTO_DCHECK(scalar_indices.count(key) == 1);
+      return values_.at(scalar_indices.at(key));
+    }
+
+    bool MetadataExists(metadata::KeyIDs key) const {
+      return scalar_indices.count(key) >= 1;
+    }
+
     void OverwriteMetadata(uint32_t index, Variadic value) {
       PERFETTO_DCHECK(index < values_.size());
       values_[index] = value;
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer.cc b/src/traced/probes/ftrace/ftrace_config_muxer.cc
index cc97bf2..f0cf926 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer.cc
+++ b/src/traced/probes/ftrace/ftrace_config_muxer.cc
@@ -148,9 +148,11 @@
         continue;
       }
 
+      // Note: sched_wakeup intentionally removed (diverging from atrace), as it
+      // is high-volume, but mostly redundant when sched_waking is also enabled.
+      // The event can still be enabled explicitly when necessary.
       if (category == "sched") {
         events.insert(GroupAndName("sched", "sched_switch"));
-        events.insert(GroupAndName("sched", "sched_wakeup"));
         events.insert(GroupAndName("sched", "sched_waking"));
         events.insert(GroupAndName("sched", "sched_blocked_reason"));
         events.insert(GroupAndName("sched", "sched_cpu_hotplug"));
diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn
index 844da88..e0984c8 100644
--- a/src/tracing/BUILD.gn
+++ b/src/tracing/BUILD.gn
@@ -22,9 +22,6 @@
   public_deps = [
     ":common",
     "../../include/perfetto/ext/tracing/core",
-    "../../protos/perfetto/common:lite",
-    "../../protos/perfetto/trace:minimal_lite",
-    "../../protos/perfetto/trace:trusted_lite",
     "../../protos/perfetto/trace:zero",
     "../../protos/perfetto/trace/interned_data:zero",
     "../../protos/perfetto/trace/track_event:zero",
@@ -32,7 +29,8 @@
   deps = [
     "../../gn:default_deps",
     "../../include/perfetto/tracing",
-    "../../protos/perfetto/config:lite",
+    "../../protos/perfetto/common:zero",
+    "../../protos/perfetto/config:zero",
     "../../protos/perfetto/trace/perfetto:zero",  # For MetatraceWriter.
     "../base",
     "../protozero",
@@ -61,6 +59,7 @@
     "core/tracing_service_impl.h",
     "core/virtual_destructors.cc",
   ]
+  assert_no_deps = [ "//gn:protobuf_lite" ]
 }
 
 # TODO(primiano): Remove this target as soon as chromium's
@@ -252,7 +251,7 @@
   deps = [
     ":common",
     "../../include/perfetto/tracing/core",
-    "../../protos/perfetto/config:lite",
+    "../../protos/perfetto/config:cpp",
     "../base",
     "../tracing",
   ]
@@ -262,6 +261,7 @@
   ]
   sources = [
     "data_source.cc",
+    "event_context.cc",
     "internal/in_process_tracing_backend.cc",
     "internal/in_process_tracing_backend.h",
     "internal/tracing_muxer_impl.cc",
@@ -270,7 +270,6 @@
     "platform.cc",
     "tracing.cc",
     "track_event_category_registry.cc",
-    "track_event_context.cc",
     "virtual_destructors.cc",
   ]
 
diff --git a/src/tracing/api_integrationtest.cc b/src/tracing/api_integrationtest.cc
index 44fa477..9022be2 100644
--- a/src/tracing/api_integrationtest.cc
+++ b/src/tracing/api_integrationtest.cc
@@ -777,11 +777,11 @@
 
   auto random_value = random();
   TRACE_EVENT_BEGIN("foo", "EventWithTypedArg",
-                    [random_value](perfetto::TrackEventContext ctx) {
-                      auto* log = ctx.track_event()->set_log_message();
+                    [random_value](perfetto::EventContext ctx) {
+                      auto* log = ctx.event()->set_log_message();
                       log->set_source_location_iid(1);
                       log->set_body_iid(2);
-                      auto* dbg = ctx.track_event()->add_debug_annotations();
+                      auto* dbg = ctx.event()->add_debug_annotations();
                       dbg->set_name("random");
                       dbg->set_int_value(random_value);
                     });
@@ -855,45 +855,38 @@
 
   size_t body_iid;
   InternedLogMessageBody::commit_count = 0;
-  TRACE_EVENT_BEGIN(
-      "foo", "EventWithState", [&](perfetto::TrackEventContext ctx) {
-        EXPECT_EQ(0, InternedLogMessageBody::commit_count);
-        body_iid = InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
-        auto log = ctx.track_event()->set_log_message();
-        log->set_body_iid(body_iid);
-        EXPECT_EQ(1, InternedLogMessageBody::commit_count);
+  TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
+    EXPECT_EQ(0, InternedLogMessageBody::commit_count);
+    body_iid = InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
+    auto log = ctx.event()->set_log_message();
+    log->set_body_iid(body_iid);
+    EXPECT_EQ(1, InternedLogMessageBody::commit_count);
 
-        auto body_iid2 =
-            InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
-        EXPECT_EQ(body_iid, body_iid2);
-        EXPECT_EQ(1, InternedLogMessageBody::commit_count);
-      });
+    auto body_iid2 = InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
+    EXPECT_EQ(body_iid, body_iid2);
+    EXPECT_EQ(1, InternedLogMessageBody::commit_count);
+  });
   TRACE_EVENT_END("foo");
 
-  TRACE_EVENT_BEGIN(
-      "foo", "EventWithState", [&](perfetto::TrackEventContext ctx) {
-        // Check that very large amounts of interned data works.
-        auto log = ctx.track_event()->set_log_message();
-        log->set_body_iid(
-            InternedLogMessageBody::Get(&ctx, large_message.str()));
-        EXPECT_EQ(2, InternedLogMessageBody::commit_count);
-      });
+  TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
+    // Check that very large amounts of interned data works.
+    auto log = ctx.event()->set_log_message();
+    log->set_body_iid(InternedLogMessageBody::Get(&ctx, large_message.str()));
+    EXPECT_EQ(2, InternedLogMessageBody::commit_count);
+  });
   TRACE_EVENT_END("foo");
 
   // Make sure interned data persists across trace points.
-  TRACE_EVENT_BEGIN(
-      "foo", "EventWithState", [&](perfetto::TrackEventContext ctx) {
-        auto body_iid2 =
-            InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
-        EXPECT_EQ(body_iid, body_iid2);
+  TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
+    auto body_iid2 = InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
+    EXPECT_EQ(body_iid, body_iid2);
 
-        auto body_iid3 =
-            InternedLogMessageBody::Get(&ctx, "I knew him, Horatio");
-        EXPECT_NE(body_iid, body_iid3);
-        auto log = ctx.track_event()->set_log_message();
-        log->set_body_iid(body_iid3);
-        EXPECT_EQ(3, InternedLogMessageBody::commit_count);
-      });
+    auto body_iid3 = InternedLogMessageBody::Get(&ctx, "I knew him, Horatio");
+    EXPECT_NE(body_iid, body_iid3);
+    auto log = ctx.event()->set_log_message();
+    log->set_body_iid(body_iid3);
+    EXPECT_EQ(3, InternedLogMessageBody::commit_count);
+  });
   TRACE_EVENT_END("foo");
 
   tracing_session->get()->StopBlocking();
@@ -932,20 +925,18 @@
   tracing_session->get()->StartBlocking();
 
   size_t body_iid;
-  TRACE_EVENT_BEGIN(
-      "foo", "EventWithState", [&](perfetto::TrackEventContext ctx) {
-        body_iid = InternedLogMessageBodySmall::Get(&ctx, "This above all:");
-        auto log = ctx.track_event()->set_log_message();
-        log->set_body_iid(body_iid);
+  TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
+    body_iid = InternedLogMessageBodySmall::Get(&ctx, "This above all:");
+    auto log = ctx.event()->set_log_message();
+    log->set_body_iid(body_iid);
 
-        auto body_iid2 =
-            InternedLogMessageBodySmall::Get(&ctx, "This above all:");
-        EXPECT_EQ(body_iid, body_iid2);
+    auto body_iid2 = InternedLogMessageBodySmall::Get(&ctx, "This above all:");
+    EXPECT_EQ(body_iid, body_iid2);
 
-        auto body_iid3 =
-            InternedLogMessageBodySmall::Get(&ctx, "to thine own self be true");
-        EXPECT_NE(body_iid, body_iid3);
-      });
+    auto body_iid3 =
+        InternedLogMessageBodySmall::Get(&ctx, "to thine own self be true");
+    EXPECT_NE(body_iid, body_iid3);
+  });
   TRACE_EVENT_END("foo");
 
   tracing_session->get()->StopBlocking();
@@ -983,11 +974,11 @@
 
   size_t body_iid;
   TRACE_EVENT_BEGIN(
-      "foo", "EventWithState", [&](perfetto::TrackEventContext ctx) {
+      "foo", "EventWithState", [&](perfetto::EventContext ctx) {
         // Test using a dynamically created interned value.
         body_iid = InternedLogMessageBodyHashed::Get(
             &ctx, std::string("Though this ") + "be madness,");
-        auto log = ctx.track_event()->set_log_message();
+        auto log = ctx.event()->set_log_message();
         log->set_body_iid(body_iid);
 
         auto body_iid2 =
@@ -1037,23 +1028,21 @@
   auto* tracing_session = NewTrace(cfg);
   tracing_session->get()->StartBlocking();
 
-  TRACE_EVENT_BEGIN(
-      "foo", "EventWithState", [&](perfetto::TrackEventContext ctx) {
-        const SourceLocation location{"file.cc", "SomeFunction", 123};
-        auto location_iid = InternedSourceLocation::Get(&ctx, location);
-        auto body_iid =
-            InternedLogMessageBody::Get(&ctx, "To be, or not to be");
-        auto log = ctx.track_event()->set_log_message();
-        log->set_source_location_iid(location_iid);
-        log->set_body_iid(body_iid);
+  TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
+    const SourceLocation location{"file.cc", "SomeFunction", 123};
+    auto location_iid = InternedSourceLocation::Get(&ctx, location);
+    auto body_iid = InternedLogMessageBody::Get(&ctx, "To be, or not to be");
+    auto log = ctx.event()->set_log_message();
+    log->set_source_location_iid(location_iid);
+    log->set_body_iid(body_iid);
 
-        auto location_iid2 = InternedSourceLocation::Get(&ctx, location);
-        EXPECT_EQ(location_iid, location_iid2);
+    auto location_iid2 = InternedSourceLocation::Get(&ctx, location);
+    EXPECT_EQ(location_iid, location_iid2);
 
-        const SourceLocation location2{"file.cc", "SomeFunction", 456};
-        auto location_iid3 = InternedSourceLocation::Get(&ctx, location2);
-        EXPECT_NE(location_iid, location_iid3);
-      });
+    const SourceLocation location2{"file.cc", "SomeFunction", 456};
+    auto location_iid3 = InternedSourceLocation::Get(&ctx, location2);
+    EXPECT_NE(location_iid, location_iid3);
+  });
   TRACE_EVENT_END("foo");
 
   tracing_session->get()->StopBlocking();
@@ -1077,10 +1066,9 @@
 
   {
     uint64_t arg = 123;
-    TRACE_EVENT("test", "TestEventWithArgs",
-                [&](perfetto::TrackEventContext ctx) {
-                  ctx.track_event()->set_log_message()->set_body_iid(arg);
-                });
+    TRACE_EVENT("test", "TestEventWithArgs", [&](perfetto::EventContext ctx) {
+      ctx.event()->set_log_message()->set_body_iid(arg);
+    });
   }
 
   {
diff --git a/src/tracing/core/trace_packet_unittest.cc b/src/tracing/core/trace_packet_unittest.cc
index 0469ae8..c8fb8f9 100644
--- a/src/tracing/core/trace_packet_unittest.cc
+++ b/src/tracing/core/trace_packet_unittest.cc
@@ -20,36 +20,11 @@
 
 #include "protos/perfetto/trace/trace.pb.h"
 #include "protos/perfetto/trace/trace_packet.pb.h"
-#include "protos/perfetto/trace/trusted_packet.pb.h"
 #include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 namespace {
 
-static_assert(static_cast<int>(TracePacket::kPacketFieldNumber) ==
-                  static_cast<int>(protos::Trace::kPacketFieldNumber),
-              "packet field id mismatch");
-
-static_assert(
-    static_cast<int>(protos::TracePacket::kTrustedUidFieldNumber) ==
-        static_cast<int>(protos::TrustedPacket::kTrustedUidFieldNumber),
-    "trusted_uid field id mismatch");
-
-static_assert(
-    static_cast<int>(protos::TracePacket::kTraceConfigFieldNumber) ==
-        static_cast<int>(protos::TrustedPacket::kTraceConfigFieldNumber),
-    "trace_config field id mismatch");
-
-static_assert(
-    static_cast<int>(protos::TracePacket::kTraceStatsFieldNumber) ==
-        static_cast<int>(protos::TrustedPacket::kTraceStatsFieldNumber),
-    "trace_stats field id mismatch");
-
-static_assert(
-    static_cast<int>(protos::TracePacket::kClockSnapshotFieldNumber) ==
-        static_cast<int>(protos::TrustedPacket::kClockSnapshotFieldNumber),
-    "clock_snapshot field id mismatch");
-
 TEST(TracePacketTest, Simple) {
   protos::TracePacket proto;
   proto.mutable_for_testing()->set_str("string field");
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index 26331d7..0e3b424 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -49,15 +49,20 @@
 #include "perfetto/ext/tracing/core/shared_memory_abi.h"
 #include "perfetto/ext/tracing/core/trace_packet.h"
 #include "perfetto/ext/tracing/core/trace_writer.h"
+#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "perfetto/protozero/static_buffer.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
 #include "perfetto/tracing/core/tracing_service_state.h"
 #include "src/tracing/core/packet_stream_validator.h"
 #include "src/tracing/core/shared_memory_arbiter_impl.h"
 #include "src/tracing/core/trace_buffer.h"
 
-#include "protos/perfetto/trace/clock_snapshot.pb.h"
-#include "protos/perfetto/trace/system_info.pb.h"
-#include "protos/perfetto/trace/trusted_packet.pb.h"
+#include "protos/perfetto/common/trace_stats.pbzero.h"
+#include "protos/perfetto/config/trace_config.pbzero.h"
+#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
+#include "protos/perfetto/trace/system_info.pbzero.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "protos/perfetto/trace/trigger.pbzero.h"
 
 // General note: this class must assume that Producers are malicious and will
 // try to crash / exploit this class. We can trust pointers because they come
@@ -132,6 +137,14 @@
   return static_cast<int32_t>(acc);
 }
 
+void SerializeAndAppendPacket(std::vector<TracePacket>* packets,
+                              std::vector<uint8_t> packet) {
+  Slice slice = Slice::Allocate(packet.size());
+  memcpy(slice.own_data(), packet.data(), packet.size());
+  packets->emplace_back();
+  packets->back().AddSlice(std::move(slice));
+}
+
 }  // namespace
 
 // These constants instead are defined in the header because are used by tests.
@@ -1540,21 +1553,18 @@
       // truncated packets are also rejected, so the producer can't give us a
       // partial packet (e.g., a truncated string) which only becomes valid when
       // the trusted data is appended here.
-      protos::TrustedPacket trusted_packet;
-      trusted_packet.set_trusted_uid(
+      Slice slice = Slice::Allocate(32);
+      protozero::StaticBuffered<protos::pbzero::TracePacket> trusted_packet(
+          slice.own_data(), slice.size);
+      trusted_packet->set_trusted_uid(
           static_cast<int32_t>(sequence_properties.producer_uid_trusted));
-      trusted_packet.set_trusted_packet_sequence_id(
+      trusted_packet->set_trusted_packet_sequence_id(
           tracing_session->GetPacketSequenceID(
               sequence_properties.producer_id_trusted,
               sequence_properties.writer_id));
       if (previous_packet_dropped)
-        trusted_packet.set_previous_packet_dropped(previous_packet_dropped);
-      static constexpr size_t kTrustedBufSize = 16;
-      Slice slice = Slice::Allocate(kTrustedBufSize);
-      PERFETTO_CHECK(
-          trusted_packet.SerializeToArray(slice.own_data(), kTrustedBufSize));
-      slice.size = static_cast<size_t>(trusted_packet.GetCachedSize());
-      PERFETTO_DCHECK(slice.size > 0 && slice.size <= kTrustedBufSize);
+        trusted_packet->set_previous_packet_dropped(previous_packet_dropped);
+      slice.size = trusted_packet.Finalize();
       packet.AddSlice(std::move(slice));
 
       // Append the packet (inclusive of the trusted uid) to |packets|.
@@ -2160,23 +2170,17 @@
   // The sync marks are used to tokenize large traces efficiently.
   // See description in trace_packet.proto.
   if (sync_marker_packet_size_ == 0) {
-    // Serialize the marker and the uid separately to guarantee that the marker
-    // is serialzied at the end and is adjacent to the start of the next packet.
-    int size_left = static_cast<int>(sizeof(sync_marker_packet_));
-    uint8_t* dst = &sync_marker_packet_[0];
-    protos::TrustedPacket packet;
-    packet.set_trusted_uid(static_cast<int32_t>(uid_));
-    packet.set_trusted_packet_sequence_id(kServicePacketSequenceID);
-    PERFETTO_CHECK(packet.SerializeToArray(dst, size_left));
-    size_left -= packet.ByteSize();
-    sync_marker_packet_size_ += static_cast<size_t>(packet.ByteSize());
-    dst += sync_marker_packet_size_;
+    // The marker ABI expects that the marker is written after the uid.
+    // Protozero guarantees that fields are written in the same order of the
+    // calls. The ResynchronizeTraceStreamUsingSyncMarker test verifies the ABI.
+    protozero::StaticBuffered<protos::pbzero::TracePacket> packet(
+        &sync_marker_packet_[0], sizeof(sync_marker_packet_));
+    packet->set_trusted_uid(static_cast<int32_t>(uid_));
+    packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
 
-    packet.Clear();
-    packet.set_synchronization_marker(kSyncMarker, sizeof(kSyncMarker));
-    PERFETTO_CHECK(packet.SerializeToArray(dst, size_left));
-    sync_marker_packet_size_ += static_cast<size_t>(packet.ByteSize());
-    PERFETTO_CHECK(sync_marker_packet_size_ <= sizeof(sync_marker_packet_));
+    // Keep this last.
+    packet->set_synchronization_marker(kSyncMarker, sizeof(kSyncMarker));
+    sync_marker_packet_size_ = packet.Finalize();
   }
   packets->emplace_back();
   packets->back().AddSlice(&sync_marker_packet_[0], sync_marker_packet_size_);
@@ -2184,33 +2188,36 @@
 
 void TracingServiceImpl::SnapshotClocks(std::vector<TracePacket>* packets,
                                         bool set_root_timestamp) {
-  protos::TrustedPacket packet;
-  protos::ClockSnapshot* clock_snapshot = packet.mutable_clock_snapshot();
+  protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+  uint64_t root_timestamp_ns = 0;
+  auto* clock_snapshot = packet->set_clock_snapshot();
 
 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) && \
     !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   struct {
     clockid_t id;
-    protos::ClockSnapshot::Clock::BuiltinClocks type;
+    protos::pbzero::ClockSnapshot::Clock::BuiltinClocks type;
     struct timespec ts;
   } clocks[] = {
-      {CLOCK_BOOTTIME, protos::ClockSnapshot::Clock::BOOTTIME, {0, 0}},
+      {CLOCK_BOOTTIME, protos::pbzero::ClockSnapshot::Clock::BOOTTIME, {0, 0}},
       {CLOCK_REALTIME_COARSE,
-       protos::ClockSnapshot::Clock::REALTIME_COARSE,
+       protos::pbzero::ClockSnapshot::Clock::REALTIME_COARSE,
        {0, 0}},
       {CLOCK_MONOTONIC_COARSE,
-       protos::ClockSnapshot::Clock::MONOTONIC_COARSE,
+       protos::pbzero::ClockSnapshot::Clock::MONOTONIC_COARSE,
        {0, 0}},
-      {CLOCK_REALTIME, protos::ClockSnapshot::Clock::REALTIME, {0, 0}},
-      {CLOCK_MONOTONIC, protos::ClockSnapshot::Clock::MONOTONIC, {0, 0}},
+      {CLOCK_REALTIME, protos::pbzero::ClockSnapshot::Clock::REALTIME, {0, 0}},
+      {CLOCK_MONOTONIC,
+       protos::pbzero::ClockSnapshot::Clock::MONOTONIC,
+       {0, 0}},
       {CLOCK_MONOTONIC_RAW,
-       protos::ClockSnapshot::Clock::MONOTONIC_RAW,
+       protos::pbzero::ClockSnapshot::Clock::MONOTONIC_RAW,
        {0, 0}},
       {CLOCK_PROCESS_CPUTIME_ID,
-       protos::ClockSnapshot::Clock::PROCESS_CPUTIME,
+       protos::pbzero::ClockSnapshot::Clock::PROCESS_CPUTIME,
        {0, 0}},
       {CLOCK_THREAD_CPUTIME_ID,
-       protos::ClockSnapshot::Clock::THREAD_CPUTIME,
+       protos::pbzero::ClockSnapshot::Clock::THREAD_CPUTIME,
        {0, 0}},
   };
   // First snapshot all the clocks as atomically as we can.
@@ -2220,11 +2227,11 @@
   }
   for (auto& clock : clocks) {
     if (set_root_timestamp &&
-        clock.type == protos::ClockSnapshot::Clock::BOOTTIME) {
-      packet.set_timestamp(
-          static_cast<uint64_t>(base::FromPosixTimespec(clock.ts).count()));
+        clock.type == protos::pbzero::ClockSnapshot::Clock::BOOTTIME) {
+      root_timestamp_ns =
+          static_cast<uint64_t>(base::FromPosixTimespec(clock.ts).count());
     }
-    protos::ClockSnapshot::Clock* c = clock_snapshot->add_clocks();
+    auto* c = clock_snapshot->add_clocks();
     c->set_clock_id(static_cast<uint32_t>(clock.type));
     c->set_timestamp(
         static_cast<uint64_t>(base::FromPosixTimespec(clock.ts).count()));
@@ -2232,32 +2239,27 @@
 #else   // !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
   auto wall_time_ns = static_cast<uint64_t>(base::GetWallTimeNs().count());
   if (set_root_timestamp)
-    packet.set_timestamp(wall_time_ns);
-  protos::ClockSnapshot::Clock* c = clock_snapshot->add_clocks();
-  c->set_clock_id(protos::ClockSnapshot::Clock::MONOTONIC);
+    root_timestamp_ns = wall_time_ns;
+  auto* c = clock_snapshot->add_clocks();
+  c->set_clock_id(protos::pbzero::ClockSnapshot::Clock::MONOTONIC);
   c->set_timestamp(wall_time_ns);
 #endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 
-  packet.set_trusted_uid(static_cast<int32_t>(uid_));
-  packet.set_trusted_packet_sequence_id(kServicePacketSequenceID);
-  Slice slice = Slice::Allocate(static_cast<size_t>(packet.ByteSize()));
-  PERFETTO_CHECK(packet.SerializeWithCachedSizesToArray(slice.own_data()));
-  packets->emplace_back();
-  packets->back().AddSlice(std::move(slice));
+  if (root_timestamp_ns)
+    packet->set_timestamp(root_timestamp_ns);
+  packet->set_trusted_uid(static_cast<int32_t>(uid_));
+  packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
+
+  SerializeAndAppendPacket(packets, packet.SerializeAsArray());
 }
 
 void TracingServiceImpl::SnapshotStats(TracingSession* tracing_session,
                                        std::vector<TracePacket>* packets) {
-  protos::TrustedPacket packet;
-  packet.set_trusted_uid(static_cast<int32_t>(uid_));
-  packet.set_trusted_packet_sequence_id(kServicePacketSequenceID);
-
-  protos::TraceStats* trace_stats = packet.mutable_trace_stats();
-  GetTraceStats(tracing_session).ToProto(trace_stats);
-  Slice slice = Slice::Allocate(static_cast<size_t>(packet.ByteSize()));
-  PERFETTO_CHECK(packet.SerializeWithCachedSizesToArray(slice.own_data()));
-  packets->emplace_back();
-  packets->back().AddSlice(std::move(slice));
+  protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+  packet->set_trusted_uid(static_cast<int32_t>(uid_));
+  packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
+  GetTraceStats(tracing_session).Serialize(packet->set_trace_stats());
+  SerializeAndAppendPacket(packets, packet.SerializeAsArray());
 }
 
 TraceStats TracingServiceImpl::GetTraceStats(TracingSession* tracing_session) {
@@ -2291,14 +2293,11 @@
   if (tracing_session->did_emit_config)
     return;
   tracing_session->did_emit_config = true;
-  protos::TrustedPacket packet;
-  tracing_session->config.ToProto(packet.mutable_trace_config());
-  packet.set_trusted_uid(static_cast<int32_t>(uid_));
-  packet.set_trusted_packet_sequence_id(kServicePacketSequenceID);
-  Slice slice = Slice::Allocate(static_cast<size_t>(packet.ByteSize()));
-  PERFETTO_CHECK(packet.SerializeWithCachedSizesToArray(slice.own_data()));
-  packets->emplace_back();
-  packets->back().AddSlice(std::move(slice));
+  protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+  packet->set_trusted_uid(static_cast<int32_t>(uid_));
+  packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
+  tracing_session->config.Serialize(packet->set_trace_config());
+  SerializeAndAppendPacket(packets, packet.SerializeAsArray());
 }
 
 void TracingServiceImpl::MaybeEmitSystemInfo(
@@ -2307,24 +2306,21 @@
   if (tracing_session->did_emit_system_info)
     return;
   tracing_session->did_emit_system_info = true;
-  protos::TrustedPacket packet;
+  protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  protos::SystemInfo* info = packet.mutable_system_info();
+  auto* info = packet->set_system_info();
   struct utsname uname_info;
   if (uname(&uname_info) == 0) {
-    protos::Utsname* utsname_info = info->mutable_utsname();
+    auto* utsname_info = info->set_utsname();
     utsname_info->set_sysname(uname_info.sysname);
     utsname_info->set_version(uname_info.version);
     utsname_info->set_machine(uname_info.machine);
     utsname_info->set_release(uname_info.release);
   }
 #endif
-  packet.set_trusted_uid(static_cast<int32_t>(uid_));
-  packet.set_trusted_packet_sequence_id(kServicePacketSequenceID);
-  Slice slice = Slice::Allocate(static_cast<size_t>(packet.ByteSize()));
-  PERFETTO_CHECK(packet.SerializeWithCachedSizesToArray(slice.own_data()));
-  packets->emplace_back();
-  packets->back().AddSlice(std::move(slice));
+  packet->set_trusted_uid(static_cast<int32_t>(uid_));
+  packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
+  SerializeAndAppendPacket(packets, packet.SerializeAsArray());
 }
 
 void TracingServiceImpl::MaybeEmitReceivedTriggers(
@@ -2335,20 +2331,16 @@
   for (size_t i = tracing_session->num_triggers_emitted_into_trace;
        i < tracing_session->received_triggers.size(); ++i) {
     const auto& info = tracing_session->received_triggers[i];
-    protos::TrustedPacket packet;
-
-    protos::Trigger* trigger = packet.mutable_trigger();
+    protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+    auto* trigger = packet->set_trigger();
     trigger->set_trigger_name(info.trigger_name);
     trigger->set_producer_name(info.producer_name);
     trigger->set_trusted_producer_uid(static_cast<int32_t>(info.producer_uid));
 
-    packet.set_timestamp(info.boot_time_ns);
-    packet.set_trusted_uid(static_cast<int32_t>(uid_));
-    packet.set_trusted_packet_sequence_id(kServicePacketSequenceID);
-    Slice slice = Slice::Allocate(static_cast<size_t>(packet.ByteSize()));
-    PERFETTO_CHECK(packet.SerializeWithCachedSizesToArray(slice.own_data()));
-    packets->emplace_back();
-    packets->back().AddSlice(std::move(slice));
+    packet->set_timestamp(info.boot_time_ns);
+    packet->set_trusted_uid(static_cast<int32_t>(uid_));
+    packet->set_trusted_packet_sequence_id(kServicePacketSequenceID);
+    SerializeAndAppendPacket(packets, packet.SerializeAsArray());
     ++tracing_session->num_triggers_emitted_into_trace;
   }
 }
diff --git a/src/tracing/track_event_context.cc b/src/tracing/event_context.cc
similarity index 87%
rename from src/tracing/track_event_context.cc
rename to src/tracing/event_context.cc
index 93f45cb..2126e2c 100644
--- a/src/tracing/track_event_context.cc
+++ b/src/tracing/event_context.cc
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-#include "perfetto/tracing/track_event_context.h"
+#include "perfetto/tracing/event_context.h"
 
 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
 #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
 
 namespace perfetto {
 
-TrackEventContext::TrackEventContext(
-    TrackEventContext::TracePacketHandle trace_packet,
+EventContext::EventContext(
+    EventContext::TracePacketHandle trace_packet,
     internal::TrackEventIncrementalState* incremental_state)
     : trace_packet_(std::move(trace_packet)),
-      track_event_(trace_packet_->set_track_event()),
+      event_(trace_packet_->set_track_event()),
       incremental_state_(incremental_state) {}
 
-TrackEventContext::~TrackEventContext() {
+EventContext::~EventContext() {
   // When the track event is finalized (i.e., the context is destroyed), we
   // should flush any newly seen interned data to the trace. The data has
   // earlier been written to a heap allocated protobuf message
diff --git a/src/tracing/internal/tracing_muxer_impl.cc b/src/tracing/internal/tracing_muxer_impl.cc
index 1ce6f93..a185f25 100644
--- a/src/tracing/internal/tracing_muxer_impl.cc
+++ b/src/tracing/internal/tracing_muxer_impl.cc
@@ -37,7 +37,6 @@
 #include "perfetto/tracing/trace_writer_base.h"
 #include "perfetto/tracing/tracing.h"
 #include "perfetto/tracing/tracing_backend.h"
-#include "protos/perfetto/config/trace_config.pb.h"
 #include "src/tracing/internal/in_process_tracing_backend.h"
 #include "src/tracing/internal/system_tracing_backend.h"
 
@@ -59,12 +58,8 @@
 
 uint64_t ComputeConfigHash(const DataSourceConfig& config) {
   base::Hash hasher;
-  perfetto::protos::DataSourceConfig config_proto;
-  config.ToProto(&config_proto);
-  std::string config_bytes;
-  bool serialized = config_proto.SerializeToString(&config_bytes);
-  PERFETTO_DCHECK(serialized);
-  hasher.Update(&config_bytes[0], config_bytes.size());
+  std::string config_bytes = config.SerializeAsString();
+  hasher.Update(config_bytes.data(), config_bytes.size());
   return hasher.digest();
 }
 
diff --git a/src/tracing/internal/track_event_internal.cc b/src/tracing/internal/track_event_internal.cc
index 2e65517..198586a 100644
--- a/src/tracing/internal/track_event_internal.cc
+++ b/src/tracing/internal/track_event_internal.cc
@@ -131,7 +131,7 @@
 }
 
 // static
-TrackEventContext TrackEventInternal::WriteEvent(
+EventContext TrackEventInternal::WriteEvent(
     TraceWriterBase* trace_writer,
     TrackEventIncrementalState* incr_state,
     const char* category,
@@ -150,10 +150,10 @@
 
   // We assume that |category| and |name| point to strings with static lifetime.
   // This means we can use their addresses as interning keys.
-  TrackEventContext ctx(std::move(packet), incr_state);
+  EventContext ctx(std::move(packet), incr_state);
   size_t category_iid = InternedEventCategory::Get(&ctx, category);
 
-  auto track_event = ctx.track_event();
+  auto track_event = ctx.event();
   track_event->set_type(type);
   // TODO(skyostil): Handle multiple categories.
   track_event->add_category_iids(category_iid);
diff --git a/src/tracing/test/tracing_module.cc b/src/tracing/test/tracing_module.cc
index 4b0283e..2df377f0 100644
--- a/src/tracing/test/tracing_module.cc
+++ b/src/tracing/test/tracing_module.cc
@@ -59,11 +59,10 @@
 }
 
 void FunctionWithOneTrackEventWithTypedArgument() {
-  TRACE_EVENT_BEGIN("cat1", "EventWithArg",
-                    [](perfetto::TrackEventContext ctx) {
-                      auto log = ctx.track_event()->set_log_message();
-                      log->set_body_iid(0x42);
-                    });
+  TRACE_EVENT_BEGIN("cat1", "EventWithArg", [](perfetto::EventContext ctx) {
+    auto log = ctx.event()->set_log_message();
+    log->set_body_iid(0x42);
+  });
   // Simulates the non-tracing work of this function, which should take priority
   // over the above trace event in terms of instruction scheduling.
   puts("Hello");
diff --git a/test/metrics/android_process_growth.out b/test/metrics/android_process_growth.out
deleted file mode 100644
index e108056..0000000
--- a/test/metrics/android_process_growth.out
+++ /dev/null
@@ -1,14 +0,0 @@
-android_process_growth {
-  instance_metrics {
-    pid: 3
-    process_name: "com.google.android.calendar"
-    anon_and_swap_start_value: 2000
-    anon_and_swap_change_bytes: 4000
-  }
-  instance_metrics {
-    pid: 4
-    process_name: "com.google.android.calendar"
-    anon_and_swap_start_value: 150
-    anon_and_swap_change_bytes: 0
-  }
-}
diff --git a/test/metrics/android_process_growth.py b/test/metrics/android_process_growth.py
deleted file mode 100644
index 75bdece..0000000
--- a/test/metrics/android_process_growth.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-anon_member = 1
-swap_member = 2
-
-trace = synth_common.create_trace()
-trace.add_process_tree_packet()
-trace.add_process(1, 0, 'init')
-trace.add_process(2, 1, 'system_server')
-trace.add_process(3, 1, 'com.google.android.calendar')
-trace.add_process(4, 1, 'com.google.android.calendar')
-
-trace.add_ftrace_packet(cpu=0)
-trace.add_rss_stat(100, 3, anon_member, 1000)
-trace.add_rss_stat(100, 3, swap_member, 1000)
-trace.add_rss_stat(100, 4, anon_member, 100)
-trace.add_rss_stat(100, 4, swap_member, 50)
-
-trace.add_rss_stat(200, 3, anon_member, 2000)
-trace.add_rss_stat(200, 3, swap_member, 2000)
-trace.add_rss_stat(200, 4, anon_member, 1000)
-trace.add_rss_stat(200, 4, swap_member, 100)
-
-trace.add_rss_stat(300, 3, anon_member, 3000)
-trace.add_rss_stat(300, 3, swap_member, 3000)
-trace.add_rss_stat(300, 4, anon_member, 50)
-trace.add_rss_stat(300, 4, swap_member, 100)
-
-print(trace.trace.SerializeToString())
diff --git a/test/metrics/heap_profile.textproto b/test/metrics/heap_profile.textproto
index 831b002..d7dcfd7 100644
--- a/test/metrics/heap_profile.textproto
+++ b/test/metrics/heap_profile.textproto
@@ -4,11 +4,13 @@
       pid: 1
       ppid: 0
       cmdline: "init"
+      uid: 0
     }
     processes {
       pid: 2
       ppid: 1
       cmdline: "system_server"
+      uid: 1000
     }
   }
 }
diff --git a/test/metrics/heap_profile_callsites.out b/test/metrics/heap_profile_callsites.out
index 5f8c14c..6079714 100644
--- a/test/metrics/heap_profile_callsites.out
+++ b/test/metrics/heap_profile_callsites.out
@@ -2,6 +2,10 @@
   instance_stats {
     pid: 2
     process_name: "system_server"
+    process {
+      name: "system_server"
+      uid: 1000
+    }
     callsites {
       hash: -2067767828047084124
       parent_hash: 3061552492032359760
diff --git a/test/metrics/index b/test/metrics/index
index 8f29693..0ee6a7f 100644
--- a/test/metrics/index
+++ b/test/metrics/index
@@ -4,7 +4,6 @@
 
 # Synthetic traces
 android_mem_by_priority.py android_mem android_mem_by_priority.out
-android_process_growth.py android_process_growth android_process_growth.out
 android_lmk.py android_lmk android_mem_lmk.out
 android_ion.py android_ion android_ion.out
 
diff --git a/test/metrics/java_heap_stats.out b/test/metrics/java_heap_stats.out
index 64db708..f818457 100644
--- a/test/metrics/java_heap_stats.out
+++ b/test/metrics/java_heap_stats.out
@@ -1,7 +1,10 @@
 java_heap_stats {
   instance_stats {
     upid: 2
-    process_name: "system_server"
+    process {
+      name: "system_server"
+      uid: 1000
+    }
     samples {
       ts: 10
       heap_size: 224
diff --git a/test/trace_processor/heap_graph.textproto b/test/trace_processor/heap_graph.textproto
index b785578..4001fcf 100644
--- a/test/trace_processor/heap_graph.textproto
+++ b/test/trace_processor/heap_graph.textproto
@@ -4,11 +4,13 @@
       pid: 1
       ppid: 0
       cmdline: "init"
+      uid: 0
     }
     processes {
       pid: 2
       ppid: 1
       cmdline: "system_server"
+      uid: 1000
     }
   }
 }
diff --git a/test/trace_processor/index b/test/trace_processor/index
index 808b2cf..2ead199 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -87,6 +87,7 @@
 ../data/android_sched_and_ps.pb span_left_join_left_partitioned.sql span_left_join_left_partitioned.out
 ../data/android_sched_and_ps.pb span_outer_join.sql span_outer_join.out
 ../data/android_sched_and_ps.pb span_left_join_empty_right.sql span_left_join_empty_right.out
+../data/android_sched_and_ps.pb span_join_zero_negative_dur.sql span_join_zero_negative_dur.out
 
 # Window table
 ../data/android_sched_and_ps.pb smoke_window.sql android_sched_and_ps_smoke_window.out
diff --git a/test/trace_processor/oom_query.sql b/test/trace_processor/oom_query.sql
index 638cffe..7ab3118 100644
--- a/test/trace_processor/oom_query.sql
+++ b/test/trace_processor/oom_query.sql
@@ -64,7 +64,7 @@
  */
 CREATE VIEW output AS
 SELECT ts,
-       lead(ts, 1, ts) over win - ts as dur,
+       lead(ts, 1, ts + dur) over win - ts as dur,
        SUM(rss_oom_lt_zero_diff) OVER win as rss_oom_lt_zero,
        SUM(rss_oom_eq_zero_diff) OVER win as rss_oom_eq_zero,
        SUM(rss_fg_diff) OVER win as rss_fg,
diff --git a/test/trace_processor/span_join_zero_negative_dur.out b/test/trace_processor/span_join_zero_negative_dur.out
new file mode 100644
index 0000000..dd65666
--- /dev/null
+++ b/test/trace_processor/span_join_zero_negative_dur.out
@@ -0,0 +1,12 @@
+
+
+
+
+
+"ts","dur","part"
+1,0,0
+1,2,0
+5,-1,0
+5,0,0
+1,1,1
+2,0,1
diff --git a/test/trace_processor/span_join_zero_negative_dur.sql b/test/trace_processor/span_join_zero_negative_dur.sql
new file mode 100644
index 0000000..246ebcf
--- /dev/null
+++ b/test/trace_processor/span_join_zero_negative_dur.sql
@@ -0,0 +1,29 @@
+create table t1(
+  ts BIG INT,
+  dur BIG INT,
+  part BIG INT,
+  PRIMARY KEY (part, ts, dur)
+) without rowid;
+
+INSERT INTO t1(ts, dur, part)
+VALUES
+(1, 0, 0),
+(5, -1, 0),
+(2, 0, 1);
+
+create table t2(
+  ts BIG INT,
+  dur BIG INT,
+  part BIG INT,
+  PRIMARY KEY (part, ts, dur)
+) without rowid;
+
+INSERT INTO t2(ts, dur, part)
+VALUES
+(1, 2, 0),
+(5, 0, 0),
+(1, 1, 1);
+
+create virtual table sp using span_outer_join(t1 PARTITIONED part, t2 PARTITIONED part);
+
+select ts,dur,part from sp;
diff --git a/test/trace_processor/synth_oom_oom_query.out b/test/trace_processor/synth_oom_oom_query.out
index 9e99271..998d67d 100644
--- a/test/trace_processor/synth_oom_oom_query.out
+++ b/test/trace_processor/synth_oom_oom_query.out
@@ -21,3 +21,4 @@
 122,1,880.000000,880.000000,880.000000,1050.000000,1050.000000,1050.000000
 123,1,885.000000,885.000000,885.000000,1180.000000,1180.000000,1180.000000
 124,1,885.000000,885.000000,885.000000,1160.000000,1160.000000,1160.000000
+125,1,885.000000,885.000000,885.000000,1120.000000,1120.000000,1120.000000
diff --git a/tools/gen_bazel b/tools/gen_bazel
index 38dcee9..a68cef1 100755
--- a/tools/gen_bazel
+++ b/tools/gen_bazel
@@ -170,7 +170,10 @@
         else:
           indent = '    '
         for entry in v:
-          res += '%s    "%s",\n' % (indent, entry)
+          if entry.startswith('PERFETTO_CONFIG.'):
+            res += '%s    %s,\n' % (indent, entry)
+          else:
+            res += '%s    "%s",\n' % (indent, entry)
         res += '%s]' % indent
         if k == 'deps' and self.external_deps:
           res += ' + %s' % self.external_deps[0]
@@ -215,7 +218,7 @@
   assert (target.type == 'proto_library')
 
   def get_sources_label(target_name):
-    return re.sub('_(lite|zero|cpp)$', '',
+    return re.sub('_(lite|zero|cpp|ipc)$', '',
                   get_bazel_label_name(target_name)) + '_protos'
 
   sources_label_name = get_sources_label(target.name)
@@ -253,11 +256,20 @@
   assert (all(x.startswith('//') for x in target.sources))
   assert (all(x.endswith('.proto') for x in target.sources))
   sources_label.srcs = sorted([x[2:] for x in target.sources])  # Strip //.
-  deps = [':' + get_sources_label(x) for x in target.proto_deps]
+
+  # TODO(primiano): Remove the "wire_protocol not in x" condition below once
+  # the IPC layer stops depending on libprotobuf (i.e. once aosp/1163503 lands).
+  deps = [
+      ':' + get_sources_label(x)
+      for x in target.proto_deps
+      if '//protos/perfetto/ipc:wire_protocol' not in x
+  ]
   sources_label.deps = sorted(deps)
 
   if target.name in proto_targets:
     sources_label.visibility = ['//visibility:public']
+  else:
+    sources_label.visibility = ['PERFETTO_CONFIG.proto_library_visibility']
 
   return [plugin_label, sources_label]
 
diff --git a/tools/tmux b/tools/tmux
index 035127f..6b6d14c 100755
--- a/tools/tmux
+++ b/tools/tmux
@@ -24,7 +24,7 @@
 function get_gn_value() {
   local out=$1
   local key=$2
-  gn args "$out" --list --short | sed -n -e "s/$key = \"\(.*\)\"/\1/p"
+  gn args "$out" --list=$key --short | awk '{print $3}' | tr -d '"'
 }
 
 function is_monolithic() {
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 276f9d6..2d65f7a 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -241,15 +241,6 @@
       "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
       "dev": true
     },
-    "agent-base": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
-      "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
-      "dev": true,
-      "requires": {
-        "es6-promisify": "^5.0.0"
-      }
-    },
     "ajv": {
       "version": "6.9.1",
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz",
@@ -761,16 +752,6 @@
       "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
       "dev": true
     },
-    "axios": {
-      "version": "0.17.1",
-      "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz",
-      "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=",
-      "dev": true,
-      "requires": {
-        "follow-redirects": "^1.2.5",
-        "is-buffer": "^1.1.5"
-      }
-    },
     "babel-code-frame": {
       "version": "6.26.0",
       "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
@@ -1178,13 +1159,13 @@
       }
     },
     "browser-sync": {
-      "version": "2.26.3",
-      "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.26.3.tgz",
-      "integrity": "sha512-VLzpjCA4uXqfzkwqWtMM6hvPm2PNHp2RcmzBXcbi6C9WpkUhhFb8SVAr4CFrCsFxDg+oY6HalOjn8F+egyvhag==",
+      "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.2",
-        "browser-sync-ui": "^2.26.2",
+        "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",
@@ -1198,8 +1179,8 @@
         "fs-extra": "3.0.1",
         "http-proxy": "1.15.2",
         "immutable": "^3",
-        "localtunnel": "1.9.1",
-        "micromatch": "2.3.11",
+        "localtunnel": "1.9.2",
+        "micromatch": "^3.1.10",
         "opn": "5.3.0",
         "portscanner": "2.1.1",
         "qs": "6.2.3",
@@ -1215,6 +1196,83 @@
         "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",
@@ -1232,6 +1290,244 @@
             "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",
@@ -1241,6 +1537,100 @@
             "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",
@@ -1315,32 +1705,6 @@
         }
       }
     },
-    "browser-sync-client": {
-      "version": "2.26.2",
-      "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.26.2.tgz",
-      "integrity": "sha512-FEuVJD41fI24HJ30XOT2RyF5WcnEtdJhhTqeyDlnMk/8Ox9MZw109rvk9pdfRWye4soZLe+xcAo9tHSMxvgAdw==",
-      "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.2",
-      "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.26.2.tgz",
-      "integrity": "sha512-LF7GMWo8ELOE0eAlxuRCfnGQT1ZxKP9flCfGgZdXFc6BwmoqaJHlYe7MmVvykKkXjolRXTz8ztXAKGVqNwJ3EQ==",
-      "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"
-      }
-    },
     "bs-recipes": {
       "version": "1.3.4",
       "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz",
@@ -2503,32 +2867,6 @@
         "locate-path": "^2.0.0"
       }
     },
-    "follow-redirects": {
-      "version": "1.7.0",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz",
-      "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==",
-      "dev": true,
-      "requires": {
-        "debug": "^3.2.6"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.2.6",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
-          "dev": true,
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
-        "ms": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
-          "dev": true
-        }
-      }
-    },
     "for-in": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -2613,8 +2951,7 @@
         "ansi-regex": {
           "version": "2.1.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "aproba": {
           "version": "1.2.0",
@@ -2657,8 +2994,7 @@
         "code-point-at": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "concat-map": {
           "version": "0.0.1",
@@ -2669,8 +3005,7 @@
         "console-control-strings": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "core-util-is": {
           "version": "1.0.2",
@@ -2787,8 +3122,7 @@
         "inherits": {
           "version": "2.0.3",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "ini": {
           "version": "1.3.5",
@@ -2800,7 +3134,6 @@
           "version": "1.0.0",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "number-is-nan": "^1.0.0"
           }
@@ -2830,7 +3163,6 @@
           "version": "2.3.5",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "safe-buffer": "^5.1.2",
             "yallist": "^3.0.0"
@@ -2849,7 +3181,6 @@
           "version": "0.5.1",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "minimist": "0.0.8"
           }
@@ -2943,7 +3274,6 @@
           "version": "1.4.0",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "wrappy": "1"
           }
@@ -3029,8 +3359,7 @@
         "safe-buffer": {
           "version": "5.1.2",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "safer-buffer": {
           "version": "2.1.2",
@@ -3066,7 +3395,6 @@
           "version": "1.0.2",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "code-point-at": "^1.0.0",
             "is-fullwidth-code-point": "^1.0.0",
@@ -3086,7 +3414,6 @@
           "version": "3.0.1",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "ansi-regex": "^2.0.0"
           }
@@ -3130,14 +3457,12 @@
         "wrappy": {
           "version": "1.0.2",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "yallist": {
           "version": "3.0.3",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         }
       }
     },
@@ -3310,12 +3635,12 @@
       "dev": true
     },
     "handlebars": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.0.tgz",
-      "integrity": "sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==",
+      "version": "4.5.3",
+      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
+      "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
       "dev": true,
       "requires": {
-        "async": "^2.5.0",
+        "neo-async": "^2.6.0",
         "optimist": "^0.6.1",
         "source-map": "^0.6.1",
         "uglify-js": "^3.1.4"
@@ -3529,15 +3854,24 @@
       }
     },
     "https-proxy-agent": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
-      "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
+      "version": "2.2.4",
+      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
+      "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
       "dev": true,
       "requires": {
-        "agent-base": "^4.1.0",
+        "agent-base": "^4.3.0",
         "debug": "^3.1.0"
       },
       "dependencies": {
+        "agent-base": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
+          "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
+          "dev": true,
+          "requires": {
+            "es6-promisify": "^5.0.0"
+          }
+        },
         "debug": {
           "version": "3.2.6",
           "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
@@ -3548,9 +3882,9 @@
           }
         },
         "ms": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
           "dev": true
         }
       }
@@ -4445,9 +4779,9 @@
       "dev": true
     },
     "js-yaml": {
-      "version": "3.12.1",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz",
-      "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==",
+      "version": "3.13.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+      "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
       "dev": true,
       "requires": {
         "argparse": "^1.0.7",
@@ -4628,111 +4962,6 @@
         "strip-bom": "^2.0.0"
       }
     },
-    "localtunnel": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.1.tgz",
-      "integrity": "sha512-HWrhOslklDvxgOGFLxi6fQVnvpl6XdX4sPscfqMZkzi3gtt9V7LKBWYvNUcpHSVvjwCQ6xzXacVvICNbNcyPnQ==",
-      "dev": true,
-      "requires": {
-        "axios": "0.17.1",
-        "debug": "2.6.9",
-        "openurl": "1.1.1",
-        "yargs": "6.6.0"
-      },
-      "dependencies": {
-        "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"
-          }
-        },
-        "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"
-          }
-        },
-        "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"
-          }
-        },
-        "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.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"
-          }
-        },
-        "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"
-          }
-        }
-      }
-    },
     "locate-path": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
@@ -4744,9 +4973,9 @@
       }
     },
     "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==",
       "dev": true
     },
     "lodash.isfinite": {
@@ -4959,9 +5188,9 @@
       "dev": true
     },
     "mithril": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/mithril/-/mithril-1.1.6.tgz",
-      "integrity": "sha512-fWcUrQTCqu8M916rj1MFGlHaPh65rznPu6U/N2U9g81H89klDCIptSK5bnkNkC+jyi3sJIXjyGhSQjUnR8jzZA=="
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/mithril/-/mithril-1.1.7.tgz",
+      "integrity": "sha512-1SAkGeVrIVvkUHlPHvR3pXdWzNfTzmS/fBAe+rC2ApEBfZFFc+idi8Qg/M5JoW/sZkIDXSfQYVgvENMIhBIVAg=="
     },
     "mitt": {
       "version": "1.1.3",
@@ -4970,9 +5199,9 @@
       "dev": true
     },
     "mixin-deep": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
-      "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+      "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
       "dev": true,
       "requires": {
         "for-in": "^1.0.2",
@@ -5077,6 +5306,12 @@
       "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
       "dev": true
     },
+    "neo-async": {
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
+      "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
+      "dev": true
+    },
     "node-gyp": {
       "version": "3.8.0",
       "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
@@ -6542,288 +6777,19 @@
       }
     },
     "rollup-pluginutils": {
-      "version": "2.7.1",
-      "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.7.1.tgz",
-      "integrity": "sha512-3nRf3buQGR9qz/IsSzhZAJyoK663kzseps8itkYHr+Z7ESuaffEPfgRinxbCRA0pf0gzLqkNKkSb8aNVTq75NA==",
+      "version": "2.8.2",
+      "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
+      "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
       "dev": true,
       "requires": {
-        "estree-walker": "^0.6.0",
-        "micromatch": "^3.1.10"
+        "estree-walker": "^0.6.1"
       },
       "dependencies": {
-        "arr-diff": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
-          "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+        "estree-walker": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
+          "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
           "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"
-          }
         }
       }
     },
@@ -7380,9 +7346,9 @@
       "dev": true
     },
     "set-value": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
-      "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+      "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
       "dev": true,
       "requires": {
         "extend-shallow": "^2.0.1",
@@ -8280,38 +8246,15 @@
       "dev": true
     },
     "union-value": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
-      "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+      "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
       "dev": true,
       "requires": {
         "arr-union": "^3.1.0",
         "get-value": "^2.0.6",
         "is-extendable": "^0.1.1",
-        "set-value": "^0.4.3"
-      },
-      "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"
-          }
-        },
-        "set-value": {
-          "version": "0.4.3",
-          "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
-          "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
-          "dev": true,
-          "requires": {
-            "extend-shallow": "^2.0.1",
-            "is-extendable": "^0.1.1",
-            "is-plain-object": "^2.0.1",
-            "to-object-path": "^0.3.0"
-          }
-        }
+        "set-value": "^2.0.1"
       }
     },
     "universalify": {
diff --git a/ui/package.json b/ui/package.json
index 7e3b8b5..e960062 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -24,7 +24,7 @@
     "immer": "^1.12.1",
     "jsbn-rsa": "^1.0.3",
     "micromodal": "^0.4.0",
-    "mithril": "^1.1.6",
+    "mithril": "^1.1.7",
     "noice-json-rpc": "^1.2.0",
     "pako": "^1.0.10",
     "protobufjs": "^6.8.8",
diff --git a/ui/src/assets/common.scss b/ui/src/assets/common.scss
index dc4e411..85720b8 100644
--- a/ui/src/assets/common.scss
+++ b/ui/src/assets/common.scss
@@ -53,7 +53,6 @@
 
 * {
     box-sizing: border-box;
-    overflow: hidden;
     -webkit-tap-highlight-color: none;
     touch-action: none;
 }
@@ -97,6 +96,7 @@
     grid-template-rows: auto auto 1fr;
     grid-template-columns: auto 1fr;
     color: #121212;
+    overflow: hidden;
 }
 
 button {
@@ -132,7 +132,8 @@
     grid-area: page;
     position: relative;
     display: flex;
-    flex-direction: column
+    flex-direction: column;
+    overflow: hidden;
 }
 
 .split-panel {
@@ -140,6 +141,7 @@
   display: flex;
   flex-flow: row;
   position: relative;
+  overflow: hidden;
 }
 
 .video-panel {
@@ -346,6 +348,24 @@
   overflow-y: auto;
   flex: 1 1 auto;
   will-change: transform;  // Force layer creation.
+  display: grid;
+  grid-template-columns: 1fr;
+  grid-template-rows: 1fr;
+  grid-template-areas: "space";
+}
+
+.details-panel-container {
+  position: relative;
+  overflow-x: hidden;
+  overflow-y: auto;
+  flex: 1 1 auto;
+  // TODO(taylori): This causes the sticky header to flicker when scrolling.
+  // Is will-change necessary in the details panel?
+  // will-change: transform;
+  display: grid;
+  grid-template-columns: 1fr;
+  grid-template-rows: 1fr;
+  grid-template-areas: "space";
 }
 
 .pinned-panel-container {
@@ -355,6 +375,10 @@
   overflow: visible;
   box-shadow: 1px 3px 15px rgba(23, 32, 44, 0.3);
   z-index: 2;
+  display: grid;
+  grid-template-columns: 1fr;
+  grid-template-rows: 1fr;
+  grid-template-areas: "space";
 }
 
 // In the scrolling case, since the canvas is overdrawn and continuously
@@ -362,14 +386,17 @@
 // height equaling the total height of the content to prevent scrolling
 // height from growing.
 .scroll-limiter {
-  overflow: hidden;
   position: relative;
+  grid-area: space;
+  overflow: hidden;
 }
 
 canvas.main-canvas {
-  top: 0px;
   z-index: -1;
-  position: absolute;
+}
+
+.panels {
+  grid-area: space;
 }
 
 .panel {
diff --git a/ui/src/assets/details.scss b/ui/src/assets/details.scss
index 5a0e44a..d5f4d5c 100644
--- a/ui/src/assets/details.scss
+++ b/ui/src/assets/details.scss
@@ -33,7 +33,7 @@
       .tab {
         font-family: 'Google Sans';
         color: #3c4b5d;
-        padding: 3px 10px 10px 10px;
+        padding: 3px 10px 0px 10px;
         margin-top: 3px;
         font-size: 13px;
         border-radius: 5px 5px 0px 0px;
@@ -78,26 +78,25 @@
     }
   }
 
-  .details-panel-container {
-    .scroll-limiter {
-      height: 100%;
-      display: flex;
-      flex-direction: column;
-      .panel:last-child {
-        flex-grow: 1;
-      }
-    }
-  }
 }
 
 .details-panel {
-  padding: 10px;
   font-family: 'Google Sans';
   color: #3c4b5d;
-
   .details-panel-heading {
-    font-size: 16px;
-    padding-bottom: 5px;
+    padding: 10px 0 5px 0;
+    position: sticky;
+    top: 0px;
+    display: flex;
+    background: white;
+    h2 {
+      font-size: 16px;
+      font-family: 'Google Sans';
+      padding: 0 10px;
+      &.split {
+        width: 50%;
+      }
+    }
   }
 
   table {
@@ -109,6 +108,7 @@
     max-width: 50%;
     table-layout: fixed;
     word-wrap: break-word;
+    padding: 10px;
     tr:hover {
       background-color: hsl(214, 22%, 90%);
     }
@@ -141,12 +141,14 @@
     padding-bottom: .5rem;
     border-radius: .25rem;
     margin-top: 12px;
+    margin-left: 10px;
   }
 
   .explanation {
     font-size: 14px;
     width: 35%;
     margin-top: 10px;
+    padding-left: 10px;
   }
 
   .material-icons {
@@ -209,17 +211,16 @@
   display: grid;
   grid-template-rows: auto 1fr;
 
+  header {
+    position: sticky;
+    top: 0px;
+    z-index: 1;
+  }
+
   header.stale {
     color: grey;
   }
 
-  .scrolling-container {
-    overflow-y: scroll;
-    position: relative;
-    width: 100%;
-    background-color: #fefefe;
-    border-bottom: 1px solid hsl(213, 22%, 75%);
-
     .rows {
       position: relative;
       direction: ltr;
@@ -280,6 +281,5 @@
           }
         }
       }
-    }
   }
 }
diff --git a/ui/src/frontend/chrome_slice_panel.ts b/ui/src/frontend/chrome_slice_panel.ts
index 97ce65c..b43286e 100644
--- a/ui/src/frontend/chrome_slice_panel.ts
+++ b/ui/src/frontend/chrome_slice_panel.ts
@@ -25,7 +25,7 @@
     if (sliceInfo.ts && sliceInfo.dur && sliceInfo.name) {
       return m(
           '.details-panel',
-          m('.details-panel-heading', `Slice Details:`),
+          m('.details-panel-heading', m('h2', `Slice Details`)),
           m(
               '.details-table',
               [m('table',
@@ -47,10 +47,11 @@
     } else {
       return m(
           '.details-panel',
-          m(
-              '.details-panel-heading',
-              `Slice Details:`,
-              ));
+          m('.details-panel-heading',
+            m(
+                'h2',
+                `Slice Details`,
+                )));
     }
   }
   renderCanvas(_ctx: CanvasRenderingContext2D, _size: PanelSize) {}
diff --git a/ui/src/frontend/counter_panel.ts b/ui/src/frontend/counter_panel.ts
index 458a037..df207ff 100644
--- a/ui/src/frontend/counter_panel.ts
+++ b/ui/src/frontend/counter_panel.ts
@@ -29,7 +29,7 @@
         counterInfo.duration !== undefined) {
       return m(
           '.details-panel',
-          m('.details-panel-heading', `Counter Details:`),
+          m('.details-panel-heading', m('h2', `Counter Details`)),
           m(
               '.details-table',
               [m('table',
@@ -50,7 +50,8 @@
               ));
     } else {
       return m(
-          '.details-panel', m('.details-panel-heading', `Counter Details:`));
+          '.details-panel',
+          m('.details-panel-heading', m('h2', `Counter Details`)));
     }
   }
 
diff --git a/ui/src/frontend/flamegraph.ts b/ui/src/frontend/flamegraph.ts
index 12b0785..704d14f 100644
--- a/ui/src/frontend/flamegraph.ts
+++ b/ui/src/frontend/flamegraph.ts
@@ -132,6 +132,15 @@
     // Draw root node.
     ctx.fillStyle = this.generateColor('root', false);
     ctx.fillRect(x, currentY, width, nodeHeight);
+    ctx.font = `${this.textSize}px Google Sans`;
+    const text = cropText(
+        `root: ${
+            this.displaySize(
+                this.totalSize, unit, unit === 'B' ? 1024 : 1000)}`,
+        charWidth,
+        width - 2);
+    ctx.fillStyle = 'black';
+    ctx.fillText(text, x + 5, currentY + nodeHeight - 4);
     currentY += nodeHeight;
 
 
@@ -219,23 +228,67 @@
 
     if (this.hoveredX > -1 && this.hoveredY > -1 && this.hoveredCallsite) {
       // Draw the tooltip.
-      const line1 = this.getCallsiteName(this.hoveredCallsite);
+      const lines: string[] = [];
+      let lineSplitter: LineSplitter;
+      const nameText = this.getCallsiteName(this.hoveredCallsite);
+      lineSplitter =
+          splitIfTooBig(nameText, width, ctx.measureText(nameText).width);
+      const nameTextWidth = lineSplitter.lineWidth;
+      lines.push(...lineSplitter.lines);
+
+      const mappingText = this.hoveredCallsite.mapping;
+      lineSplitter =
+          splitIfTooBig(mappingText, width, ctx.measureText(mappingText).width);
+      const mappingTextWidth = lineSplitter.lineWidth;
+      lines.push(...lineSplitter.lines);
+
       const percentage = this.hoveredCallsite.totalSize / this.totalSize * 100;
-      const line2 = `total: ${this.hoveredCallsite.totalSize}${unit} (${
-          percentage.toFixed(2)}%)`;
+      const totalSizeText = `total: ${
+          this.displaySize(
+              this.hoveredCallsite.totalSize,
+              unit,
+              unit === 'B' ? 1024 : 1000)} (${percentage.toFixed(2)}%)`;
+      lineSplitter = splitIfTooBig(
+          totalSizeText, width, ctx.measureText(totalSizeText).width);
+      const totalSizeTextWidth = lineSplitter.lineWidth;
+      lines.push(...lineSplitter.lines);
+
+      let selfSizeWidth = 0;
+      if (this.hoveredCallsite.selfSize > 0) {
+        const selfSizeText = `self: ${
+            this.displaySize(
+                this.hoveredCallsite.selfSize,
+                unit,
+                unit === 'B' ? 1024 : 1000)} (${percentage.toFixed(2)}%)`;
+        lineSplitter = splitIfTooBig(
+            selfSizeText, width, ctx.measureText(selfSizeText).width);
+        selfSizeWidth = lineSplitter.lineWidth;
+        lines.push(...lineSplitter.lines);
+      }
+
+      const rectWidth = Math.max(
+                            nameTextWidth,
+                            mappingTextWidth,
+                            totalSizeTextWidth,
+                            selfSizeWidth) +
+          16;
+      const rectXStart = this.hoveredX + 8 + rectWidth > width ?
+          width - rectWidth - 8 :
+          this.hoveredX + 8;
+      const rectHeight = nodeHeight * (lines.length + 1);
+      const rectYStart = this.hoveredY + 4 + rectHeight > height ?
+          height - rectHeight - 8 :
+          this.hoveredY + 4;
+
       ctx.font = '12px Google Sans';
-      const line1Width = ctx.measureText(line1).width;
-      const line2Width = ctx.measureText(line2).width;
-      const rectWidth = Math.max(line1Width, line2Width);
-      const rectYStart = this.hoveredY + 10;
-      const rectHeight = nodeHeight * 3;
-      const rectYEnd = rectYStart + rectHeight;
       ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
-      ctx.fillRect(this.hoveredX + 5, rectYStart, rectWidth + 16, rectHeight);
+      ctx.fillRect(rectXStart, rectYStart, rectWidth, rectHeight);
       ctx.fillStyle = 'hsl(200, 50%, 40%)';
       ctx.textAlign = 'left';
-      ctx.fillText(line1, this.hoveredX + 8, rectYStart + 18 /* 8 + 10s */);
-      ctx.fillText(line2, this.hoveredX + 8, rectYEnd - 8);
+      for (let i = 0; i < lines.length; i++) {
+        const line = lines[i];
+        ctx.fillText(line, rectXStart + 4, rectYStart + (i + 1) * 18);
+      }
     }
   }
 
@@ -244,6 +297,21 @@
                                                            value.name;
   }
 
+  private displaySize(totalSize: number, unit: string, step = 1024): string {
+    if (unit === '') return totalSize.toLocaleString();
+    if (totalSize === 0) return `0 ${unit}`;
+    const units = [
+      ['', 0],
+      ['K', step],
+      ['M', Math.pow(step, 2)],
+      ['G', Math.pow(step, 3)]
+    ];
+    let unitsIndex = Math.trunc(Math.log(totalSize) / Math.log(step));
+    unitsIndex = unitsIndex > units.length - 1 ? units.length - 1 : unitsIndex;
+    return `${(totalSize / +units[unitsIndex][1]).toLocaleString()} ${
+        units[unitsIndex][0]}${unit}`;
+  }
+
   onMouseMove({x, y}: {x: number, y: number}) {
     this.hoveredX = x;
     this.hoveredY = y;
@@ -303,3 +371,23 @@
     this.isThumbnail = isThumbnail;
   }
 }
+
+export interface LineSplitter {
+  lineWidth: number;
+  lines: string[];
+}
+
+export function splitIfTooBig(
+    line: string, width: number, lineWidth: number): LineSplitter {
+  if (line === '') return {lineWidth, lines: []};
+  const lines: string[] = [];
+  const charWidth = lineWidth / line.length;
+  const maxWidth = width - 32;
+  const maxLineLen = Math.trunc(maxWidth / charWidth);
+  while (line.length > 0) {
+    lines.push(line.slice(0, maxLineLen));
+    line = line.slice(maxLineLen);
+  }
+  lineWidth = Math.min(maxWidth, lineWidth);
+  return {lineWidth, lines};
+}
diff --git a/ui/src/frontend/flamegraph_unittest.ts b/ui/src/frontend/flamegraph_unittest.ts
new file mode 100644
index 0000000..87a327d
--- /dev/null
+++ b/ui/src/frontend/flamegraph_unittest.ts
@@ -0,0 +1,53 @@
+// 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.
+
+import {splitIfTooBig} from './flamegraph';
+
+test('textGoingToMultipleLines', () => {
+  const text = 'Dummy text to go to multiple lines.';
+
+  const lineSplitter = splitIfTooBig(text, 7 + 32, text.length);
+
+  expect(lineSplitter).toEqual({
+    lines: ['Dummy t', 'ext to ', 'go to m', 'ultiple', ' lines.'],
+    lineWidth: 7
+  });
+});
+
+test('emptyText', () => {
+  const text = '';
+
+  const lineSplitter = splitIfTooBig(text, 10, 5);
+
+  expect(lineSplitter).toEqual({lines: [], lineWidth: 5});
+});
+
+test('textEnoughForOneLine', () => {
+  const text = 'Dummy text to go to one lines.';
+
+  const lineSplitter = splitIfTooBig(text, text.length + 32, text.length);
+
+  expect(lineSplitter).toEqual({lines: [text], lineWidth: text.length});
+});
+
+test('textGoingToTwoLines', () => {
+  const text = 'Dummy text to go to two lines.';
+
+  const lineSplitter = splitIfTooBig(text, text.length / 2 + 32, text.length);
+
+  expect(lineSplitter).toEqual({
+    lines: ['Dummy text to g', 'o to two lines.'],
+    lineWidth: text.length / 2
+  });
+});
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index c78fc11..81ae8f6 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -51,6 +51,8 @@
   depth: number;
   name?: string;
   totalSize: number;
+  selfSize: number;
+  mapping: string;
 }
 
 export interface HeapProfileDetails {
diff --git a/ui/src/frontend/gridline_helper.ts b/ui/src/frontend/gridline_helper.ts
index 9f9ac9b..b7a3c5a 100644
--- a/ui/src/frontend/gridline_helper.ts
+++ b/ui/src/frontend/gridline_helper.ts
@@ -72,12 +72,20 @@
   const step = getGridStepSize(span.duration, desiredSteps);
   const start = Math.round(span.start / step) * step;
   const lines: Array<[number, number]> = [];
-  for (let s = start; s < span.end; s += step) {
+  let previousTimestamp = Number.NEGATIVE_INFINITY;
+  // Iterating over the number of steps instead of
+  // for (let s = start; s < span.end; s += step) because if start is very large
+  // number and step very small, s will never reach end.
+  for (let i = 0; i < desiredSteps; i++) {
     let xPos = TRACK_SHELL_WIDTH;
-    xPos += Math.floor(timescale.timeToPx(s));
+    const timestamp = start + i * step;
+    xPos += Math.floor(timescale.timeToPx(timestamp));
     if (xPos < TRACK_SHELL_WIDTH) continue;
     if (xPos > width) break;
-    lines.push([xPos, s]);
+    if (Math.abs(timestamp - previousTimestamp) > Number.EPSILON) {
+      previousTimestamp = timestamp;
+      lines.push([xPos, timestamp]);
+    }
   }
   return lines;
 }
diff --git a/ui/src/frontend/heap_profile_panel.ts b/ui/src/frontend/heap_profile_panel.ts
index 938a80b..524bb40 100644
--- a/ui/src/frontend/heap_profile_panel.ts
+++ b/ui/src/frontend/heap_profile_panel.ts
@@ -37,7 +37,7 @@
       this.pid = heapDumpInfo.pid;
       return m(
           '.details-panel',
-          m('.details-panel-heading', `Heap Profile Details:`),
+          m('.details-panel-heading', m('h2', `Heap Profile Details`)),
           m(
               '.details-table',
               [m('table',
@@ -76,7 +76,7 @@
     } else {
       return m(
           '.details-panel',
-          m('.details-panel-heading', `Heap Snapshot Details:`));
+          m('.details-panel-heading', m('h2', `Heap Profile Details`)));
     }
   }
 
diff --git a/ui/src/frontend/logs_panel.ts b/ui/src/frontend/logs_panel.ts
index 1f80869..2f4c485 100644
--- a/ui/src/frontend/logs_panel.ts
+++ b/ui/src/frontend/logs_panel.ts
@@ -59,8 +59,8 @@
   }
 
   oncreate({dom}: m.CVnodeDOM) {
-    this.scrollContainer =
-        assertExists(dom.querySelector('.scrolling-container') as HTMLElement);
+    this.scrollContainer = assertExists(
+        dom.parentElement!.parentElement!.parentElement as HTMLElement);
     this.scrollContainer.addEventListener(
         'scroll', this.onScroll.bind(this), {passive: true});
     this.bounds = globals.trackDataStore.get(LogBoundsKey) as LogBounds;
@@ -143,8 +143,7 @@
             'class': isStale ? 'stale' : '',
           },
           `Logs rows [${offset}, ${offset + count}] / ${total}`),
-        m('.scrolling-container',
-          m('.rows', {style: {height: `${total * ROW_H}px`}}, rows)));
+        m('.rows', {style: {height: `${total * ROW_H}px`}}, rows));
   }
 
   renderCanvas() {}
diff --git a/ui/src/frontend/panel_container.ts b/ui/src/frontend/panel_container.ts
index 80f99c2..d040eea 100644
--- a/ui/src/frontend/panel_container.ts
+++ b/ui/src/frontend/panel_container.ts
@@ -140,10 +140,13 @@
         m('.panel', panel, m('.debug-panel-border')) :
         m('.panel', {key: panel.key}, panel);
 
-    return m(
-        '.scroll-limiter',
-        m('canvas.main-canvas'),
-        attrs.panels.map(renderPanel));
+    return [
+      m(
+          '.scroll-limiter',
+          m('canvas.main-canvas'),
+          ),
+      m('.panels', attrs.panels.map(renderPanel))
+    ];
   }
 
   onupdate(vnodeDom: m.CVnodeDOM<Attrs>) {
@@ -210,7 +213,7 @@
     this.panelHeights = [];
     this.totalPanelHeight = 0;
 
-    const panels = dom.querySelectorAll('.panel');
+    const panels = dom.parentElement!.querySelectorAll('.panel');
     assertTrue(panels.length === this.attrs.panels.length);
     for (let i = 0; i < panels.length; i++) {
       const height = panels[i].getBoundingClientRect().height;
diff --git a/ui/src/frontend/slice_panel.ts b/ui/src/frontend/slice_panel.ts
index 1437c37..7a37de7 100644
--- a/ui/src/frontend/slice_panel.ts
+++ b/ui/src/frontend/slice_panel.ts
@@ -19,7 +19,7 @@
 import {translateState} from '../common/thread_state';
 import {timeToCode, toNs} from '../common/time';
 
-import {globals} from './globals';
+import {globals, SliceDetails, ThreadDesc} from './globals';
 import {Panel, PanelSize} from './panel';
 import {scrollToTrackAndTs} from './scroll_helper';
 
@@ -29,47 +29,47 @@
     if (sliceInfo.utid === undefined) return;
     const threadInfo = globals.threads.get(sliceInfo.utid);
 
-    if (threadInfo && sliceInfo.ts !== undefined &&
-        sliceInfo.dur !== undefined) {
-      return m(
-          '.details-panel',
-          m('.details-panel-heading', `Slice Details:`),
-          m(
-              '.details-table',
-              [m('table',
-                 [
-                   m('tr',
-                     m('th', `Process`),
-                     m('td', `${threadInfo.procName} [${threadInfo.pid}]`)),
-                   m('tr',
-                     m('th', `Thread`),
-                     m('td',
-                       `${threadInfo.threadName} [${threadInfo.tid}]`,
-                       m('i.material-icons',
-                         {
-                           onclick: () => this.goToThread(),
-                           title: 'Go to thread'
-                         },
-                         'call_made'))),
-                   m('tr',
-                     m('th', `Start time`),
-                     m('td', `${timeToCode(sliceInfo.ts)}`)),
-                   m('tr',
-                     m('th', `Duration`),
-                     m('td', `${timeToCode(sliceInfo.dur)}`)),
-                   m('tr', m('th', `Prio`), m('td', `${sliceInfo.priority}`)),
-                   m('tr',
-                     m('th', `End State`),
-                     m('td', `${translateState(sliceInfo.endState)}`))
-                 ])],
-              ));
+    return m(
+        '.details-panel',
+        m('.details-panel-heading',
+          m('h2.split', `Slice Details`),
+          (sliceInfo.wakeupTs && sliceInfo.wakerUtid) ?
+              m('h2.split', 'Scheduling Latency') :
+              ''),
+        this.getDetails(sliceInfo, threadInfo));
+  }
+
+  getDetails(sliceInfo: SliceDetails, threadInfo: ThreadDesc|undefined) {
+    if (!threadInfo || sliceInfo.ts === undefined ||
+        sliceInfo.dur === undefined) {
+      return null;
     } else {
       return m(
-          '.details-panel',
-          m(
-              '.details-panel-heading',
-              `Slice Details:`,
-              ));
+          '.details-table',
+          m('table',
+            [
+              m('tr',
+                m('th', `Process`),
+                m('td', `${threadInfo.procName} [${threadInfo.pid}]`)),
+              m('tr',
+                m('th', `Thread`),
+                m('td',
+                  `${threadInfo.threadName} [${threadInfo.tid}]`,
+                  m('i.material-icons',
+                    {onclick: () => this.goToThread(), title: 'Go to thread'},
+                    'call_made'))),
+              m('tr',
+                m('th', `Start time`),
+                m('td', `${timeToCode(sliceInfo.ts)}`)),
+              m('tr',
+                m('th', `Duration`),
+                m('td', `${timeToCode(sliceInfo.dur)}`)),
+              m('tr', m('th', `Prio`), m('td', `${sliceInfo.priority}`)),
+              m('tr',
+                m('th', `End State`),
+                m('td', `${translateState(sliceInfo.endState)}`))
+            ]),
+      );
     }
   }
 
@@ -113,13 +113,8 @@
     // Show expanded details on the scheduling of the currently selected slice.
     if (details.wakeupTs && details.wakerUtid !== undefined) {
       const threadInfo = globals.threads.get(details.wakerUtid);
-      // Draw separation line.
-      ctx.fillStyle = '#3c4b5d';
-      ctx.fillRect(size.width / 2, 10, 1, size.height - 10);
-      ctx.font = '16px Google Sans';
-      ctx.fillText('Scheduling Latency:', size.width / 2 + 30, 30);
       // Draw diamond and vertical line.
-      const startDraw = {x: size.width / 2 + 30, y: 52};
+      const startDraw = {x: size.width / 2 + 20, y: 52};
       ctx.beginPath();
       ctx.moveTo(startDraw.x, startDraw.y + 28);
       ctx.fillStyle = 'black';
diff --git a/ui/src/frontend/thread_state_panel.ts b/ui/src/frontend/thread_state_panel.ts
index 3df1884..7ad6127 100644
--- a/ui/src/frontend/thread_state_panel.ts
+++ b/ui/src/frontend/thread_state_panel.ts
@@ -36,7 +36,7 @@
     if (threadInfo) {
       return m(
           '.details-panel',
-          m('.details-panel-heading', 'Thread State'),
+          m('.details-panel-heading', m('h2', 'Thread State')),
           m('.details-table', [m('table', [
               m('tr',
                 m('th', `Start time`),
diff --git a/ui/src/frontend/track_panel.ts b/ui/src/frontend/track_panel.ts
index 22e5b9a..c5fc8d7 100644
--- a/ui/src/frontend/track_panel.ts
+++ b/ui/src/frontend/track_panel.ts
@@ -153,7 +153,7 @@
   view({attrs}: m.CVnode<TrackContentAttrs>) {
     return m('.track-content', {
       onmousemove: (e: MouseEvent) => {
-        attrs.track.onMouseMove({x: e.layerX, y: e.layerY});
+        attrs.track.onMouseMove({x: e.layerX - TRACK_SHELL_WIDTH, y: e.layerY});
         globals.rafScheduler.scheduleRedraw();
       },
       onmouseout: () => {
@@ -165,15 +165,16 @@
         // track.
         if (e.shiftKey) return;
         // If the click is outside of the current time range, clear it.
-        const clickTime =
-            globals.frontendLocalState.timeScale.pxToTime(e.layerX);
+        const clickTime = globals.frontendLocalState.timeScale.pxToTime(
+            e.layerX - TRACK_SHELL_WIDTH);
         const start = globals.frontendLocalState.selectedTimeRange.startSec;
         const end = globals.frontendLocalState.selectedTimeRange.endSec;
         if (start !== undefined && end !== undefined &&
             (clickTime < start || clickTime > end)) {
           globals.frontendLocalState.removeTimeRange();
           e.stopPropagation();
-        } else if (attrs.track.onMouseClick({x: e.layerX, y: e.layerY})) {
+        } else if (attrs.track.onMouseClick(
+                       {x: e.layerX - TRACK_SHELL_WIDTH, y: e.layerY})) {
           e.stopPropagation();
         }
         globals.rafScheduler.scheduleRedraw();
diff --git a/ui/src/tracks/heap_profile_flamegraph/controller.ts b/ui/src/tracks/heap_profile_flamegraph/controller.ts
index b84c688..d4cf389 100644
--- a/ui/src/tracks/heap_profile_flamegraph/controller.ts
+++ b/ui/src/tracks/heap_profile_flamegraph/controller.ts
@@ -108,7 +108,9 @@
     parentId: callsite.parentId,
     depth: callsite.depth,
     name: callsite.name,
-    totalSize: callsite.totalSize
+    totalSize: callsite.totalSize,
+    mapping: callsite.mapping,
+    selfSize: callsite.selfSize
   };
 }
 
@@ -330,7 +332,7 @@
 
     const callsites = await this.query(
         `SELECT hash, name, parent_hash, depth, size, alloc_size, count,
-        alloc_count from ${tableName} ${orderBy}`);
+        alloc_count, map_name, self_size from ${tableName} ${orderBy}`);
 
     const flamegraphData: CallsiteInfo[] = new Array();
     const hashToindex: Map<number, number> = new Map();
@@ -338,8 +340,10 @@
       const hash = callsites.columns[0].longValues![i];
       const name = callsites.columns[1].stringValues![i];
       const parentHash = callsites.columns[2].longValues![i];
-      const depth = callsites.columns[3].longValues![i];
-      const totalSize = callsites.columns[sizeIndex].longValues![i];
+      const depth = +callsites.columns[3].longValues![i];
+      const totalSize = +callsites.columns[sizeIndex].longValues![i];
+      const mapping = callsites.columns[8].stringValues![i];
+      const selfSize = +callsites.columns[9].longValues![i];
       const parentId =
           hashToindex.has(+parentHash) ? hashToindex.get(+parentHash)! : -1;
       hashToindex.set(+hash, i);
@@ -347,7 +351,7 @@
       // as an id of callsite. That way, we have quicker access to parent and it
       // will stay unique.
       flamegraphData.push(
-          {id: i, totalSize: +totalSize, depth: +depth, parentId, name});
+          {id: i, totalSize, depth, parentId, name, selfSize, mapping});
     }
     return flamegraphData;
   }
@@ -396,27 +400,27 @@
     // hash.  Slices will be merged into a big slice.
     await this.query(
         `create view if not exists ${tableNameCallsiteHashNameSize} as
-      with recursive callsite_table_names(
-        id, hash, name, size, alloc_size, count, alloc_count, parent_hash,
-        depth) AS (
-      select id, hash(name) as hash, name, size, alloc_size, count, alloc_count,
-      -1, depth
-      from ${tableNameCallsiteNameSize}
-      where depth = 0
-      UNION ALL
-      SELECT cs.id, hash(cs.name, ctn.hash) as hash, cs.name, cs.size,
-      cs.alloc_size, cs.count, cs.alloc_count, ctn.hash,
-      cs.depth
-      FROM callsite_table_names ctn
-      INNER JOIN ${tableNameCallsiteNameSize} cs ON ctn.id = cs.parent_id
-      )
-      SELECT hash, name, parent_hash, depth,
-      SUM(size) as size,
-      SUM(case when alloc_size > 0 then alloc_size else 0 end) as alloc_size,
-      SUM(count) as count,
-      SUM(case when alloc_count > 0 then alloc_count else 0 end) as alloc_count
-      FROM callsite_table_names
-      group by hash`);
+        with recursive callsite_table_names(
+          id, hash, name, map_name, size, alloc_size, count, alloc_count,
+          parent_hash, depth) AS (
+        select id, hash(name) as hash, name, map_name, size, alloc_size, count,
+          alloc_count, -1, depth
+        from ${tableNameCallsiteNameSize}
+        where depth = 0
+        union all
+        select cs.id, hash(cs.name, ctn.hash) as hash, cs.name, cs.map_name,
+          cs.size, cs.alloc_size, cs.count, cs.alloc_count, ctn.hash, cs.depth
+        from callsite_table_names ctn
+        inner join ${tableNameCallsiteNameSize} cs ON ctn.id = cs.parent_id
+        )
+        select hash, name, map_name, parent_hash, depth, SUM(size) as size,
+          SUM(case when alloc_size > 0 then alloc_size else 0 end)
+            as alloc_size, SUM(count) as count,
+          SUM(case when alloc_count > 0 then alloc_count else 0 end)
+            as alloc_count
+        from callsite_table_names
+        group by hash`);
+
     // Recursive query to compute the cumulative size of each callsite.
     // Base case: We get all the callsites where the size is non-zero.
     // Recursive case: We get the callsite which is the parent of the current
@@ -428,23 +432,27 @@
     //  callsite hash.
     await this.query(`create temp table if not exists ${
         tableNameGroupedCallsitesForFlamegraph}
-        as with recursive callsite_children(hash, name, parent_hash, depth,
-          size, alloc_size, count, alloc_count) AS (
-        select hash, name, parent_hash, depth, size, alloc_size,
-          count, alloc_count
+        as with recursive callsite_children(
+          hash, name, map_name, parent_hash, depth, size, alloc_size, count,
+          alloc_count, self_size, self_alloc_size, self_count, self_alloc_count)
+        as (
+        select hash, name, map_name, parent_hash, depth, size, alloc_size,
+          count, alloc_count, size as self_size, alloc_size as self_alloc_size,
+          count as self_count, alloc_count as self_alloc_count
         from ${tableNameCallsiteHashNameSize}
         union all
-        select chns.hash, chns.name, chns.parent_hash, chns.depth, cc.size,
-        cc.alloc_size, cc.count, cc.alloc_count
+        select chns.hash, chns.name, chns.map_name, chns.parent_hash,
+          chns.depth, cc.size, cc.alloc_size, cc.count, cc.alloc_count,
+          chns.size, chns.alloc_size, chns.count, chns.alloc_count
         from ${tableNameCallsiteHashNameSize} chns
         inner join callsite_children cc on chns.hash = cc.parent_hash
         )
-        SELECT hash, name, parent_hash, depth,
-        SUM(size) as size,
-        SUM(case when alloc_size > 0 then alloc_size else 0 end) as alloc_size,
-        SUM(count) as count,
-        SUM(case when alloc_count > 0 then alloc_count else 0 end) as
-          alloc_count
+        select hash, name, map_name, parent_hash, depth, SUM(size) as size,
+          SUM(case when alloc_size > 0 then alloc_size else 0 end)
+            as alloc_size, SUM(count) as count,
+          SUM(case when alloc_count > 0 then alloc_count else 0 end) as
+            alloc_count,
+          self_size, self_alloc_size, self_count, self_alloc_count
         from callsite_children
         group by hash`);
     return tableNameGroupedCallsitesForFlamegraph;
diff --git a/ui/src/tracks/heap_profile_flamegraph/controller_unittest.ts b/ui/src/tracks/heap_profile_flamegraph/controller_unittest.ts
index 22db892..ef110dd 100644
--- a/ui/src/tracks/heap_profile_flamegraph/controller_unittest.ts
+++ b/ui/src/tracks/heap_profile_flamegraph/controller_unittest.ts
@@ -3,10 +3,42 @@
 
 test('zeroCallsitesMerged', () => {
   const callsites: CallsiteInfo[] = [
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 10},
-    {id: 2, parentId: -1, name: 'B', depth: 0, totalSize: 8},
-    {id: 3, parentId: 1, name: 'A3', depth: 1, totalSize: 4},
-    {id: 4, parentId: 2, name: 'B4', depth: 1, totalSize: 4},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 2,
+      parentId: -1,
+      name: 'B',
+      depth: 0,
+      totalSize: 8,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 3,
+      parentId: 1,
+      name: 'A3',
+      depth: 1,
+      totalSize: 4,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 4,
+      parentId: 2,
+      name: 'B4',
+      depth: 1,
+      totalSize: 4,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ];
 
   const mergedCallsites = mergeCallsites(callsites, 5);
@@ -17,11 +49,51 @@
 
 test('zeroCallsitesMerged2', () => {
   const callsites: CallsiteInfo[] = [
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 10},
-    {id: 2, parentId: -1, name: 'B', depth: 0, totalSize: 8},
-    {id: 3, parentId: 1, name: 'A3', depth: 1, totalSize: 6},
-    {id: 4, parentId: 1, name: 'A4', depth: 1, totalSize: 4},
-    {id: 5, parentId: 2, name: 'B5', depth: 1, totalSize: 8},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 2,
+      parentId: -1,
+      name: 'B',
+      depth: 0,
+      totalSize: 8,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 3,
+      parentId: 1,
+      name: 'A3',
+      depth: 1,
+      totalSize: 6,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 4,
+      parentId: 1,
+      name: 'A4',
+      depth: 1,
+      totalSize: 4,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 5,
+      parentId: 2,
+      name: 'B5',
+      depth: 1,
+      totalSize: 8,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ];
 
   const mergedCallsites = mergeCallsites(callsites, 5);
@@ -32,36 +104,172 @@
 
 test('twoCallsitesMerged', () => {
   const callsites: CallsiteInfo[] = [
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 10},
-    {id: 2, parentId: 1, name: 'A2', depth: 1, totalSize: 5},
-    {id: 3, parentId: 1, name: 'A3', depth: 1, totalSize: 5},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 2,
+      parentId: 1,
+      name: 'A2',
+      depth: 1,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 3,
+      parentId: 1,
+      name: 'A3',
+      depth: 1,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ];
 
   const mergedCallsites = mergeCallsites(callsites, 6);
 
   expect(mergedCallsites).toEqual([
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 10},
-    {id: 2, parentId: 1, name: 'A2', depth: 1, totalSize: 10},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 2,
+      parentId: 1,
+      name: 'A2',
+      depth: 1,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ]);
 });
 
 test('manyCallsitesMerged', () => {
   const callsites: CallsiteInfo[] = [
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 10},
-    {id: 2, parentId: 1, name: 'A2', depth: 1, totalSize: 5},
-    {id: 3, parentId: 1, name: 'A3', depth: 1, totalSize: 3},
-    {id: 4, parentId: 1, name: 'A4', depth: 1, totalSize: 1},
-    {id: 5, parentId: 1, name: 'A5', depth: 1, totalSize: 1},
-    {id: 6, parentId: 3, name: 'A36', depth: 2, totalSize: 1},
-    {id: 7, parentId: 4, name: 'A47', depth: 2, totalSize: 1},
-    {id: 8, parentId: 5, name: 'A58', depth: 2, totalSize: 1},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 2,
+      parentId: 1,
+      name: 'A2',
+      depth: 1,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 3,
+      parentId: 1,
+      name: 'A3',
+      depth: 1,
+      totalSize: 3,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 4,
+      parentId: 1,
+      name: 'A4',
+      depth: 1,
+      totalSize: 1,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 5,
+      parentId: 1,
+      name: 'A5',
+      depth: 1,
+      totalSize: 1,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 6,
+      parentId: 3,
+      name: 'A36',
+      depth: 2,
+      totalSize: 1,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 7,
+      parentId: 4,
+      name: 'A47',
+      depth: 2,
+      totalSize: 1,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 8,
+      parentId: 5,
+      name: 'A58',
+      depth: 2,
+      totalSize: 1,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ];
 
   const expectedMergedCallsites: CallsiteInfo[] = [
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 10},
-    {id: 2, parentId: 1, name: 'A2', depth: 1, totalSize: 5},
-    {id: 3, parentId: 1, name: 'A3', depth: 1, totalSize: 5},
-    {id: 6, parentId: 3, name: 'A36', depth: 2, totalSize: 3},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 2,
+      parentId: 1,
+      name: 'A2',
+      depth: 1,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 3,
+      parentId: 1,
+      name: 'A3',
+      depth: 1,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 6,
+      parentId: 3,
+      name: 'A36',
+      depth: 2,
+      totalSize: 3,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ];
 
   const mergedCallsites = mergeCallsites(callsites, 4);
@@ -74,23 +282,135 @@
 
 test('manyCallsitesMergedWithoutChildren', () => {
   const callsites: CallsiteInfo[] = [
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 5},
-    {id: 2, parentId: -1, name: 'B', depth: 0, totalSize: 5},
-    {id: 3, parentId: 1, name: 'A3', depth: 1, totalSize: 3},
-    {id: 4, parentId: 1, name: 'A4', depth: 1, totalSize: 1},
-    {id: 5, parentId: 1, name: 'A5', depth: 1, totalSize: 1},
-    {id: 6, parentId: 2, name: 'B6', depth: 1, totalSize: 5},
-    {id: 7, parentId: 4, name: 'A47', depth: 2, totalSize: 1},
-    {id: 8, parentId: 6, name: 'B68', depth: 2, totalSize: 1},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 2,
+      parentId: -1,
+      name: 'B',
+      depth: 0,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 3,
+      parentId: 1,
+      name: 'A3',
+      depth: 1,
+      totalSize: 3,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 4,
+      parentId: 1,
+      name: 'A4',
+      depth: 1,
+      totalSize: 1,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 5,
+      parentId: 1,
+      name: 'A5',
+      depth: 1,
+      totalSize: 1,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 6,
+      parentId: 2,
+      name: 'B6',
+      depth: 1,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 7,
+      parentId: 4,
+      name: 'A47',
+      depth: 2,
+      totalSize: 1,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 8,
+      parentId: 6,
+      name: 'B68',
+      depth: 2,
+      totalSize: 1,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ];
 
   const expectedMergedCallsites: CallsiteInfo[] = [
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 5},
-    {id: 2, parentId: -1, name: 'B', depth: 0, totalSize: 5},
-    {id: 3, parentId: 1, name: 'A3', depth: 1, totalSize: 5},
-    {id: 6, parentId: 2, name: 'B6', depth: 1, totalSize: 5},
-    {id: 7, parentId: 3, name: 'A47', depth: 2, totalSize: 1},
-    {id: 8, parentId: 6, name: 'B68', depth: 2, totalSize: 1},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 2,
+      parentId: -1,
+      name: 'B',
+      depth: 0,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 3,
+      parentId: 1,
+      name: 'A3',
+      depth: 1,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 6,
+      parentId: 2,
+      name: 'B6',
+      depth: 1,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 7,
+      parentId: 3,
+      name: 'A47',
+      depth: 2,
+      totalSize: 1,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 8,
+      parentId: 6,
+      name: 'B68',
+      depth: 2,
+      totalSize: 1,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ];
 
   const mergedCallsites = mergeCallsites(callsites, 4);
@@ -104,18 +424,90 @@
 
 test('smallCallsitesNotNextToEachOtherInArray', () => {
   const callsites: CallsiteInfo[] = [
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 20},
-    {id: 2, parentId: 1, name: 'A2', depth: 1, totalSize: 8},
-    {id: 3, parentId: 1, name: 'A3', depth: 1, totalSize: 1},
-    {id: 4, parentId: 1, name: 'A4', depth: 1, totalSize: 8},
-    {id: 5, parentId: 1, name: 'A5', depth: 1, totalSize: 3},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 20,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 2,
+      parentId: 1,
+      name: 'A2',
+      depth: 1,
+      totalSize: 8,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 3,
+      parentId: 1,
+      name: 'A3',
+      depth: 1,
+      totalSize: 1,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 4,
+      parentId: 1,
+      name: 'A4',
+      depth: 1,
+      totalSize: 8,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 5,
+      parentId: 1,
+      name: 'A5',
+      depth: 1,
+      totalSize: 3,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ];
 
   const expectedMergedCallsites: CallsiteInfo[] = [
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 20},
-    {id: 2, parentId: 1, name: 'A2', depth: 1, totalSize: 8},
-    {id: 3, parentId: 1, name: 'A3', depth: 1, totalSize: 4},
-    {id: 4, parentId: 1, name: 'A4', depth: 1, totalSize: 8},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 20,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 2,
+      parentId: 1,
+      name: 'A2',
+      depth: 1,
+      totalSize: 8,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 3,
+      parentId: 1,
+      name: 'A3',
+      depth: 1,
+      totalSize: 4,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 4,
+      parentId: 1,
+      name: 'A4',
+      depth: 1,
+      totalSize: 8,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ];
 
   const mergedCallsites = mergeCallsites(callsites, 4);
@@ -129,9 +521,33 @@
 
 test('smallCallsitesNotMerged', () => {
   const callsites: CallsiteInfo[] = [
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 10},
-    {id: 2, parentId: 1, name: 'A2', depth: 1, totalSize: 2},
-    {id: 3, parentId: 1, name: 'A3', depth: 1, totalSize: 2},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 2,
+      parentId: 1,
+      name: 'A2',
+      depth: 1,
+      totalSize: 2,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 3,
+      parentId: 1,
+      name: 'A3',
+      depth: 1,
+      totalSize: 2,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ];
 
   const mergedCallsites = mergeCallsites(callsites, 1);
@@ -141,53 +557,325 @@
 
 test('mergingRootCallsites', () => {
   const callsites: CallsiteInfo[] = [
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 10},
-    {id: 2, parentId: -1, name: 'B', depth: 0, totalSize: 2},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 2,
+      parentId: -1,
+      name: 'B',
+      depth: 0,
+      totalSize: 2,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ];
 
   const mergedCallsites = mergeCallsites(callsites, 20);
 
   expect(mergedCallsites).toEqual([
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 12},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 12,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ]);
 });
 
 test('largerFlamegraph', () => {
   const data: CallsiteInfo[] = [
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 60},
-    {id: 2, parentId: -1, name: 'B', depth: 0, totalSize: 40},
-    {id: 3, parentId: 1, name: 'A3', depth: 1, totalSize: 25},
-    {id: 4, parentId: 1, name: 'A4', depth: 1, totalSize: 15},
-    {id: 5, parentId: 1, name: 'A5', depth: 1, totalSize: 10},
-    {id: 6, parentId: 1, name: 'A6', depth: 1, totalSize: 10},
-    {id: 7, parentId: 2, name: 'B7', depth: 1, totalSize: 30},
-    {id: 8, parentId: 2, name: 'B8', depth: 1, totalSize: 10},
-    {id: 9, parentId: 3, name: 'A39', depth: 2, totalSize: 20},
-    {id: 10, parentId: 4, name: 'A410', depth: 2, totalSize: 10},
-    {id: 11, parentId: 4, name: 'A411', depth: 2, totalSize: 3},
-    {id: 12, parentId: 4, name: 'A412', depth: 2, totalSize: 2},
-    {id: 13, parentId: 5, name: 'A513', depth: 2, totalSize: 5},
-    {id: 14, parentId: 5, name: 'A514', depth: 2, totalSize: 5},
-    {id: 15, parentId: 7, name: 'A715', depth: 2, totalSize: 10},
-    {id: 16, parentId: 7, name: 'A716', depth: 2, totalSize: 5},
-    {id: 17, parentId: 7, name: 'A717', depth: 2, totalSize: 5},
-    {id: 18, parentId: 7, name: 'A718', depth: 2, totalSize: 5},
-    {id: 19, parentId: 9, name: 'A919', depth: 3, totalSize: 10},
-    {id: 20, parentId: 17, name: 'A1720', depth: 3, totalSize: 2},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 60,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 2,
+      parentId: -1,
+      name: 'B',
+      depth: 0,
+      totalSize: 40,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 3,
+      parentId: 1,
+      name: 'A3',
+      depth: 1,
+      totalSize: 25,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 4,
+      parentId: 1,
+      name: 'A4',
+      depth: 1,
+      totalSize: 15,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 5,
+      parentId: 1,
+      name: 'A5',
+      depth: 1,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 6,
+      parentId: 1,
+      name: 'A6',
+      depth: 1,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 7,
+      parentId: 2,
+      name: 'B7',
+      depth: 1,
+      totalSize: 30,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 8,
+      parentId: 2,
+      name: 'B8',
+      depth: 1,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 9,
+      parentId: 3,
+      name: 'A39',
+      depth: 2,
+      totalSize: 20,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 10,
+      parentId: 4,
+      name: 'A410',
+      depth: 2,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 11,
+      parentId: 4,
+      name: 'A411',
+      depth: 2,
+      totalSize: 3,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 12,
+      parentId: 4,
+      name: 'A412',
+      depth: 2,
+      totalSize: 2,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 13,
+      parentId: 5,
+      name: 'A513',
+      depth: 2,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 14,
+      parentId: 5,
+      name: 'A514',
+      depth: 2,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 15,
+      parentId: 7,
+      name: 'A715',
+      depth: 2,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 16,
+      parentId: 7,
+      name: 'A716',
+      depth: 2,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 17,
+      parentId: 7,
+      name: 'A717',
+      depth: 2,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 18,
+      parentId: 7,
+      name: 'A718',
+      depth: 2,
+      totalSize: 5,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 19,
+      parentId: 9,
+      name: 'A919',
+      depth: 3,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 20,
+      parentId: 17,
+      name: 'A1720',
+      depth: 3,
+      totalSize: 2,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ];
 
   const expectedData: CallsiteInfo[] = [
-    {id: 1, parentId: -1, name: 'A', depth: 0, totalSize: 60},
-    {id: 2, parentId: -1, name: 'B', depth: 0, totalSize: 40},
-    {id: 3, parentId: 1, name: 'A3', depth: 1, totalSize: 25},
-    {id: 4, parentId: 1, name: 'A4', depth: 1, totalSize: 35},
-    {id: 7, parentId: 2, name: 'B7', depth: 1, totalSize: 30},
-    {id: 8, parentId: 2, name: 'B8', depth: 1, totalSize: 10},
-    {id: 9, parentId: 3, name: 'A39', depth: 2, totalSize: 20},
-    {id: 10, parentId: 4, name: 'A410', depth: 2, totalSize: 25},
-    {id: 15, parentId: 7, name: 'A715', depth: 2, totalSize: 25},
-    {id: 19, parentId: 9, name: 'A919', depth: 3, totalSize: 10},
-    {id: 20, parentId: 15, name: 'A1720', depth: 3, totalSize: 2},
+    {
+      id: 1,
+      parentId: -1,
+      name: 'A',
+      depth: 0,
+      totalSize: 60,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 2,
+      parentId: -1,
+      name: 'B',
+      depth: 0,
+      totalSize: 40,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 3,
+      parentId: 1,
+      name: 'A3',
+      depth: 1,
+      totalSize: 25,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 4,
+      parentId: 1,
+      name: 'A4',
+      depth: 1,
+      totalSize: 35,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 7,
+      parentId: 2,
+      name: 'B7',
+      depth: 1,
+      totalSize: 30,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 8,
+      parentId: 2,
+      name: 'B8',
+      depth: 1,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 9,
+      parentId: 3,
+      name: 'A39',
+      depth: 2,
+      totalSize: 20,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 10,
+      parentId: 4,
+      name: 'A410',
+      depth: 2,
+      totalSize: 25,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 15,
+      parentId: 7,
+      name: 'A715',
+      depth: 2,
+      totalSize: 25,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 19,
+      parentId: 9,
+      name: 'A919',
+      depth: 3,
+      totalSize: 10,
+      selfSize: 0,
+      mapping: 'x'
+    },
+    {
+      id: 20,
+      parentId: 15,
+      name: 'A1720',
+      depth: 3,
+      totalSize: 2,
+      selfSize: 0,
+      mapping: 'x'
+    },
   ];
 
   // In this case, on depth 1, callsites A4, A5 and A6 should be merged and