Merge "ui: small fixes to service worker / offline support"
diff --git a/Android.bp b/Android.bp
index 1d28c13..abbbb9a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -21,6 +21,7 @@
     "src/trace_processor/metrics/android/android_batt.sql",
     "src/trace_processor/metrics/android/android_cpu.sql",
     "src/trace_processor/metrics/android/android_cpu_agg.sql",
+    "src/trace_processor/metrics/android/android_hwui_metric.sql",
     "src/trace_processor/metrics/android/android_ion.sql",
     "src/trace_processor/metrics/android/android_lmk.sql",
     "src/trace_processor/metrics/android/android_lmk_reason.sql",
@@ -2786,6 +2787,7 @@
     "protos/perfetto/metrics/android/batt_metric.proto",
     "protos/perfetto/metrics/android/cpu_metric.proto",
     "protos/perfetto/metrics/android/heap_profile_callsites.proto",
+    "protos/perfetto/metrics/android/hwui_metric.proto",
     "protos/perfetto/metrics/android/ion_metric.proto",
     "protos/perfetto/metrics/android/java_heap_stats.proto",
     "protos/perfetto/metrics/android/lmk_metric.proto",
@@ -2808,6 +2810,7 @@
     "external/perfetto/protos/perfetto/metrics/android/batt_metric.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/cpu_metric.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/heap_profile_callsites.pbzero.cc",
+    "external/perfetto/protos/perfetto/metrics/android/hwui_metric.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/ion_metric.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/java_heap_stats.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/lmk_metric.pbzero.cc",
@@ -2830,6 +2833,7 @@
     "protos/perfetto/metrics/android/batt_metric.proto",
     "protos/perfetto/metrics/android/cpu_metric.proto",
     "protos/perfetto/metrics/android/heap_profile_callsites.proto",
+    "protos/perfetto/metrics/android/hwui_metric.proto",
     "protos/perfetto/metrics/android/ion_metric.proto",
     "protos/perfetto/metrics/android/java_heap_stats.proto",
     "protos/perfetto/metrics/android/lmk_metric.proto",
@@ -2852,6 +2856,7 @@
     "external/perfetto/protos/perfetto/metrics/android/batt_metric.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/cpu_metric.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/heap_profile_callsites.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/hwui_metric.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/ion_metric.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/java_heap_stats.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/lmk_metric.pbzero.h",
diff --git a/BUILD b/BUILD
index 0cc3c33..3df1dca 100644
--- a/BUILD
+++ b/BUILD
@@ -672,6 +672,7 @@
         "src/trace_processor/metrics/android/android_batt.sql",
         "src/trace_processor/metrics/android/android_cpu.sql",
         "src/trace_processor/metrics/android/android_cpu_agg.sql",
+        "src/trace_processor/metrics/android/android_hwui_metric.sql",
         "src/trace_processor/metrics/android/android_ion.sql",
         "src/trace_processor/metrics/android/android_lmk.sql",
         "src/trace_processor/metrics/android/android_lmk_reason.sql",
@@ -709,6 +710,7 @@
 filegroup(
     name = "src_trace_processor_metrics_lib",
     srcs = [
+        "src/trace_processor/metrics/custom_options.descriptor.h",
         "src/trace_processor/metrics/metrics.cc",
         "src/trace_processor/metrics/metrics.descriptor.h",
         "src/trace_processor/metrics/metrics.h",
@@ -1772,6 +1774,7 @@
         "protos/perfetto/metrics/android/batt_metric.proto",
         "protos/perfetto/metrics/android/cpu_metric.proto",
         "protos/perfetto/metrics/android/heap_profile_callsites.proto",
+        "protos/perfetto/metrics/android/hwui_metric.proto",
         "protos/perfetto/metrics/android/ion_metric.proto",
         "protos/perfetto/metrics/android/java_heap_stats.proto",
         "protos/perfetto/metrics/android/lmk_metric.proto",
diff --git a/docs/trace-processor.md b/docs/trace-processor.md
index cea8846..532056b 100644
--- a/docs/trace-processor.md
+++ b/docs/trace-processor.md
@@ -8,8 +8,10 @@
 through SQL queries. The trace processor is used:
 * By the [Perfetto UI](https://ui.perfetto.dev/), in the form of a
   Web Assembly module.
-* Standalone, using the `trace_processor_shell` target
-  (`ninja -C out/xxx trace_processor_shell`).
+* Standalone:
+  * using the [prebuilt](http://get.perfetto.dev/trace_processor) binaries.
+  * using the `trace_processor_shell` target from source
+    (`ninja -C out/xxx trace_processor_shell`).
 * In internal pipelines for batch processing.
 
 Supported input formats:
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index 3d756d0..828a493 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -66,6 +66,10 @@
   build_with_chromium = false
 }
 
+if (!defined(is_nacl)) {
+  is_nacl = false
+}
+
 declare_args() {
   # The Android blueprint file generator set this to true (as well as
   # is_perfetto_build_generator). This is just about being built in the
@@ -135,7 +139,7 @@
   # system backend in the client library.
   # This includes building things that rely on POSIX sockets, this places
   # limitations on the supported operating systems.
-  enable_perfetto_ipc = !is_win && !is_fuchsia &&
+  enable_perfetto_ipc = !is_win && !is_fuchsia && !is_nacl &&
                         (perfetto_build_standalone ||
                          perfetto_build_with_android || build_with_chromium)
 
diff --git a/gn/standalone/BUILDCONFIG.gn b/gn/standalone/BUILDCONFIG.gn
index d980a05..3668c0f 100644
--- a/gn/standalone/BUILDCONFIG.gn
+++ b/gn/standalone/BUILDCONFIG.gn
@@ -36,10 +36,11 @@
 is_linux_host = host_os == "linux"
 is_mac = current_os == "mac"
 
-# Building with Windows/Fuchsia is currently only supported in the Chromium
+# Building with Windows/Fuchsia/nacl is currently only supported in the Chromium
 # tree so always set this to false.
 is_win = false
 is_fuchsia = false
+is_nacl = false
 
 if (target_cpu == "") {
   target_cpu = host_cpu
diff --git a/include/perfetto/ext/tracing/ipc/consumer_ipc_client.h b/include/perfetto/ext/tracing/ipc/consumer_ipc_client.h
index b39d17c..bb88073 100644
--- a/include/perfetto/ext/tracing/ipc/consumer_ipc_client.h
+++ b/include/perfetto/ext/tracing/ipc/consumer_ipc_client.h
@@ -20,6 +20,7 @@
 #include <memory>
 #include <string>
 
+#include "perfetto/base/export.h"
 #include "perfetto/ext/tracing/core/tracing_service.h"
 
 namespace perfetto {
@@ -31,7 +32,7 @@
 //   Consumer(s) of the tracing library.
 // Implemented in:
 //   src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
-class ConsumerIPCClient {
+class PERFETTO_EXPORT ConsumerIPCClient {
  public:
   // Connects to the producer port of the Service listening on the given
   // |service_sock_name|. If the connection is successful, the OnConnect()
diff --git a/include/perfetto/ext/tracing/ipc/producer_ipc_client.h b/include/perfetto/ext/tracing/ipc/producer_ipc_client.h
index 71b2431..6c1bdba 100644
--- a/include/perfetto/ext/tracing/ipc/producer_ipc_client.h
+++ b/include/perfetto/ext/tracing/ipc/producer_ipc_client.h
@@ -32,7 +32,7 @@
 //   Producer(s) of the tracing library.
 // Implemented in:
 //   src/tracing/ipc/producer/producer_ipc_client_impl.cc
-class ProducerIPCClient {
+class PERFETTO_EXPORT ProducerIPCClient {
  public:
   // Connects to the producer port of the Service listening on the given
   // |service_sock_name|. If the connection is successful, the OnConnect()
@@ -42,15 +42,15 @@
   // callbacks invoked on the Producer interface: no more Producer callbacks are
   // invoked immediately after its destruction and any pending callback will be
   // dropped.
-  PERFETTO_EXPORT static std::unique_ptr<TracingService::ProducerEndpoint>
-  Connect(const char* service_sock_name,
-          Producer*,
-          const std::string& producer_name,
-          base::TaskRunner*,
-          TracingService::ProducerSMBScrapingMode smb_scraping_mode =
-              TracingService::ProducerSMBScrapingMode::kDefault,
-          size_t shared_memory_size_hint_bytes = 0,
-          size_t shared_memory_page_size_hint_bytes = 0);
+  static std::unique_ptr<TracingService::ProducerEndpoint> Connect(
+      const char* service_sock_name,
+      Producer*,
+      const std::string& producer_name,
+      base::TaskRunner*,
+      TracingService::ProducerSMBScrapingMode smb_scraping_mode =
+          TracingService::ProducerSMBScrapingMode::kDefault,
+      size_t shared_memory_size_hint_bytes = 0,
+      size_t shared_memory_page_size_hint_bytes = 0);
 
  protected:
   ProducerIPCClient() = delete;
diff --git a/include/perfetto/ext/tracing/ipc/service_ipc_host.h b/include/perfetto/ext/tracing/ipc/service_ipc_host.h
index 86915af..ed3deb9 100644
--- a/include/perfetto/ext/tracing/ipc/service_ipc_host.h
+++ b/include/perfetto/ext/tracing/ipc/service_ipc_host.h
@@ -19,6 +19,7 @@
 
 #include <memory>
 
+#include "perfetto/base/export.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
 
@@ -34,7 +35,7 @@
 //   The code in the tracing client that will host the service e.g., traced.
 // Implemented in:
 //   src/tracing/ipc/service/service_ipc_host_impl.cc
-class ServiceIPCHost {
+class PERFETTO_EXPORT ServiceIPCHost {
  public:
   static std::unique_ptr<ServiceIPCHost> CreateInstance(base::TaskRunner*);
   virtual ~ServiceIPCHost();
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index 5f7e2b4..9b51e5b 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -19,6 +19,7 @@
     "batt_metric.proto",
     "cpu_metric.proto",
     "heap_profile_callsites.proto",
+    "hwui_metric.proto",
     "ion_metric.proto",
     "java_heap_stats.proto",
     "lmk_metric.proto",
diff --git a/protos/perfetto/metrics/android/hwui_metric.proto b/protos/perfetto/metrics/android/hwui_metric.proto
new file mode 100644
index 0000000..b2c11c8
--- /dev/null
+++ b/protos/perfetto/metrics/android/hwui_metric.proto
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package perfetto.protos;
+
+// Android HWUI graphics performance and graphics memory usage metrics.
+message ProcessRenderInfo {
+  // Name of the package launched
+  optional string process_name = 1;
+
+  // CPU time spent on RenderThread in milliseconds.
+  optional int64 rt_cpu_time_ms = 2;
+
+  // Number of frames drawn on RenderThread, followed by max/min/avg CPU time to draw a frame
+  // in nanoseconds.
+  optional uint32 draw_frame_count = 3;
+  optional int64 draw_frame_max = 4;
+  optional int64 draw_frame_min = 5;
+  optional double draw_frame_avg = 6;
+
+  // Number of GPU commands flushes and max/min/avg time per flush in nanoseconds.
+  optional uint32 flush_count = 7;
+  optional int64 flush_max = 8;
+  optional int64 flush_min = 9;
+  optional double flush_avg = 10;
+
+  // Number of View tree preparation counts and max/min/avg time to traverse the tree in
+  // nanoseconds.
+  optional uint32 prepare_tree_count = 11;
+  optional int64 prepare_tree_max = 12;
+  optional int64 prepare_tree_min = 13;
+  optional double prepare_tree_avg = 14;
+
+  // Number of times the GPU rendered a frame and max/min/avg time for GPU to finish rendering in
+  // in nanoseconds.
+  optional uint32 gpu_completion_count = 15;
+  optional int64 gpu_completion_max = 16;
+  optional int64 gpu_completion_min = 17;
+  optional double gpu_completion_avg = 18;
+
+  // Number of times a frame was recorded/serialized in a display list on the UI thread with
+  // max/min/avg time in nanoseconds.
+  optional uint32 ui_record_count = 19;
+  optional int64 ui_record_max = 20;
+  optional int64 ui_record_min = 21;
+  optional double ui_record_avg = 22;
+
+  // number of unique shader programs that were used to render frames, followed by total and average
+  // times to prepare a shader in nanoseconds.
+  optional uint32 shader_compile_count = 23;
+  optional int64 shader_compile_time = 24;
+  optional double shader_compile_avg = 25;
+  // number of shader programs loaded from the disk cache, followed by total time and average time
+  // to prepare a shader in nanoseconds.
+  optional uint32 cache_hit_count = 26;
+  optional int64 cache_hit_time = 27;
+  optional double cache_hit_avg = 28;
+  // number of shader programs compiled/linked, followed by total time and average time to prepare
+  // a shader in nanoseconds.
+  optional uint32 cache_miss_count = 29;
+  optional int64 cache_miss_time = 30;
+  optional double cache_miss_avg = 31;
+
+  // max/min/avg CPU memory used for graphics by HWUI at the end of a frame.
+  optional int64 graphics_cpu_mem_max = 32;
+  optional int64 graphics_cpu_mem_min = 33;
+  optional double graphics_cpu_mem_avg = 34;
+
+  // max/min/avg GPU memory used by HWUI at the end of a frame excluding textures.
+  optional int64 graphics_gpu_mem_max = 35;
+  optional int64 graphics_gpu_mem_min = 36;
+  optional double graphics_gpu_mem_avg = 37;
+
+  // max/min/avg memory used for GPU textures by HWUI at the end of a frame.
+  optional int64 texture_mem_max = 38;
+  optional int64 texture_mem_min = 39;
+  optional double texture_mem_avg = 40;
+
+  // max/min/avg memory used by HWUI at the end of a frame. This is a sum of previous 3 categories.
+  optional int64 all_mem_max = 41;
+  optional int64 all_mem_min = 42;
+  optional double all_mem_avg = 43;
+}
+
+message AndroidHwuiMetric {
+  //  HWUI metrics for processes that have a RenderThread.
+  repeated ProcessRenderInfo process_info = 1;
+}
diff --git a/protos/perfetto/metrics/custom_options.proto b/protos/perfetto/metrics/custom_options.proto
new file mode 100644
index 0000000..8f4bfbb
--- /dev/null
+++ b/protos/perfetto/metrics/custom_options.proto
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+import "google/protobuf/descriptor.proto";
+
+// Field options you can define on a metric. These options are only exposed as
+// part of JSON export.
+extend google.protobuf.FieldOptions {
+  optional string unit = 50001;
+  optional string improvementDirection = 50002;
+}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index 3a2b71b..16be108 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -28,6 +28,7 @@
 import "protos/perfetto/metrics/android/powrails_metric.proto";
 import "protos/perfetto/metrics/android/startup_metric.proto";
 import "protos/perfetto/metrics/android/heap_profile_callsites.proto";
+import "protos/perfetto/metrics/android/hwui_metric.proto";
 import "protos/perfetto/metrics/android/package_list.proto";
 import "protos/perfetto/metrics/android/unmapped_java_symbols.proto";
 import "protos/perfetto/metrics/android/unsymbolized_frames.proto";
@@ -51,7 +52,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 20
+// Next id: 21
 message TraceMetrics {
   reserved 4, 10, 13, 14;
 
@@ -103,6 +104,8 @@
   // Java type names that have no deobfuscation mappings.
   optional UnmappedJavaSymbols unmapped_java_symbols = 19;
 
+  optional AndroidHwuiMetric android_hwui_metric = 20;
+
   // Demo extensions.
   extensions 450 to 499;
 
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index f368c31..4cf3399 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -406,6 +406,94 @@
 
 // End of protos/perfetto/metrics/android/heap_profile_callsites.proto
 
+// Begin of protos/perfetto/metrics/android/hwui_metric.proto
+
+// Android HWUI graphics performance and graphics memory usage metrics.
+message ProcessRenderInfo {
+  // Name of the package launched
+  optional string process_name = 1;
+
+  // CPU time spent on RenderThread in milliseconds.
+  optional int64 rt_cpu_time_ms = 2;
+
+  // Number of frames drawn on RenderThread, followed by max/min/avg CPU time to draw a frame
+  // in nanoseconds.
+  optional uint32 draw_frame_count = 3;
+  optional int64 draw_frame_max = 4;
+  optional int64 draw_frame_min = 5;
+  optional double draw_frame_avg = 6;
+
+  // Number of GPU commands flushes and max/min/avg time per flush in nanoseconds.
+  optional uint32 flush_count = 7;
+  optional int64 flush_max = 8;
+  optional int64 flush_min = 9;
+  optional double flush_avg = 10;
+
+  // Number of View tree preparation counts and max/min/avg time to traverse the tree in
+  // nanoseconds.
+  optional uint32 prepare_tree_count = 11;
+  optional int64 prepare_tree_max = 12;
+  optional int64 prepare_tree_min = 13;
+  optional double prepare_tree_avg = 14;
+
+  // Number of times the GPU rendered a frame and max/min/avg time for GPU to finish rendering in
+  // in nanoseconds.
+  optional uint32 gpu_completion_count = 15;
+  optional int64 gpu_completion_max = 16;
+  optional int64 gpu_completion_min = 17;
+  optional double gpu_completion_avg = 18;
+
+  // Number of times a frame was recorded/serialized in a display list on the UI thread with
+  // max/min/avg time in nanoseconds.
+  optional uint32 ui_record_count = 19;
+  optional int64 ui_record_max = 20;
+  optional int64 ui_record_min = 21;
+  optional double ui_record_avg = 22;
+
+  // number of unique shader programs that were used to render frames, followed by total and average
+  // times to prepare a shader in nanoseconds.
+  optional uint32 shader_compile_count = 23;
+  optional int64 shader_compile_time = 24;
+  optional double shader_compile_avg = 25;
+  // number of shader programs loaded from the disk cache, followed by total time and average time
+  // to prepare a shader in nanoseconds.
+  optional uint32 cache_hit_count = 26;
+  optional int64 cache_hit_time = 27;
+  optional double cache_hit_avg = 28;
+  // number of shader programs compiled/linked, followed by total time and average time to prepare
+  // a shader in nanoseconds.
+  optional uint32 cache_miss_count = 29;
+  optional int64 cache_miss_time = 30;
+  optional double cache_miss_avg = 31;
+
+  // max/min/avg CPU memory used for graphics by HWUI at the end of a frame.
+  optional int64 graphics_cpu_mem_max = 32;
+  optional int64 graphics_cpu_mem_min = 33;
+  optional double graphics_cpu_mem_avg = 34;
+
+  // max/min/avg GPU memory used by HWUI at the end of a frame excluding textures.
+  optional int64 graphics_gpu_mem_max = 35;
+  optional int64 graphics_gpu_mem_min = 36;
+  optional double graphics_gpu_mem_avg = 37;
+
+  // max/min/avg memory used for GPU textures by HWUI at the end of a frame.
+  optional int64 texture_mem_max = 38;
+  optional int64 texture_mem_min = 39;
+  optional double texture_mem_avg = 40;
+
+  // max/min/avg memory used by HWUI at the end of a frame. This is a sum of previous 3 categories.
+  optional int64 all_mem_max = 41;
+  optional int64 all_mem_min = 42;
+  optional double all_mem_avg = 43;
+}
+
+message AndroidHwuiMetric {
+  //  HWUI metrics for processes that have a RenderThread.
+  repeated ProcessRenderInfo process_info = 1;
+}
+
+// End of protos/perfetto/metrics/android/hwui_metric.proto
+
 // Begin of protos/perfetto/metrics/android/package_list.proto
 
 message AndroidPackageList {
@@ -490,7 +578,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 20
+// Next id: 21
 message TraceMetrics {
   reserved 4, 10, 13, 14;
 
@@ -542,6 +630,8 @@
   // Java type names that have no deobfuscation mappings.
   optional UnmappedJavaSymbols unmapped_java_symbols = 19;
 
+  optional AndroidHwuiMetric android_hwui_metric = 20;
+
   // Demo extensions.
   extensions 450 to 499;
 
diff --git a/src/base/logging.cc b/src/base/logging.cc
index d38e263..b733988 100644
--- a/src/base/logging.cc
+++ b/src/base/logging.cc
@@ -125,11 +125,11 @@
   // to correlated events across differrent processses (e.g. traced and
   // traced_probes). The wall time % 1000 is good enough.
   char timestamp[32];
-  int t_ms = static_cast<int>(GetWallTimeMs().count());
-  int t_sec = t_ms / 1000;
+  uint32_t t_ms = static_cast<uint32_t>(GetWallTimeMs().count());
+  uint32_t t_sec = t_ms / 1000;
   t_ms -= t_sec * 1000;
   t_sec = t_sec % 1000;
-  snprintf(timestamp, sizeof(timestamp), "[%03d.%03d] ", t_sec, t_ms);
+  snprintf(timestamp, sizeof(timestamp), "[%03u.%03u] ", t_sec, t_ms);
 
   if (use_colors) {
     fprintf(stderr, "%s%s%s%s %s%s%s\n", kLightGray, timestamp, file_and_line,
diff --git a/src/perfetto_cmd/perfetto_config.descriptor.h b/src/perfetto_cmd/perfetto_config.descriptor.h
index c630e83..f9e012e 100644
--- a/src/perfetto_cmd/perfetto_config.descriptor.h
+++ b/src/perfetto_cmd/perfetto_config.descriptor.h
@@ -25,7 +25,7 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// f242f1ac484bbe7ba4c45e77b56ab588f8015196
+// d6628b15181dba5287e35b56b966b39ea93d42b1
 // SHA1(protos/perfetto/config/perfetto_config.proto)
 // 9bf7f741997f67724c7ee1b186b117708ac5228d
 
diff --git a/src/profiling/memory/unwinding.cc b/src/profiling/memory/unwinding.cc
index 6b030c0..ad18031 100644
--- a/src/profiling/memory/unwinding.cc
+++ b/src/profiling/memory/unwinding.cc
@@ -58,6 +58,8 @@
 namespace profiling {
 namespace {
 
+constexpr base::TimeMillis kMapsReparseInterval{500};
+
 constexpr size_t kMaxFrames = 1000;
 
 // We assume average ~300us per unwind. If we handle up to 1000 unwinds, this
@@ -204,8 +206,14 @@
   uint8_t error_code = 0;
   for (int attempt = 0; attempt < 2; ++attempt) {
     if (attempt > 0) {
+      if (metadata->last_maps_reparse_time + kMapsReparseInterval >
+          base::GetWallTimeMs()) {
+        PERFETTO_DLOG("Skipping reparse due to rate limit.");
+        break;
+      }
       PERFETTO_DLOG("Reparsing maps");
       metadata->ReparseMaps();
+      metadata->last_maps_reparse_time = base::GetWallTimeMs();
       // Regs got invalidated by libuwindstack's speculative jump.
       // Reset.
       ReadFromRawData(regs.get(), alloc_metadata->register_data);
diff --git a/src/profiling/memory/unwinding.h b/src/profiling/memory/unwinding.h
index 39216fe..a702c64 100644
--- a/src/profiling/memory/unwinding.h
+++ b/src/profiling/memory/unwinding.h
@@ -27,6 +27,7 @@
 #include <unwindstack/JitDebug.h>
 #endif
 
+#include "perfetto/base/time.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/thread_task_runner.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
@@ -129,6 +130,7 @@
   // The API of libunwindstack expects shared_ptr for Memory.
   std::shared_ptr<unwindstack::Memory> fd_mem;
   uint64_t reparses = 0;
+  base::TimeMillis last_maps_reparse_time{0};
 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
   std::unique_ptr<unwindstack::JitDebug> jit_debug;
   std::unique_ptr<unwindstack::DexFiles> dex_files;
diff --git a/src/protozero/test/example_proto/test_messages.descriptor.h b/src/protozero/test/example_proto/test_messages.descriptor.h
index 849203b..f27e4ec 100644
--- a/src/protozero/test/example_proto/test_messages.descriptor.h
+++ b/src/protozero/test/example_proto/test_messages.descriptor.h
@@ -25,7 +25,7 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// f242f1ac484bbe7ba4c45e77b56ab588f8015196
+// d6628b15181dba5287e35b56b966b39ea93d42b1
 // SHA1(src/protozero/test/example_proto/test_messages.proto)
 // bd59c7719b091c8277d2dce867d28dfa5b40bab2
 
diff --git a/src/trace_processor/containers/bit_vector_benchmark.cc b/src/trace_processor/containers/bit_vector_benchmark.cc
index b4a0c27..206bc5d 100644
--- a/src/trace_processor/containers/bit_vector_benchmark.cc
+++ b/src/trace_processor/containers/bit_vector_benchmark.cc
@@ -17,6 +17,7 @@
 #include <benchmark/benchmark.h>
 
 #include "src/trace_processor/containers/bit_vector.h"
+#include "src/trace_processor/containers/bit_vector_iterators.h"
 
 namespace {
 
@@ -27,15 +28,40 @@
 }
 
 void BitVectorArgs(benchmark::internal::Benchmark* b) {
-  b->Arg(64);
+  std::vector<int> set_percentages;
+  if (IsBenchmarkFunctionalOnly()) {
+    set_percentages = std::vector<int>{50};
+  } else {
+    set_percentages = std::vector<int>{0, 1, 5, 50, 95, 99, 100};
+  }
 
-  if (!IsBenchmarkFunctionalOnly()) {
-    b->Arg(512);
-    b->Arg(8192);
-    b->Arg(123456);
-    b->Arg(1234567);
+  for (int percentage : set_percentages) {
+    b->Args({64, percentage});
+
+    if (!IsBenchmarkFunctionalOnly()) {
+      b->Args({512, percentage});
+      b->Args({8192, percentage});
+      b->Args({123456, percentage});
+      b->Args({1234567, percentage});
+    }
   }
 }
+
+BitVector BvWithSizeAndSetPercentage(uint32_t size, uint32_t set_percentage) {
+  static constexpr uint32_t kRandomSeed = 29;
+  std::minstd_rand0 rnd_engine(kRandomSeed);
+
+  BitVector bv;
+  for (uint32_t i = 0; i < size; ++i) {
+    if (rnd_engine() % 100 < set_percentage) {
+      bv.AppendTrue();
+    } else {
+      bv.AppendFalse();
+    }
+  }
+  return bv;
+}
+
 }  // namespace
 
 static void BM_BitVectorAppendTrue(benchmark::State& state) {
@@ -61,15 +87,9 @@
   std::minstd_rand0 rnd_engine(kRandomSeed);
 
   uint32_t size = static_cast<uint32_t>(state.range(0));
+  uint32_t set_percentage = static_cast<uint32_t>(state.range(1));
 
-  BitVector bv;
-  for (uint32_t i = 0; i < size; ++i) {
-    if (rnd_engine() % 2) {
-      bv.AppendTrue();
-    } else {
-      bv.AppendFalse();
-    }
-  }
+  BitVector bv = BvWithSizeAndSetPercentage(size, set_percentage);
 
   static constexpr uint32_t kPoolSize = 1024 * 1024;
   std::vector<bool> bit_pool(kPoolSize);
@@ -93,15 +113,9 @@
   std::minstd_rand0 rnd_engine(kRandomSeed);
 
   uint32_t size = static_cast<uint32_t>(state.range(0));
+  uint32_t set_percentage = static_cast<uint32_t>(state.range(1));
 
-  BitVector bv;
-  for (uint32_t i = 0; i < size; ++i) {
-    if (rnd_engine() % 2) {
-      bv.AppendTrue();
-    } else {
-      bv.AppendFalse();
-    }
-  }
+  BitVector bv = BvWithSizeAndSetPercentage(size, set_percentage);
 
   static constexpr uint32_t kPoolSize = 1024 * 1024;
   std::vector<uint32_t> row_pool(kPoolSize);
@@ -123,16 +137,9 @@
   std::minstd_rand0 rnd_engine(kRandomSeed);
 
   uint32_t size = static_cast<uint32_t>(state.range(0));
+  uint32_t set_percentage = static_cast<uint32_t>(state.range(1));
 
-  BitVector bv;
-  for (uint32_t i = 0; i < size; ++i) {
-    if (rnd_engine() % 2) {
-      bv.AppendTrue();
-    } else {
-      bv.AppendFalse();
-    }
-  }
-
+  BitVector bv = BvWithSizeAndSetPercentage(size, set_percentage);
   static constexpr uint32_t kPoolSize = 1024 * 1024;
   std::vector<uint32_t> row_pool(kPoolSize);
   uint32_t set_bit_count = bv.GetNumBitsSet();
@@ -153,11 +160,12 @@
   std::minstd_rand0 rnd_engine(kRandomSeed);
 
   uint32_t size = static_cast<uint32_t>(state.range(0));
+  uint32_t set_percentage = static_cast<uint32_t>(state.range(1));
 
   uint32_t count = 0;
   BitVector bv;
   for (uint32_t i = 0; i < size; ++i) {
-    bool value = rnd_engine() % 2;
+    bool value = rnd_engine() % 100 < set_percentage;
     if (value) {
       bv.AppendTrue();
     } else {
@@ -205,11 +213,12 @@
   std::minstd_rand0 rnd_engine(kRandomSeed);
 
   uint32_t size = static_cast<uint32_t>(state.range(0));
+  uint32_t set_percentage = static_cast<uint32_t>(state.range(1));
 
   BitVector bv;
   BitVector picker;
   for (uint32_t i = 0; i < size; ++i) {
-    bool value = rnd_engine() % 2;
+    bool value = rnd_engine() % 100 < set_percentage;
     if (value) {
       bv.AppendTrue();
 
@@ -234,3 +243,16 @@
   }
 }
 BENCHMARK(BM_BitVectorUpdateSetBits)->Apply(BitVectorArgs);
+
+static void BM_BitVectorSetBitsIterator(benchmark::State& state) {
+  uint32_t size = static_cast<uint32_t>(state.range(0));
+  uint32_t set_percentage = static_cast<uint32_t>(state.range(1));
+
+  BitVector bv = BvWithSizeAndSetPercentage(size, set_percentage);
+  for (auto _ : state) {
+    for (auto it = bv.IterateSetBits(); it; it.Next()) {
+      benchmark::DoNotOptimize(it.index());
+    }
+  }
+}
+BENCHMARK(BM_BitVectorSetBitsIterator)->Apply(BitVectorArgs);
diff --git a/src/trace_processor/export_json.cc b/src/trace_processor/export_json.cc
index ed6e5f8..1e78477 100644
--- a/src/trace_processor/export_json.cc
+++ b/src/trace_processor/export_json.cc
@@ -27,6 +27,7 @@
 #include <json/writer.h>
 #include <stdio.h>
 
+#include <algorithm>
 #include <cstring>
 #include <deque>
 #include <limits>
@@ -187,26 +188,146 @@
       if (label_filter_ && !label_filter_("traceEvents"))
         return;
 
-      // Pop end events with smaller or equal timestamps.
-      PopEndEvents(event["ts"].asInt64());
-
       DoWriteEvent(event);
     }
 
-    void PushEndEvent(const Json::Value& event) {
+    void AddAsyncBeginEvent(const Json::Value& event) {
       if (label_filter_ && !label_filter_("traceEvents"))
         return;
 
-      // Pop any end events that end before the new one.
-      PopEndEvents(event["ts"].asInt64() - 1);
+      async_begin_events_.push_back(event);
+    }
 
+    void AddAsyncInstantEvent(const Json::Value& event) {
+      if (label_filter_ && !label_filter_("traceEvents"))
+        return;
+
+      async_instant_events_.push_back(event);
+    }
+
+    void AddAsyncEndEvent(const Json::Value& event) {
+      if (label_filter_ && !label_filter_("traceEvents"))
+        return;
+
+      async_end_events_.push_back(event);
+    }
+
+    void SortAndEmitAsyncEvents() {
       // Catapult doesn't handle out-of-order begin/end events well, especially
       // when their timestamps are the same, but their order is incorrect. Since
-      // our events are sorted by begin timestamp, we only have to reorder end
-      // events. We do this by buffering them into a stack, so that both begin &
-      // end events of potential child events have been emitted before we emit
-      // the end of a parent event.
-      end_events_.push_back(event);
+      // we process events sorted by begin timestamp, |async_begin_events_| and
+      // |async_instant_events_| are already sorted. We now only have to sort
+      // |async_end_events_| and merge-sort all events into a single sequence.
+
+      // Sort |async_end_events_|. Note that we should order by ascending
+      // timestamp, but in reverse-stable order. This way, a child slices's end
+      // is emitted before its parent's end event, even if both end events have
+      // the same timestamp. To accomplish this, we perform a stable sort in
+      // descending order and later iterate via reverse iterators.
+      struct {
+        bool operator()(const Json::Value& a, const Json::Value& b) const {
+          return a["ts"].asInt64() > b["ts"].asInt64();
+        }
+      } CompareEvents;
+      std::stable_sort(async_end_events_.begin(), async_end_events_.end(),
+                       CompareEvents);
+
+      // Merge sort by timestamp. If events share the same timestamp, prefer
+      // instant events, then end events, so that old slices close before new
+      // ones are opened, but instant events remain in their deepest nesting
+      // level.
+      auto instant_event_it = async_instant_events_.begin();
+      auto end_event_it = async_end_events_.rbegin();
+      auto begin_event_it = async_begin_events_.begin();
+
+      auto has_instant_event = instant_event_it != async_instant_events_.end();
+      auto has_end_event = end_event_it != async_end_events_.rend();
+      auto has_begin_event = begin_event_it != async_begin_events_.end();
+
+      auto emit_next_instant = [&instant_event_it, &has_instant_event, this]() {
+        DoWriteEvent(*instant_event_it);
+        instant_event_it++;
+        has_instant_event = instant_event_it != async_instant_events_.end();
+      };
+      auto emit_next_end = [&end_event_it, &has_end_event, this]() {
+        DoWriteEvent(*end_event_it);
+        end_event_it++;
+        has_end_event = end_event_it != async_end_events_.rend();
+      };
+      auto emit_next_begin = [&begin_event_it, &has_begin_event, this]() {
+        DoWriteEvent(*begin_event_it);
+        begin_event_it++;
+        has_begin_event = begin_event_it != async_begin_events_.end();
+      };
+
+      auto emit_next_instant_or_end = [&instant_event_it, &end_event_it,
+                                       &emit_next_instant, &emit_next_end]() {
+        if ((*instant_event_it)["ts"].asInt64() <=
+            (*end_event_it)["ts"].asInt64()) {
+          emit_next_instant();
+        } else {
+          emit_next_end();
+        }
+      };
+      auto emit_next_instant_or_begin = [&instant_event_it, &begin_event_it,
+                                         &emit_next_instant,
+                                         &emit_next_begin]() {
+        if ((*instant_event_it)["ts"].asInt64() <=
+            (*begin_event_it)["ts"].asInt64()) {
+          emit_next_instant();
+        } else {
+          emit_next_begin();
+        }
+      };
+      auto emit_next_end_or_begin = [&end_event_it, &begin_event_it,
+                                     &emit_next_end, &emit_next_begin]() {
+        if ((*end_event_it)["ts"].asInt64() <=
+            (*begin_event_it)["ts"].asInt64()) {
+          emit_next_end();
+        } else {
+          emit_next_begin();
+        }
+      };
+
+      // While we still have events in all iterators, consider each.
+      while (has_instant_event && has_end_event && has_begin_event) {
+        if ((*instant_event_it)["ts"].asInt64() <=
+            (*end_event_it)["ts"].asInt64()) {
+          emit_next_instant_or_begin();
+        } else {
+          emit_next_end_or_begin();
+        }
+      }
+
+      // Only instant and end events left.
+      while (has_instant_event && has_end_event) {
+        emit_next_instant_or_end();
+      }
+
+      // Only instant and begin events left.
+      while (has_instant_event && has_begin_event) {
+        emit_next_instant_or_begin();
+      }
+
+      // Only end and begin events left.
+      while (has_end_event && has_begin_event) {
+        emit_next_end_or_begin();
+      }
+
+      // Remaining instant events.
+      while (has_instant_event) {
+        emit_next_instant();
+      }
+
+      // Remaining end events.
+      while (has_end_event) {
+        emit_next_end();
+      }
+
+      // Remaining begin events.
+      while (has_begin_event) {
+        emit_next_begin();
+      }
     }
 
     void WriteMetadataEvent(const char* metadata_type,
@@ -300,7 +421,7 @@
     }
 
     void WriteFooter() {
-      PopEndEvents(std::numeric_limits<int64_t>::max());
+      SortAndEmitAsyncEvents();
 
       // Filter metadata entries.
       if (metadata_filter_) {
@@ -372,16 +493,6 @@
       first_event_ = false;
     }
 
-    void PopEndEvents(int64_t max_ts) {
-      while (!end_events_.empty()) {
-        int64_t ts = end_events_.back()["ts"].asInt64();
-        if (ts > max_ts)
-          break;
-        DoWriteEvent(end_events_.back());
-        end_events_.pop_back();
-      }
-    }
-
     OutputWriter* output_;
     ArgumentFilterPredicate argument_filter_;
     MetadataFilterPredicate metadata_filter_;
@@ -391,7 +502,9 @@
     Json::Value metadata_;
     std::string system_trace_data_;
     std::string user_trace_data_;
-    std::deque<Json::Value> end_events_;
+    std::vector<Json::Value> async_begin_events_;
+    std::vector<Json::Value> async_instant_events_;
+    std::vector<Json::Value> async_end_events_;
   };
 
   class ArgsBuilder {
@@ -794,10 +907,10 @@
 
         if (duration_ns == 0) {  // Instant async event.
           event["ph"] = "n";
-          writer_.WriteCommonEvent(event);
+          writer_.AddAsyncInstantEvent(event);
         } else {  // Async start and end.
           event["ph"] = "b";
-          writer_.WriteCommonEvent(event);
+          writer_.AddAsyncBeginEvent(event);
           // If the slice didn't finish, the duration may be negative. Don't
           // write the end event in this case.
           if (duration_ns > 0) {
@@ -812,7 +925,7 @@
                   (thread_instruction_count + thread_instruction_delta));
             }
             event["args"].clear();
-            writer_.PushEndEvent(event);
+            writer_.AddAsyncEndEvent(event);
           }
         }
       } else {
diff --git a/src/trace_processor/export_json_unittest.cc b/src/trace_processor/export_json_unittest.cc
index 2c9ec19..6d149e6 100644
--- a/src/trace_processor/export_json_unittest.cc
+++ b/src/trace_processor/export_json_unittest.cc
@@ -886,10 +886,13 @@
 TEST_F(ExportJsonTest, AsyncEvents) {
   const int64_t kTimestamp = 10000000;
   const int64_t kDuration = 100000;
+  const int64_t kTimestamp3 = 10005000;
+  const int64_t kDuration3 = 100000;
   const uint32_t kProcessID = 100;
   const char* kCategory = "cat";
   const char* kName = "name";
   const char* kName2 = "name2";
+  const char* kName3 = "name3";
   const char* kArgName = "arg_name";
   const int kArgValue = 123;
 
@@ -897,11 +900,16 @@
   StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
   StringId name_id = context_.storage->InternString(base::StringView(kName));
   StringId name2_id = context_.storage->InternString(base::StringView(kName2));
+  StringId name3_id = context_.storage->InternString(base::StringView(kName3));
 
   constexpr int64_t kSourceId = 235;
   TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
       name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
       /*source_scope=*/kNullStringId);
+  constexpr int64_t kSourceId2 = 236;
+  TrackId track2 = context_.track_tracker->InternLegacyChromeAsyncTrack(
+      name3_id, upid, kSourceId2, /*source_id_is_process_scoped=*/true,
+      /*source_scope=*/kNullStringId);
   context_.args_tracker->Flush();  // Flush track args.
 
   context_.storage->mutable_slice_table()->Insert(
@@ -919,6 +927,10 @@
   context_.storage->mutable_slice_table()->Insert(
       {kTimestamp, kDuration, track.value, cat_id, name2_id, 0, 0, 0});
 
+  // Another overlapping async event on a different track.
+  context_.storage->mutable_slice_table()->Insert(
+      {kTimestamp3, kDuration3, track2.value, cat_id, name3_id, 0, 0, 0});
+
   base::TempFile temp_file = base::TempFile::Create();
   FILE* output = fopen(temp_file.path().c_str(), "w+");
   util::Status status = ExportJson(context_.storage.get(), output);
@@ -926,7 +938,10 @@
   EXPECT_TRUE(status.ok());
 
   Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 4u);
+  EXPECT_EQ(result["traceEvents"].size(), 6u);
+
+  // Events should be sorted by timestamp, with child slice's end before its
+  // parent.
 
   Json::Value begin_event1 = result["traceEvents"][0];
   EXPECT_EQ(begin_event1["ph"].asString(), "b");
@@ -951,19 +966,31 @@
   EXPECT_FALSE(begin_event2.isMember("tts"));
   EXPECT_FALSE(begin_event2.isMember("use_async_tts"));
 
+  Json::Value begin_event3 = result["traceEvents"][2];
+  EXPECT_EQ(begin_event3["ph"].asString(), "b");
+  EXPECT_EQ(begin_event3["ts"].asInt64(), kTimestamp3 / 1000);
+  EXPECT_EQ(begin_event3["pid"].asInt(), static_cast<int>(kProcessID));
+  EXPECT_EQ(begin_event3["id2"]["local"].asString(), "0xec");
+  EXPECT_EQ(begin_event3["cat"].asString(), kCategory);
+  EXPECT_EQ(begin_event3["name"].asString(), kName3);
+  EXPECT_TRUE(begin_event3["args"].isObject());
+  EXPECT_EQ(begin_event3["args"].size(), 0u);
+  EXPECT_FALSE(begin_event3.isMember("tts"));
+  EXPECT_FALSE(begin_event3.isMember("use_async_tts"));
+
   Json::Value end_event2 = result["traceEvents"][3];
   EXPECT_EQ(end_event2["ph"].asString(), "e");
   EXPECT_EQ(end_event2["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
   EXPECT_EQ(end_event2["pid"].asInt(), static_cast<int>(kProcessID));
   EXPECT_EQ(end_event2["id2"]["local"].asString(), "0xeb");
   EXPECT_EQ(end_event2["cat"].asString(), kCategory);
-  EXPECT_EQ(end_event2["name"].asString(), kName);
+  EXPECT_EQ(end_event2["name"].asString(), kName2);
   EXPECT_TRUE(end_event2["args"].isObject());
   EXPECT_EQ(end_event2["args"].size(), 0u);
   EXPECT_FALSE(end_event2.isMember("tts"));
   EXPECT_FALSE(end_event2.isMember("use_async_tts"));
 
-  Json::Value end_event1 = result["traceEvents"][3];
+  Json::Value end_event1 = result["traceEvents"][4];
   EXPECT_EQ(end_event1["ph"].asString(), "e");
   EXPECT_EQ(end_event1["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
   EXPECT_EQ(end_event1["pid"].asInt(), static_cast<int>(kProcessID));
@@ -974,6 +1001,18 @@
   EXPECT_EQ(end_event1["args"].size(), 0u);
   EXPECT_FALSE(end_event1.isMember("tts"));
   EXPECT_FALSE(end_event1.isMember("use_async_tts"));
+
+  Json::Value end_event3 = result["traceEvents"][5];
+  EXPECT_EQ(end_event3["ph"].asString(), "e");
+  EXPECT_EQ(end_event3["ts"].asInt64(), (kTimestamp3 + kDuration3) / 1000);
+  EXPECT_EQ(end_event3["pid"].asInt(), static_cast<int>(kProcessID));
+  EXPECT_EQ(end_event3["id2"]["local"].asString(), "0xec");
+  EXPECT_EQ(end_event3["cat"].asString(), kCategory);
+  EXPECT_EQ(end_event3["name"].asString(), kName3);
+  EXPECT_TRUE(end_event3["args"].isObject());
+  EXPECT_EQ(end_event3["args"].size(), 0u);
+  EXPECT_FALSE(end_event3.isMember("tts"));
+  EXPECT_FALSE(end_event3.isMember("use_async_tts"));
 }
 
 TEST_F(ExportJsonTest, AsyncEventWithThreadTimestamp) {
diff --git a/src/trace_processor/heap_profile_tracker.cc b/src/trace_processor/heap_profile_tracker.cc
index 4bf0756..a2aff3a 100644
--- a/src/trace_processor/heap_profile_tracker.cc
+++ b/src/trace_processor/heap_profile_tracker.cc
@@ -24,6 +24,201 @@
 namespace perfetto {
 namespace trace_processor {
 
+namespace {
+struct MergedCallsite {
+  StringId frame_name;
+  StringId mapping_name;
+  base::Optional<uint32_t> parent_idx;
+  bool operator<(const MergedCallsite& o) const {
+    return std::tie(frame_name, mapping_name, parent_idx) <
+           std::tie(o.frame_name, o.mapping_name, o.parent_idx);
+  }
+};
+
+std::vector<MergedCallsite> GetMergedCallsites(TraceStorage* storage,
+                                               uint32_t callstack_row) {
+  const tables::StackProfileCallsiteTable& callsites_tbl =
+      storage->stack_profile_callsite_table();
+  const tables::StackProfileFrameTable& frames_tbl =
+      storage->stack_profile_frame_table();
+  const tables::SymbolTable& symbols_tbl = storage->symbol_table();
+  const tables::StackProfileMappingTable& mapping_tbl =
+      storage->stack_profile_mapping_table();
+
+  // TODO(fmayer): Clean up types and remove the static_cast.
+  uint32_t frame_idx = *frames_tbl.id().IndexOf(
+      FrameId(static_cast<uint32_t>(callsites_tbl.frame_id()[callstack_row])));
+
+  // TODO(fmayer): Clean up types and remove the static_cast.
+  uint32_t mapping_idx = *mapping_tbl.id().IndexOf(
+      MappingId(static_cast<uint32_t>(frames_tbl.mapping()[frame_idx])));
+  StringId mapping_name = mapping_tbl.name()[mapping_idx];
+
+  base::Optional<uint32_t> symbol_set_id =
+      frames_tbl.symbol_set_id()[frame_idx];
+
+  if (!symbol_set_id) {
+    StringId frame_name = frames_tbl.name()[frame_idx];
+    return {{frame_name, mapping_name, base::nullopt}};
+  }
+
+  std::vector<MergedCallsite> result;
+  // id == symbol_set_id for the bottommost frame.
+  // TODO(lalitm): Encode this optimization in the table and remove this
+  // custom optimization.
+  uint32_t symbol_set_idx = *symbols_tbl.id().IndexOf(SymbolId(*symbol_set_id));
+  for (uint32_t i = symbol_set_idx;
+       i < symbols_tbl.row_count() &&
+       symbols_tbl.symbol_set_id()[i] == *symbol_set_id;
+       ++i) {
+    result.emplace_back(
+        MergedCallsite{symbols_tbl.name()[i], mapping_name, base::nullopt});
+  }
+  return result;
+}
+}  // namespace
+
+std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> BuildNativeFlamegraph(
+    TraceStorage* storage,
+    UniquePid upid,
+    int64_t timestamp) {
+  const tables::HeapProfileAllocationTable& allocation_tbl =
+      storage->heap_profile_allocation_table();
+  const tables::StackProfileCallsiteTable& callsites_tbl =
+      storage->stack_profile_callsite_table();
+
+  StringId profile_type = storage->InternString("native");
+
+  std::vector<uint32_t> callsite_to_merged_callsite(callsites_tbl.row_count(),
+                                                    0);
+  std::map<MergedCallsite, uint32_t> merged_callsites_to_table_idx;
+
+  std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> tbl(
+      new tables::ExperimentalFlamegraphNodesTable(
+          storage->mutable_string_pool(), nullptr));
+
+  // FORWARD PASS:
+  // Aggregate callstacks by frame name / mapping name. Use symbolization data.
+  for (uint32_t i = 0; i < callsites_tbl.row_count(); ++i) {
+    base::Optional<uint32_t> parent_idx;
+    // TODO(fmayer): Clean up types and remove the conditional and static_cast.
+    if (callsites_tbl.parent_id()[i] != -1) {
+      auto parent_id = static_cast<uint32_t>(callsites_tbl.parent_id()[i]);
+      parent_idx = callsites_tbl.id().IndexOf(CallsiteId(parent_id));
+      parent_idx = callsite_to_merged_callsite[*parent_idx];
+      PERFETTO_CHECK(*parent_idx < i);
+    }
+
+    auto callsites = GetMergedCallsites(storage, i);
+    for (MergedCallsite& merged_callsite : callsites) {
+      merged_callsite.parent_idx = parent_idx;
+      auto it = merged_callsites_to_table_idx.find(merged_callsite);
+      if (it == merged_callsites_to_table_idx.end()) {
+        std::tie(it, std::ignore) = merged_callsites_to_table_idx.emplace(
+            merged_callsite, merged_callsites_to_table_idx.size());
+        tables::ExperimentalFlamegraphNodesTable::Row row{};
+        if (parent_idx) {
+          row.depth = tbl->depth()[*parent_idx] + 1;
+        } else {
+          row.depth = 0;
+        }
+        row.ts = timestamp;
+        row.upid = upid;
+        row.profile_type = profile_type;
+        row.name = merged_callsite.frame_name;
+        row.map_name = merged_callsite.mapping_name;
+        if (parent_idx)
+          row.parent_id = tbl->id()[*parent_idx].value;
+
+        parent_idx = *tbl->id().IndexOf(tbl->Insert(std::move(row)));
+        PERFETTO_CHECK(merged_callsites_to_table_idx.size() ==
+                       tbl->row_count());
+      }
+      parent_idx = it->second;
+    }
+    PERFETTO_CHECK(parent_idx);
+    callsite_to_merged_callsite[i] = *parent_idx;
+  }
+
+  // PASS OVER ALLOCATIONS:
+  // Aggregate allocations into the newly built tree.
+  auto filtered = allocation_tbl.Filter(
+      {allocation_tbl.ts().eq(timestamp), allocation_tbl.upid().eq(upid)});
+
+  if (filtered.row_count() == 0) {
+    return nullptr;
+  }
+
+  for (auto it = filtered.IterateRows(); it; it.Next()) {
+    int64_t size =
+        it.Get(static_cast<uint32_t>(
+                   tables::HeapProfileAllocationTable::ColumnIndex::size))
+            .long_value;
+    int64_t count =
+        it.Get(static_cast<uint32_t>(
+                   tables::HeapProfileAllocationTable::ColumnIndex::count))
+            .long_value;
+    int64_t callsite_id =
+        it
+            .Get(static_cast<uint32_t>(
+                tables::HeapProfileAllocationTable::ColumnIndex::callsite_id))
+            .long_value;
+
+    PERFETTO_CHECK((size < 0 && count < 0) || (size >= 0 && count >= 0));
+    uint32_t merged_idx =
+        callsite_to_merged_callsite[*callsites_tbl.id().IndexOf(
+            CallsiteId(static_cast<uint32_t>(callsite_id)))];
+    if (size > 0) {
+      // TODO(fmayer): Clean up types and remove the static_cast.
+      tbl->mutable_alloc_size()->Set(merged_idx,
+                                     tbl->alloc_size()[merged_idx] + size);
+      tbl->mutable_alloc_count()->Set(merged_idx,
+                                      tbl->alloc_count()[merged_idx] + count);
+    }
+
+    // TODO(fmayer): Clean up types and remove the static_cast.
+    tbl->mutable_size()->Set(merged_idx, tbl->size()[merged_idx] + size);
+    tbl->mutable_count()->Set(merged_idx, tbl->count()[merged_idx] + count);
+  }
+
+  // BACKWARD PASS:
+  // Propagate sizes to parents.
+  for (int64_t i = tbl->row_count() - 1; i >= 0; --i) {
+    uint32_t idx = static_cast<uint32_t>(i);
+
+    tbl->mutable_cumulative_size()->Set(
+        idx, tbl->cumulative_size()[idx] + tbl->size()[idx]);
+    tbl->mutable_cumulative_count()->Set(
+        idx, tbl->cumulative_count()[idx] + tbl->count()[idx]);
+
+    tbl->mutable_cumulative_alloc_size()->Set(
+        idx, tbl->cumulative_alloc_size()[idx] + tbl->alloc_size()[idx]);
+    tbl->mutable_cumulative_alloc_count()->Set(
+        idx, tbl->cumulative_alloc_count()[idx] + tbl->alloc_count()[idx]);
+
+    auto parent = tbl->parent_id()[idx];
+    if (parent) {
+      uint32_t parent_idx = *tbl->id().IndexOf(
+          tables::ExperimentalFlamegraphNodesTable::Id(*parent));
+      tbl->mutable_cumulative_size()->Set(
+          parent_idx,
+          tbl->cumulative_size()[parent_idx] + tbl->cumulative_size()[idx]);
+      tbl->mutable_cumulative_count()->Set(
+          parent_idx,
+          tbl->cumulative_count()[parent_idx] + tbl->cumulative_count()[idx]);
+
+      tbl->mutable_cumulative_alloc_size()->Set(
+          parent_idx, tbl->cumulative_alloc_size()[parent_idx] +
+                          tbl->cumulative_alloc_size()[idx]);
+      tbl->mutable_cumulative_alloc_count()->Set(
+          parent_idx, tbl->cumulative_alloc_count()[parent_idx] +
+                          tbl->cumulative_alloc_count()[idx]);
+    }
+  }
+
+  return tbl;
+}
+
 HeapProfileTracker::HeapProfileTracker(TraceProcessorContext* context)
     : context_(context), empty_(context_->storage->InternString({"", 0})) {}
 
diff --git a/src/trace_processor/heap_profile_tracker.h b/src/trace_processor/heap_profile_tracker.h
index 93a2440..53e7637 100644
--- a/src/trace_processor/heap_profile_tracker.h
+++ b/src/trace_processor/heap_profile_tracker.h
@@ -30,6 +30,11 @@
 namespace perfetto {
 namespace trace_processor {
 
+std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> BuildNativeFlamegraph(
+    TraceStorage* storage,
+    UniquePid upid,
+    int64_t timestamp);
+
 class TraceProcessorContext;
 
 class HeapProfileTracker {
diff --git a/src/trace_processor/importers/ftrace/rss_stat_tracker.cc b/src/trace_processor/importers/ftrace/rss_stat_tracker.cc
index db444a7..f536a02 100644
--- a/src/trace_processor/importers/ftrace/rss_stat_tracker.cc
+++ b/src/trace_processor/importers/ftrace/rss_stat_tracker.cc
@@ -69,24 +69,34 @@
 base::Optional<UniqueTid> RssStatTracker::FindUtidForMmId(int64_t mm_id,
                                                           bool is_curr,
                                                           uint32_t pid) {
-  auto it = mm_id_to_utid_.find(mm_id);
-  if (!is_curr) {
-    return it == mm_id_to_utid_.end() ? base::nullopt
-                                      : base::make_optional(it->second);
+  // If curr is true, we can just overwrite the state in the map and return
+  // the utid correspodning to |pid|.
+  if (is_curr) {
+    UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
+    mm_id_to_utid_[mm_id] = utid;
+    return utid;
   }
 
+  // If curr is false, try and lookup the utid we previously saw for this
+  // mm id.
+  auto it = mm_id_to_utid_.find(mm_id);
+  if (it == mm_id_to_utid_.end())
+    return base::nullopt;
+
+  // If the utid in the map is the same as our current utid but curr is false,
+  // that means we are in the middle of a process changing mm structs (i.e. in
+  // the middle of a vfork + exec). Therefore, we should discard the association
+  // of this vm struct with this thread.
   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
-  if (it != mm_id_to_utid_.end() && it->second != utid) {
-    // Since both of these structs have the same mm hash and both say that
-    // the mm hash is for the current project, we can assume they belong to
-    // the same process so we can associate them together.
-    // TODO(lalitm): investigate if it's possible for mm_id to be reused
-    // between different processes if we have pid reuse and get unlucky. If
-    // so, we'll need to do some more careful tracking here.
-    context_->process_tracker->AssociateThreads(it->second, utid);
+  if (it->second == utid) {
+    mm_id_to_utid_.erase(it);
+    return base::nullopt;
   }
-  mm_id_to_utid_[mm_id] = utid;
-  return utid;
+
+  // This case happens when a process is changing the VM of another process and
+  // we know that the utid corresponding to the target process. Just return that
+  // utid.
+  return it->second;
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h b/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h
index a088e87..adc3f2d 100644
--- a/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h
+++ b/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h
@@ -25,7 +25,7 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// f242f1ac484bbe7ba4c45e77b56ab588f8015196
+// d6628b15181dba5287e35b56b966b39ea93d42b1
 // SHA1(protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto)
 // b7dab60e553ebda32178373fa290f99afb94e55a
 
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.cc b/src/trace_processor/importers/proto/heap_graph_tracker.cc
index 124fab9..f96cf6e 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker.cc
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.cc
@@ -234,17 +234,17 @@
                                             // artificial root in the database.
 
     tables::ExperimentalFlamegraphNodesTable::Row alloc_row{
-        current_ts,
-        current_upid,
-        profile_type,
-        depth,
-        StringId::Raw(static_cast<uint32_t>(node.class_name)),
-        java_mapping,
+        current_ts, current_upid, profile_type, depth,
+        StringId::Raw(static_cast<uint32_t>(node.class_name)), java_mapping,
         static_cast<int64_t>(node.count),
         static_cast<int64_t>(node_to_cumulative_count[i]),
         static_cast<int64_t>(node.size),
         static_cast<int64_t>(node_to_cumulative_size[i]),
-        parent_id};
+        // For java dumps, set alloc_count == count, etc.
+        static_cast<int64_t>(node.count),
+        static_cast<int64_t>(node_to_cumulative_count[i]),
+        static_cast<int64_t>(node.size),
+        static_cast<int64_t>(node_to_cumulative_size[i]), parent_id};
     node_to_row_idx[i] = *tbl->id().IndexOf(tbl->Insert(alloc_row));
   }
   return tbl;
diff --git a/src/trace_processor/importers/proto/track_event.descriptor.h b/src/trace_processor/importers/proto/track_event.descriptor.h
index 998a400..e0237e6 100644
--- a/src/trace_processor/importers/proto/track_event.descriptor.h
+++ b/src/trace_processor/importers/proto/track_event.descriptor.h
@@ -25,7 +25,7 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// f242f1ac484bbe7ba4c45e77b56ab588f8015196
+// d6628b15181dba5287e35b56b966b39ea93d42b1
 // SHA1(protos/perfetto/trace/track_event/track_event.proto)
 // 1cd2627d7a57ddcf4e61b967cd255011bf3a09d5
 
diff --git a/src/trace_processor/metrics/BUILD.gn b/src/trace_processor/metrics/BUILD.gn
index 0d2db64..89febb8 100644
--- a/src/trace_processor/metrics/BUILD.gn
+++ b/src/trace_processor/metrics/BUILD.gn
@@ -32,6 +32,7 @@
   "android/android_startup_cpu.sql",
   "android/android_package_list.sql",
   "android/heap_profile_callsites.sql",
+  "android/android_hwui_metric.sql",
   "android/java_heap_stats.sql",
   "android/process_unagg_mem_view.sql",
   "android/process_mem.sql",
@@ -65,6 +66,7 @@
 if (enable_perfetto_trace_processor_sqlite) {
   source_set("lib") {
     sources = [
+      "custom_options.descriptor.h",
       "metrics.cc",
       "metrics.descriptor.h",
       "metrics.h",
diff --git a/src/trace_processor/metrics/android/android_hwui_metric.sql b/src/trace_processor/metrics/android/android_hwui_metric.sql
new file mode 100644
index 0000000..f7ba671
--- /dev/null
+++ b/src/trace_processor/metrics/android/android_hwui_metric.sql
@@ -0,0 +1,247 @@
+--
+-- Copyright 2020 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     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.
+--
+
+
+-- TOP processes that have a RenderThread, sorted by CPU time on RT
+CREATE VIEW hwui_processes AS
+SELECT
+  process.name as process_name,
+  process.upid as process_upid,
+  CAST(SUM(sched.dur) / 1e6 as INT64) as rt_cpu_time_ms,
+  thread.utid as render_thread_id
+FROM sched
+INNER JOIN thread ON (thread.utid = sched.utid AND thread.name='RenderThread')
+INNER JOIN process ON (process.upid = thread.upid)
+GROUP BY process.name
+ORDER BY rt_cpu_time_ms DESC;
+
+CREATE VIEW hwui_draw_frame AS
+SELECT
+  count(*) as draw_frame_count,
+  max(dur) as draw_frame_max,
+  min(dur) as draw_frame_min,
+  avg(dur) as draw_frame_avg,
+  thread_track.utid as render_thread_id
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+WHERE slice.name='DrawFrame' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_flush_commands AS
+SELECT
+  count(*) as flush_count,
+  max(dur) as flush_max,
+  min(dur) as flush_min,
+  avg(dur) as flush_avg,
+  thread_track.utid as render_thread_id
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+WHERE slice.name='flush commands' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_prepare_tree AS
+SELECT
+  count(*) as prepare_tree_count,
+  max(dur) as prepare_tree_max,
+  min(dur) as prepare_tree_min,
+  avg(dur) as prepare_tree_avg,
+  thread_track.utid as render_thread_id
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+WHERE slice.name='prepareTree' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_gpu_completion AS
+SELECT
+  count(*) as gpu_completion_count,
+  max(dur) as gpu_completion_max,
+  min(dur) as gpu_completion_min,
+  avg(dur) as gpu_completion_avg,
+  thread.upid as process_upid
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+INNER JOIN thread ON (thread.name='GPU completion' AND thread.utid = thread_track.utid)
+WHERE slice.name LIKE 'waiting for GPU completion%' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_ui_record AS
+SELECT
+  count(*) as ui_record_count,
+  max(dur) as ui_record_max,
+  min(dur) as ui_record_min,
+  avg(dur) as ui_record_avg,
+  thread.upid as process_upid
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+INNER JOIN thread ON (thread.name=substr(process.name,-15) AND thread.utid = thread_track.utid)
+INNER JOIN process ON (process.upid = thread.upid)
+WHERE slice.name='Record View#draw()' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_shader_compile AS
+SELECT
+  count(*) as shader_compile_count,
+  sum(dur) as shader_compile_time,
+  avg(dur) as shader_compile_avg,
+  thread_track.utid as render_thread_id
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+WHERE slice.name='shader_compile' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_cache_hit AS
+SELECT
+  count(*) as cache_hit_count,
+  sum(dur) as cache_hit_time,
+  avg(dur) as cache_hit_avg,
+  thread_track.utid as render_thread_id
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+WHERE slice.name='cache_hit' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_cache_miss AS
+SELECT
+  count(*) as cache_miss_count,
+  sum(dur) as cache_miss_time,
+  avg(dur) as cache_miss_avg,
+  thread_track.utid as render_thread_id
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+WHERE slice.name='cache_miss' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_graphics_cpu_mem AS
+SELECT
+  max(value) as graphics_cpu_mem_max,
+  min(value) as graphics_cpu_mem_min,
+  avg(value) as graphics_cpu_mem_avg,
+  process_counter_track.upid as process_upid
+FROM counter
+INNER JOIN process_counter_track ON (counter.track_id = process_counter_track.id)
+WHERE name='HWUI CPU Memory' AND counter.value >= 0
+GROUP BY process_counter_track.upid;
+
+CREATE VIEW hwui_graphics_gpu_mem AS
+SELECT
+  max(value) as graphics_gpu_mem_max,
+  min(value) as graphics_gpu_mem_min,
+  avg(value) as graphics_gpu_mem_avg,
+  process_counter_track.upid as process_upid
+FROM counter
+INNER JOIN process_counter_track ON (counter.track_id = process_counter_track.id)
+WHERE name='HWUI GPU Memory' AND counter.value >= 0
+GROUP BY process_counter_track.upid;
+
+CREATE VIEW hwui_texture_mem AS
+SELECT
+  max(value) as texture_mem_max,
+  min(value) as texture_mem_min,
+  avg(value) as texture_mem_avg,
+  process_counter_track.upid as process_upid
+FROM counter
+INNER JOIN process_counter_track ON (counter.track_id = process_counter_track.id)
+WHERE name='HWUI Texture Memory' AND counter.value >= 0
+GROUP BY process_counter_track.upid;
+
+CREATE VIEW hwui_all_mem AS
+SELECT
+  max(value) as all_mem_max,
+  min(value) as all_mem_min,
+  avg(value) as all_mem_avg,
+  process_counter_track.upid as process_upid
+FROM counter
+INNER JOIN process_counter_track ON (counter.track_id = process_counter_track.id)
+WHERE name='HWUI All Memory' AND counter.value >= 0
+GROUP BY process_counter_track.upid;
+
+CREATE VIEW android_hwui_metric_output AS
+SELECT AndroidHwuiMetric(
+  'process_info', (
+    SELECT RepeatedField(
+      ProcessRenderInfo(
+        'process_name', process_name,
+        'rt_cpu_time_ms', rt_cpu_time_ms,
+
+        'draw_frame_count', hwui_draw_frame.draw_frame_count,
+        'draw_frame_max', hwui_draw_frame.draw_frame_max,
+        'draw_frame_min', hwui_draw_frame.draw_frame_min,
+        'draw_frame_avg', hwui_draw_frame.draw_frame_avg,
+
+        'flush_count', hwui_flush_commands.flush_count,
+        'flush_max', hwui_flush_commands.flush_max,
+        'flush_min', hwui_flush_commands.flush_min,
+        'flush_avg', hwui_flush_commands.flush_avg,
+
+        'prepare_tree_count', hwui_prepare_tree.prepare_tree_count,
+        'prepare_tree_max', hwui_prepare_tree.prepare_tree_max,
+        'prepare_tree_min', hwui_prepare_tree.prepare_tree_min,
+        'prepare_tree_avg', hwui_prepare_tree.prepare_tree_avg,
+
+        'gpu_completion_count', hwui_gpu_completion.gpu_completion_count,
+        'gpu_completion_max', hwui_gpu_completion.gpu_completion_max,
+        'gpu_completion_min', hwui_gpu_completion.gpu_completion_min,
+        'gpu_completion_avg', hwui_gpu_completion.gpu_completion_avg,
+
+        'ui_record_count', hwui_ui_record.ui_record_count,
+        'ui_record_max', hwui_ui_record.ui_record_max,
+        'ui_record_min', hwui_ui_record.ui_record_min,
+        'ui_record_avg', hwui_ui_record.ui_record_avg,
+
+        'shader_compile_count', hwui_shader_compile.shader_compile_count,
+        'shader_compile_time', hwui_shader_compile.shader_compile_time,
+        'shader_compile_avg', hwui_shader_compile.shader_compile_avg,
+
+        'cache_hit_count', hwui_cache_hit.cache_hit_count,
+        'cache_hit_time', hwui_cache_hit.cache_hit_time,
+        'cache_hit_avg', hwui_cache_hit.cache_hit_avg,
+
+        'cache_miss_count', hwui_cache_miss.cache_miss_count,
+        'cache_miss_time', hwui_cache_miss.cache_miss_time,
+        'cache_miss_avg', hwui_cache_miss.cache_miss_avg,
+
+        'graphics_cpu_mem_max', CAST(hwui_graphics_cpu_mem.graphics_cpu_mem_max as INT64),
+        'graphics_cpu_mem_min', CAST(hwui_graphics_cpu_mem.graphics_cpu_mem_min as INT64),
+        'graphics_cpu_mem_avg', hwui_graphics_cpu_mem.graphics_cpu_mem_avg,
+
+        'graphics_gpu_mem_max', CAST(hwui_graphics_gpu_mem.graphics_gpu_mem_max as INT64),
+        'graphics_gpu_mem_min', CAST(hwui_graphics_gpu_mem.graphics_gpu_mem_min as INT64),
+        'graphics_gpu_mem_avg', hwui_graphics_gpu_mem.graphics_gpu_mem_avg,
+
+        'texture_mem_max', CAST(hwui_texture_mem.texture_mem_max as INT64),
+        'texture_mem_min', CAST(hwui_texture_mem.texture_mem_min as INT64),
+        'texture_mem_avg', hwui_texture_mem.texture_mem_avg,
+
+        'all_mem_max', CAST(hwui_all_mem.all_mem_max as INT64),
+        'all_mem_min', CAST(hwui_all_mem.all_mem_min as INT64),
+        'all_mem_avg', hwui_all_mem.all_mem_avg
+      )
+    )
+    FROM hwui_processes
+    LEFT JOIN hwui_draw_frame ON (hwui_draw_frame.render_thread_id = hwui_processes.render_thread_id)
+    LEFT JOIN hwui_flush_commands ON (hwui_flush_commands.render_thread_id = hwui_processes.render_thread_id)
+    LEFT JOIN hwui_prepare_tree ON (hwui_prepare_tree.render_thread_id = hwui_processes.render_thread_id)
+    LEFT JOIN hwui_gpu_completion ON (hwui_gpu_completion.process_upid = hwui_processes.process_upid)
+    LEFT JOIN hwui_ui_record ON (hwui_ui_record.process_upid = hwui_processes.process_upid)
+    LEFT JOIN hwui_shader_compile ON (hwui_shader_compile.render_thread_id = hwui_processes.render_thread_id)
+    LEFT JOIN hwui_cache_hit ON (hwui_cache_hit.render_thread_id = hwui_processes.render_thread_id)
+    LEFT JOIN hwui_cache_miss ON (hwui_cache_miss.render_thread_id = hwui_processes.render_thread_id)
+    LEFT JOIN hwui_graphics_cpu_mem ON (hwui_graphics_cpu_mem.process_upid = hwui_processes.process_upid)
+    LEFT JOIN hwui_graphics_gpu_mem ON (hwui_graphics_gpu_mem.process_upid = hwui_processes.process_upid)
+    LEFT JOIN hwui_texture_mem ON (hwui_texture_mem.process_upid = hwui_processes.process_upid)
+    LEFT JOIN hwui_all_mem ON (hwui_all_mem.process_upid = hwui_processes.process_upid)
+  )
+);
diff --git a/src/trace_processor/metrics/android/unmapped_java_symbols.sql b/src/trace_processor/metrics/android/unmapped_java_symbols.sql
index 7cc314f..d13d948 100644
--- a/src/trace_processor/metrics/android/unmapped_java_symbols.sql
+++ b/src/trace_processor/metrics/android/unmapped_java_symbols.sql
@@ -24,6 +24,7 @@
   AND INSTR(type_name, '.') = 0
   AND RTRIM(type_name, '[]') NOT IN ('byte', 'char', 'short', 'int', 'long', 'boolean', 'float', 'double')
   AND type_name NOT LIKE '$Proxy%'
+  AND LENGTH(type_name) > 0
 )
 SELECT upid, RepeatedField(type_name) AS types
 FROM distinct_unmapped_type_names GROUP BY 1;
@@ -35,6 +36,7 @@
   WHERE deobfuscated_type_name IS NULL
   AND field_name NOT LIKE '%.%.%'
   AND field_name NOT LIKE '$Proxy%'
+  AND LENGTH(field_name) > 0
 )
 SELECT upid, RepeatedField(field_name) AS fields
 FROM distinct_unmapped_field_names GROUP BY 1;
diff --git a/src/trace_processor/metrics/custom_options.descriptor.h b/src/trace_processor/metrics/custom_options.descriptor.h
new file mode 100644
index 0000000..3829d74
--- /dev/null
+++ b/src/trace_processor/metrics/custom_options.descriptor.h
@@ -0,0 +1,692 @@
+/*
+ * 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_METRICS_CUSTOM_OPTIONS_DESCRIPTOR_H_
+#define SRC_TRACE_PROCESSOR_METRICS_CUSTOM_OPTIONS_DESCRIPTOR_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <array>
+
+// This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
+
+// SHA1(tools/gen_binary_descriptors)
+// d6628b15181dba5287e35b56b966b39ea93d42b1
+// SHA1(protos/perfetto/metrics/custom_options.proto)
+// 074c971d85f72345988fb3279345cd6b3dabde9c
+
+// This is the proto CustomOptions encoded as a ProtoFileDescriptor to allow
+// for reflection without libprotobuf full/non-lite protos.
+
+namespace perfetto {
+
+constexpr std::array<uint8_t, 7803> kCustomOptionsDescriptor{
+    {0x0a, 0x9b, 0x3b, 0x0a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73,
+     0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x4d, 0x0a, 0x11, 0x46, 0x69,
+     0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
+     0x53, 0x65, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18,
+     0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+     0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x04, 0x66, 0x69, 0x6c,
+     0x65, 0x22, 0xe4, 0x04, 0x0a, 0x13, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+     0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a,
+     0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01,
+     0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12,
+     0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63,
+     0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70,
+     0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x70,
+     0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64,
+     0x65, 0x6e, 0x63, 0x79, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x05, 0x52, 0x10,
+     0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64,
+     0x65, 0x6e, 0x63, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x65, 0x61, 0x6b,
+     0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18,
+     0x0b, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0e, 0x77, 0x65, 0x61, 0x6b, 0x44,
+     0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x43, 0x0a,
+     0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70,
+     0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f,
+     0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+     0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
+     0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61,
+     0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e,
+     0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28,
+     0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
+     0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72,
+     0x6f, 0x74, 0x6f, 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70,
+     0x65, 0x12, 0x41, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
+     0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x6f,
+     0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+     0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63,
+     0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52,
+     0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x09,
+     0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20,
+     0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69,
+     0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
+     0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65,
+     0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
+     0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+     0x73, 0x12, 0x49, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
+     0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x09, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f,
+     0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f,
+     0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65,
+     0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6e, 0x74,
+     0x61, 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x79,
+     0x6e, 0x74, 0x61, 0x78, 0x22, 0xb9, 0x06, 0x0a, 0x0f, 0x44, 0x65, 0x73,
+     0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
+     0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x05,
+     0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
+     0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44,
+     0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f,
+     0x74, 0x6f, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x43, 0x0a,
+     0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06,
+     0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+     0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
+     0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+     0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74,
+     0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x6e, 0x65,
+     0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20,
+     0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+     0x6f, 0x52, 0x0a, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70,
+     0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x79,
+     0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67,
+     0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+     0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72,
+     0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x08,
+     0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x58, 0x0a, 0x0f,
+     0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61,
+     0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e,
+     0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+     0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x78, 0x74, 0x65,
+     0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0e,
+     0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e,
+     0x67, 0x65, 0x12, 0x44, 0x0a, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f,
+     0x64, 0x65, 0x63, 0x6c, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25,
+     0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+     0x6f, 0x52, 0x09, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x63, 0x6c,
+     0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
+     0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+     0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12,
+     0x55, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f,
+     0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32,
+     0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
+     0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65,
+     0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52,
+     0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e,
+     0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
+     0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28,
+     0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e,
+     0x61, 0x6d, 0x65, 0x1a, 0x7a, 0x0a, 0x0e, 0x45, 0x78, 0x74, 0x65, 0x6e,
+     0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a,
+     0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
+     0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65,
+     0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e,
+     0x64, 0x12, 0x40, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+     0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f,
+     0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+     0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61,
+     0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07,
+     0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x37, 0x0a, 0x0d, 0x52,
+     0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65,
+     0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
+     0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
+     0x03, 0x65, 0x6e, 0x64, 0x22, 0x7c, 0x0a, 0x15, 0x45, 0x78, 0x74, 0x65,
+     0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70,
+     0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69,
+     0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b,
+     0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74,
+     0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69,
+     0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70,
+     0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a,
+     0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x98,
+     0x06, 0x0a, 0x14, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63,
+     0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+     0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e,
+     0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
+     0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x05, 0x6c,
+     0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b,
+     0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+     0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x61, 0x62,
+     0x65, 0x6c, 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05,
+     0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+     0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
+     0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+     0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x79, 0x70, 0x65,
+     0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79,
+     0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
+     0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
+     0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x18,
+     0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e,
+     0x64, 0x65, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75,
+     0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01,
+     0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56,
+     0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x6e, 0x65, 0x6f,
+     0x66, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x09, 0x20, 0x01, 0x28,
+     0x05, 0x52, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x49, 0x6e, 0x64, 0x65,
+     0x78, 0x12, 0x1b, 0x0a, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x6e, 0x61,
+     0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6a, 0x73,
+     0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70,
+     0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32,
+     0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69,
+     0x6f, 0x6e, 0x73, 0x22, 0xb6, 0x02, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65,
+     0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55,
+     0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50,
+     0x45, 0x5f, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a,
+     0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10,
+     0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49,
+     0x4e, 0x54, 0x36, 0x34, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59,
+     0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x05, 0x12, 0x10,
+     0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44,
+     0x36, 0x34, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45,
+     0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x07, 0x12, 0x0d,
+     0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10,
+     0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54,
+     0x52, 0x49, 0x4e, 0x47, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59,
+     0x50, 0x45, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x0a, 0x12, 0x10,
+     0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41,
+     0x47, 0x45, 0x10, 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45,
+     0x5f, 0x42, 0x59, 0x54, 0x45, 0x53, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b,
+     0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10,
+     0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e,
+     0x55, 0x4d, 0x10, 0x0e, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45,
+     0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x0f, 0x12,
+     0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58,
+     0x45, 0x44, 0x36, 0x34, 0x10, 0x10, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59,
+     0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x11, 0x12,
+     0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54,
+     0x36, 0x34, 0x10, 0x12, 0x22, 0x43, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65,
+     0x6c, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4f,
+     0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x12, 0x0a,
+     0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49,
+     0x52, 0x45, 0x44, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42,
+     0x45, 0x4c, 0x5f, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10,
+     0x03, 0x22, 0x63, 0x0a, 0x14, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+     0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a,
+     0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65,
+     0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe3, 0x02, 0x0a, 0x13, 0x45,
+     0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
+     0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
+     0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+     0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+     0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73,
+     0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
+     0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x6f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
+     0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69,
+     0x6f, 0x6e, 0x73, 0x12, 0x5d, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72,
+     0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20,
+     0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e,
+     0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
+     0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65,
+     0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52,
+     0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e,
+     0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
+     0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28,
+     0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e,
+     0x61, 0x6d, 0x65, 0x1a, 0x3b, 0x0a, 0x11, 0x45, 0x6e, 0x75, 0x6d, 0x52,
+     0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65,
+     0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
+     0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
+     0x03, 0x65, 0x6e, 0x64, 0x22, 0x83, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x75,
+     0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
+     0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d,
+     0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e,
+     0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x07, 0x6f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21,
+     0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c,
+     0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x16, 0x53,
+     0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
+     0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x6d, 0x65, 0x74,
+     0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e,
+     0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+     0x6f, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x39, 0x0a,
+     0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72,
+     0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
+     0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x89, 0x02, 0x0a,
+     0x15, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72,
+     0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12,
+     0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+     0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e,
+     0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
+     0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70,
+     0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f,
+     0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
+     0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x38,
+     0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65,
+     0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
+     0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x10,
+     0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61,
+     0x6d, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
+     0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
+     0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x30,
+     0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72,
+     0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08,
+     0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x73, 0x65, 0x72,
+     0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67,
+     0x22, 0x92, 0x09, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x61, 0x76, 0x61,
+     0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x09, 0x52, 0x0b, 0x6a, 0x61, 0x76, 0x61, 0x50, 0x61, 0x63, 0x6b,
+     0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x6a, 0x61, 0x76, 0x61, 0x5f,
+     0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e,
+     0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6a,
+     0x61, 0x76, 0x61, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73,
+     0x73, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x6a, 0x61, 0x76,
+     0x61, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x66,
+     0x69, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
+     0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x6a, 0x61, 0x76, 0x61, 0x4d,
+     0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73,
+     0x12, 0x44, 0x0a, 0x1d, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e,
+     0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73,
+     0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x14, 0x20,
+     0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x19, 0x6a, 0x61, 0x76,
+     0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x71, 0x75,
+     0x61, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3a,
+     0x0a, 0x16, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e,
+     0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x74, 0x66, 0x38,
+     0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73,
+     0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x53, 0x74, 0x72, 0x69, 0x6e,
+     0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x74, 0x66, 0x38, 0x12, 0x53,
+     0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x5f, 0x66,
+     0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x67,
+     0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+     0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+     0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d,
+     0x6f, 0x64, 0x65, 0x3a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x52, 0x0b,
+     0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x46, 0x6f, 0x72, 0x12,
+     0x1d, 0x0a, 0x0a, 0x67, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
+     0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x6f, 0x50,
+     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x63, 0x63,
+     0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72,
+     0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a,
+     0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x63, 0x63, 0x47, 0x65,
+     0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
+     0x73, 0x12, 0x39, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65,
+     0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
+     0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
+     0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e,
+     0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
+     0x12, 0x35, 0x0a, 0x13, 0x70, 0x79, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72,
+     0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18,
+     0x12, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65,
+     0x52, 0x11, 0x70, 0x79, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53,
+     0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x14, 0x70,
+     0x68, 0x70, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73,
+     0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x2a, 0x20, 0x01, 0x28,
+     0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x12, 0x70, 0x68,
+     0x70, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76,
+     0x69, 0x63, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72,
+     0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08,
+     0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70,
+     0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2f, 0x0a, 0x10, 0x63,
+     0x63, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x72, 0x65,
+     0x6e, 0x61, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66,
+     0x61, 0x6c, 0x73, 0x65, 0x52, 0x0e, 0x63, 0x63, 0x45, 0x6e, 0x61, 0x62,
+     0x6c, 0x65, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x12, 0x2a, 0x0a, 0x11,
+     0x6f, 0x62, 0x6a, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x70,
+     0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52,
+     0x0f, 0x6f, 0x62, 0x6a, 0x63, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72,
+     0x65, 0x66, 0x69, 0x78, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x73, 0x68, 0x61,
+     0x72, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
+     0x18, 0x25, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x73, 0x68, 0x61,
+     0x72, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
+     0x21, 0x0a, 0x0c, 0x73, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x70, 0x72, 0x65,
+     0x66, 0x69, 0x78, 0x18, 0x27, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73,
+     0x77, 0x69, 0x66, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x28,
+     0x0a, 0x10, 0x70, 0x68, 0x70, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f,
+     0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09,
+     0x52, 0x0e, 0x70, 0x68, 0x70, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72,
+     0x65, 0x66, 0x69, 0x78, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x68, 0x70, 0x5f,
+     0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x29, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x68, 0x70, 0x4e, 0x61, 0x6d, 0x65,
+     0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x70, 0x68, 0x70,
+     0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6e, 0x61,
+     0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x2c, 0x20, 0x01, 0x28,
+     0x09, 0x52, 0x14, 0x70, 0x68, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
+     0x74, 0x61, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
+     0x21, 0x0a, 0x0c, 0x72, 0x75, 0x62, 0x79, 0x5f, 0x70, 0x61, 0x63, 0x6b,
+     0x61, 0x67, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72,
+     0x75, 0x62, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x58,
+     0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
+     0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7,
+     0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
+     0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69,
+     0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
+     0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0c, 0x4f, 0x70, 0x74, 0x69,
+     0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05,
+     0x53, 0x50, 0x45, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43,
+     0x4f, 0x44, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x02, 0x12, 0x10,
+     0x0a, 0x0c, 0x4c, 0x49, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49,
+     0x4d, 0x45, 0x10, 0x03, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80,
+     0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x26, 0x10, 0x27, 0x22, 0xd1, 0x02,
+     0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73,
+     0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x77, 0x69, 0x72, 0x65,
+     0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x14, 0x6d, 0x65,
+     0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x57, 0x69, 0x72, 0x65,
+     0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x4c, 0x0a, 0x1f, 0x6e, 0x6f,
+     0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x5f, 0x64, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x63,
+     0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a,
+     0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x1c, 0x6e, 0x6f, 0x53, 0x74,
+     0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
+     0x70, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72,
+     0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74,
+     0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
+     0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61,
+     0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, 0x65,
+     0x6e, 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
+     0x6d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x58, 0x0a, 0x14,
+     0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
+     0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20,
+     0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e,
+     0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74,
+     0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69,
+     0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80,
+     0x02, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10,
+     0x0a, 0x22, 0xe2, 0x03, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x63, 0x74,
+     0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e,
+     0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x06,
+     0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x52, 0x05, 0x63, 0x74, 0x79, 0x70,
+     0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18,
+     0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65,
+     0x64, 0x12, 0x47, 0x0a, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x18,
+     0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+     0x2e, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x09, 0x4a, 0x53, 0x5f,
+     0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x52, 0x06, 0x6a, 0x73, 0x74, 0x79,
+     0x70, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x05,
+     0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
+     0x04, 0x6c, 0x61, 0x7a, 0x79, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70,
+     0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+     0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65,
+     0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x04,
+     0x77, 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
+     0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x12,
+     0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72,
+     0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+     0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f,
+     0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+     0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
+     0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e,
+     0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79,
+     0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47,
+     0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, 0x52, 0x44, 0x10, 0x01,
+     0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50,
+     0x49, 0x45, 0x43, 0x45, 0x10, 0x02, 0x22, 0x35, 0x0a, 0x06, 0x4a, 0x53,
+     0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e,
+     0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4a,
+     0x53, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d,
+     0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10,
+     0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02,
+     0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x73, 0x0a, 0x0c, 0x4f, 0x6e,
+     0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58,
+     0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
+     0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7,
+     0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
+     0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69,
+     0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
+     0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80,
+     0x80, 0x80, 0x02, 0x22, 0xc0, 0x01, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d,
+     0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61,
+     0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02,
+     0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41,
+     0x6c, 0x69, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72,
+     0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
+     0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70,
+     0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75,
+     0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64,
+     0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03,
+     0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69,
+     0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
+     0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65,
+     0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+     0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02,
+     0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x9e, 0x01, 0x0a, 0x10, 0x45,
+     0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69,
+     0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65,
+     0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a,
+     0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72,
+     0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e,
+     0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f,
+     0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28,
+     0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e,
+     0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
+     0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+     0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22,
+     0x9c, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f,
+     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65,
+     0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01,
+     0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64,
+     0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a,
+     0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
+     0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07,
+     0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+     0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55,
+     0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64,
+     0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e,
+     0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80,
+     0x80, 0x02, 0x22, 0xe0, 0x02, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, 0x6f,
+     0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a,
+     0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21,
+     0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
+     0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12,
+     0x71, 0x0a, 0x11, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e,
+     0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x22, 0x20, 0x01,
+     0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74,
+     0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49,
+     0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65,
+     0x76, 0x65, 0x6c, 0x3a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54,
+     0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e,
+     0x52, 0x10, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63,
+     0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e,
+     0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f,
+     0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28,
+     0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e,
+     0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
+     0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+     0x22, 0x50, 0x0a, 0x10, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65,
+     0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x17, 0x0a, 0x13,
+     0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f,
+     0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a,
+     0x0f, 0x4e, 0x4f, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x45, 0x46, 0x46,
+     0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x44,
+     0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x2a, 0x09,
+     0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9a, 0x03,
+     0x0a, 0x13, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
+     0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
+     0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65,
+     0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+     0x6e, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x52, 0x04,
+     0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e,
+     0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
+     0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x64, 0x65, 0x6e,
+     0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
+     0x2c, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f,
+     0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20,
+     0x01, 0x28, 0x04, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76,
+     0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a,
+     0x12, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e,
+     0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
+     0x03, 0x52, 0x10, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49,
+     0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64,
+     0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+     0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+     0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74,
+     0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07,
+     0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+     0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67,
+     0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
+     0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x67, 0x67, 0x72,
+     0x65, 0x67, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x4a,
+     0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x1b,
+     0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x18,
+     0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x50,
+     0x61, 0x72, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x65, 0x78,
+     0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28,
+     0x08, 0x52, 0x0b, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
+     0x6f, 0x6e, 0x22, 0xa7, 0x02, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63,
+     0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a,
+     0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20,
+     0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f,
+     0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f,
+     0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c,
+     0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xce, 0x01, 0x0a, 0x08,
+     0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04,
+     0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02,
+     0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x04,
+     0x73, 0x70, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02,
+     0x10, 0x01, 0x52, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x12, 0x29, 0x0a, 0x10,
+     0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d,
+     0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f,
+     0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65,
+     0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x69, 0x6c,
+     0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
+     0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x72, 0x61, 0x69,
+     0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
+     0x12, 0x3a, 0x0a, 0x19, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f,
+     0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d,
+     0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52,
+     0x17, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x74, 0x61,
+     0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
+     0x22, 0xd1, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+     0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4d,
+     0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+     0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f,
+     0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+     0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f,
+     0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74,
+     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74,
+     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x6d, 0x0a, 0x0a, 0x41, 0x6e, 0x6e,
+     0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70,
+     0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10,
+     0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73,
+     0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02,
+     0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+     0x46, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x65, 0x67, 0x69,
+     0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x62, 0x65, 0x67,
+     0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20,
+     0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x42, 0x8f, 0x01, 0x0a,
+     0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, 0x10, 0x44, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x48, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
+     0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x64,
+     0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x3b, 0x64, 0x65,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0xf8, 0x01, 0x01, 0xa2,
+     0x02, 0x03, 0x47, 0x50, 0x42, 0xaa, 0x02, 0x1a, 0x47, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0xda,
+     0x01, 0x0a, 0x2c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+     0x63, 0x73, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70,
+     0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
+     0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
+     0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3a, 0x33, 0x0a,
+     0x04, 0x75, 0x6e, 0x69, 0x74, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+     0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+     0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+     0x18, 0xd1, 0x86, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x6e,
+     0x69, 0x74, 0x3a, 0x53, 0x0a, 0x14, 0x69, 0x6d, 0x70, 0x72, 0x6f, 0x76,
+     0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
+     0x6f, 0x6e, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65,
+     0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd2, 0x86,
+     0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x69, 0x6d, 0x70, 0x72, 0x6f,
+     0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74,
+     0x69, 0x6f, 0x6e}};
+
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_METRICS_CUSTOM_OPTIONS_DESCRIPTOR_H_
diff --git a/src/trace_processor/metrics/metrics.descriptor.h b/src/trace_processor/metrics/metrics.descriptor.h
index ad5b9b3..f703d36 100644
--- a/src/trace_processor/metrics/metrics.descriptor.h
+++ b/src/trace_processor/metrics/metrics.descriptor.h
@@ -25,16 +25,16 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// f242f1ac484bbe7ba4c45e77b56ab588f8015196
+// d6628b15181dba5287e35b56b966b39ea93d42b1
 // SHA1(protos/perfetto/metrics/metrics.proto)
-// e42eba6105b571de21762d07d9034b56d68faa06
+// 29445577a551e8035ed8e99128ae38062fa77ee0
 
 // 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, 11996> kMetricsDescriptor{
+constexpr std::array<uint8_t, 14060> kMetricsDescriptor{
     {0x0a, 0x94, 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,
@@ -706,177 +706,342 @@
      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, 0x0a, 0x88,
-     0x02, 0x0a, 0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
+     0x54, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x0a, 0x86,
+     0x0f, 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, 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, 0x0a, 0x9f, 0x03, 0x0a, 0x3b, 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, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6a,
-     0x61, 0x76, 0x61, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 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,
+     0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68,
+     0x77, 0x75, 0x69, 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, 0xe3, 0x0d,
+     0x0a, 0x11, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x6e,
+     0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x21, 0x0a, 0x0c, 0x70,
+     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+     0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65,
+     0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0e, 0x72, 0x74,
+     0x5f, 0x63, 0x70, 0x75, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x74, 0x43, 0x70,
+     0x75, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x64,
+     0x72, 0x61, 0x77, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f,
+     0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x64,
+     0x72, 0x61, 0x77, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x75, 0x6e,
+     0x74, 0x12, 0x24, 0x0a, 0x0e, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28,
+     0x03, 0x52, 0x0c, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x61, 0x6d, 0x65,
+     0x4d, 0x61, 0x78, 0x12, 0x24, 0x0a, 0x0e, 0x64, 0x72, 0x61, 0x77, 0x5f,
+     0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x0c, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x61,
+     0x6d, 0x65, 0x4d, 0x69, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x64, 0x72, 0x61,
+     0x77, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x76, 0x67, 0x18,
+     0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x64, 0x72, 0x61, 0x77, 0x46,
+     0x72, 0x61, 0x6d, 0x65, 0x41, 0x76, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x66,
+     0x6c, 0x75, 0x73, 0x68, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07,
+     0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x43,
+     0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x6c, 0x75, 0x73,
+     0x68, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x08, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a,
+     0x09, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x09,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x4d,
+     0x69, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x5f,
+     0x61, 0x76, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x66,
+     0x6c, 0x75, 0x73, 0x68, 0x41, 0x76, 0x67, 0x12, 0x2c, 0x0a, 0x12, 0x70,
+     0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f,
+     0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52,
+     0x10, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54, 0x72, 0x65, 0x65,
+     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x72, 0x65,
+     0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6d, 0x61,
+     0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x72, 0x65,
+     0x70, 0x61, 0x72, 0x65, 0x54, 0x72, 0x65, 0x65, 0x4d, 0x61, 0x78, 0x12,
+     0x28, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74,
+     0x72, 0x65, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28,
+     0x03, 0x52, 0x0e, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54, 0x72,
+     0x65, 0x65, 0x4d, 0x69, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x72, 0x65,
+     0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x61, 0x76,
+     0x67, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0e, 0x70, 0x72, 0x65,
+     0x70, 0x61, 0x72, 0x65, 0x54, 0x72, 0x65, 0x65, 0x41, 0x76, 0x67, 0x12,
+     0x30, 0x0a, 0x14, 0x67, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c,
+     0x65, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18,
+     0x0f, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x67, 0x70, 0x75, 0x43, 0x6f,
+     0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e,
+     0x74, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x6d,
+     0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x18,
+     0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x67, 0x70, 0x75, 0x43, 0x6f,
+     0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x12,
+     0x2c, 0x0a, 0x12, 0x67, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c,
+     0x65, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x11, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x10, 0x67, 0x70, 0x75, 0x43, 0x6f, 0x6d, 0x70,
+     0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x12, 0x2c, 0x0a,
+     0x12, 0x67, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74,
+     0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x12, 0x20, 0x01, 0x28,
+     0x01, 0x52, 0x10, 0x67, 0x70, 0x75, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
+     0x74, 0x69, 0x6f, 0x6e, 0x41, 0x76, 0x67, 0x12, 0x26, 0x0a, 0x0f, 0x75,
+     0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x75,
+     0x6e, 0x74, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x75, 0x69,
+     0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
+     0x22, 0x0a, 0x0d, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64,
+     0x5f, 0x6d, 0x61, 0x78, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b,
+     0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4d, 0x61, 0x78, 0x12,
+     0x22, 0x0a, 0x0d, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64,
+     0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b,
+     0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4d, 0x69, 0x6e, 0x12,
+     0x22, 0x0a, 0x0d, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64,
+     0x5f, 0x61, 0x76, 0x67, 0x18, 0x16, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b,
+     0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x41, 0x76, 0x67, 0x12,
+     0x30, 0x0a, 0x14, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f,
+     0x6d, 0x70, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18,
+     0x17, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x73, 0x68, 0x61, 0x64, 0x65,
+     0x72, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e,
+     0x74, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f,
+     0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65,
+     0x18, 0x18, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x73, 0x68, 0x61, 0x64,
+     0x65, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x54, 0x69, 0x6d,
+     0x65, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f,
+     0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x5f, 0x61, 0x76, 0x67, 0x18,
+     0x19, 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x73, 0x68, 0x61, 0x64, 0x65,
+     0x72, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x41, 0x76, 0x67, 0x12,
+     0x26, 0x0a, 0x0f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x68, 0x69, 0x74,
+     0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0d,
+     0x52, 0x0d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x48, 0x69, 0x74, 0x43, 0x6f,
+     0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65,
+     0x5f, 0x68, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1b, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x61, 0x63, 0x68, 0x65, 0x48, 0x69,
+     0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x61, 0x63,
+     0x68, 0x65, 0x5f, 0x68, 0x69, 0x74, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x1c,
+     0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x63, 0x61, 0x63, 0x68, 0x65, 0x48,
+     0x69, 0x74, 0x41, 0x76, 0x67, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x61, 0x63,
+     0x68, 0x65, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
+     0x74, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x63, 0x61, 0x63,
+     0x68, 0x65, 0x4d, 0x69, 0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
+     0x26, 0x0a, 0x0f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x6d, 0x69, 0x73,
+     0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x0d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x4d, 0x69, 0x73, 0x73, 0x54,
+     0x69, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65,
+     0x5f, 0x6d, 0x69, 0x73, 0x73, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x1f, 0x20,
+     0x01, 0x28, 0x01, 0x52, 0x0c, 0x63, 0x61, 0x63, 0x68, 0x65, 0x4d, 0x69,
+     0x73, 0x73, 0x41, 0x76, 0x67, 0x12, 0x2f, 0x0a, 0x14, 0x67, 0x72, 0x61,
+     0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65,
+     0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x20, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x43, 0x70, 0x75,
+     0x4d, 0x65, 0x6d, 0x4d, 0x61, 0x78, 0x12, 0x2f, 0x0a, 0x14, 0x67, 0x72,
+     0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x6d,
+     0x65, 0x6d, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x21, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x43, 0x70,
+     0x75, 0x4d, 0x65, 0x6d, 0x4d, 0x69, 0x6e, 0x12, 0x2f, 0x0a, 0x14, 0x67,
+     0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x70, 0x75, 0x5f,
+     0x6d, 0x65, 0x6d, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x22, 0x20, 0x01, 0x28,
+     0x01, 0x52, 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x43,
+     0x70, 0x75, 0x4d, 0x65, 0x6d, 0x41, 0x76, 0x67, 0x12, 0x2f, 0x0a, 0x14,
+     0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x67, 0x70, 0x75,
+     0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x23, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73,
+     0x47, 0x70, 0x75, 0x4d, 0x65, 0x6d, 0x4d, 0x61, 0x78, 0x12, 0x2f, 0x0a,
+     0x14, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x67, 0x70,
+     0x75, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x24, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
+     0x73, 0x47, 0x70, 0x75, 0x4d, 0x65, 0x6d, 0x4d, 0x69, 0x6e, 0x12, 0x2f,
+     0x0a, 0x14, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x67,
+     0x70, 0x75, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x25,
+     0x20, 0x01, 0x28, 0x01, 0x52, 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69,
+     0x63, 0x73, 0x47, 0x70, 0x75, 0x4d, 0x65, 0x6d, 0x41, 0x76, 0x67, 0x12,
+     0x26, 0x0a, 0x0f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x6d,
+     0x65, 0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x26, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x0d, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x4d, 0x65, 0x6d,
+     0x4d, 0x61, 0x78, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x65, 0x78, 0x74, 0x75,
+     0x72, 0x65, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x27,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72,
+     0x65, 0x4d, 0x65, 0x6d, 0x4d, 0x69, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x74,
+     0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x61,
+     0x76, 0x67, 0x18, 0x28, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0d, 0x74, 0x65,
+     0x78, 0x74, 0x75, 0x72, 0x65, 0x4d, 0x65, 0x6d, 0x41, 0x76, 0x67, 0x12,
+     0x1e, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d,
+     0x61, 0x78, 0x18, 0x29, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x61, 0x6c,
+     0x6c, 0x4d, 0x65, 0x6d, 0x4d, 0x61, 0x78, 0x12, 0x1e, 0x0a, 0x0b, 0x61,
+     0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x2a,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x61, 0x6c, 0x6c, 0x4d, 0x65, 0x6d,
+     0x4d, 0x69, 0x6e, 0x12, 0x1e, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x5f, 0x6d,
+     0x65, 0x6d, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x01,
+     0x52, 0x09, 0x61, 0x6c, 0x6c, 0x4d, 0x65, 0x6d, 0x41, 0x76, 0x67, 0x22,
+     0x5a, 0x0a, 0x11, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x48, 0x77,
+     0x75, 0x69, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x45, 0x0a, 0x0c,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f,
+     0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x6e, 0x64,
+     0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x0a, 0x88, 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, 0x72, 0x6f, 0x63,
-     0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x96, 0x02, 0x0a, 0x13, 0x55,
+     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, 0x0a, 0x9f,
+     0x03, 0x0a, 0x3b, 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, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6a, 0x61, 0x76, 0x61,
+     0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 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, 0x96, 0x02, 0x0a, 0x13, 0x55, 0x6e, 0x6d, 0x61,
+     0x70, 0x70, 0x65, 0x64, 0x4a, 0x61, 0x76, 0x61, 0x53, 0x79, 0x6d, 0x62,
+     0x6f, 0x6c, 0x73, 0x12, 0x5c, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65,
+     0x73, 0x73, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 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, 0x55,
      0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x4a, 0x61, 0x76, 0x61, 0x53,
-     0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x12, 0x5c, 0x0a, 0x0f, 0x70, 0x72,
-     0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
-     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, 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x4a, 0x61,
-     0x76, 0x61, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x2e, 0x50, 0x72,
-     0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73,
-     0x52, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x79, 0x6d,
-     0x62, 0x6f, 0x6c, 0x73, 0x1a, 0xa0, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f,
-     0x63, 0x65, 0x73, 0x73, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x12,
-     0x52, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d,
-     0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 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, 0x0f, 0x70, 0x72, 0x6f, 0x63,
-     0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12,
-     0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
-     0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65,
-     0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c,
-     0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09,
-     0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x0a,
-     0xfc, 0x01, 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, 0x0a, 0xf8, 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, 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, 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,
+     0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65,
+     0x73, 0x73, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x52, 0x0e, 0x70,
+     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
+     0x73, 0x1a, 0xa0, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
+     0x73, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x12, 0x52, 0x0a, 0x10,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61,
+     0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 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, 0x0a, 0xb4, 0x13, 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,
+     0x61, 0x74, 0x61, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+     0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09,
+     0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
+     0x03, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d,
+     0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e,
+     0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x66,
+     0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x0a, 0xfc, 0x01, 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, 0x0a,
+     0xf8, 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,
+     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, 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, 0x0a, 0xbb, 0x14, 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, 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, 0x6e, 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, 0x6c, 0x6d, 0x6b, 0x5f, 0x6d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
-     0x37, 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, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35, 0x70, 0x72,
+     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, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69,
-     0x6c, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x1a, 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, 0x1a, 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, 0x1a,
+     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, 0x6e, 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, 0x6c, 0x6d, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x37, 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, 0x72, 0x65,
+     0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 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,
+     0x1a, 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, 0x1a, 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, 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, 0x68, 0x77, 0x75, 0x69, 0x5f, 0x6d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
      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,
@@ -931,7 +1096,7 @@
      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,
-     0xda, 0x09, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74,
+     0xae, 0x0a, 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, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
@@ -1031,7 +1196,14 @@
      0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x4a, 0x61, 0x76, 0x61,
      0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x52, 0x13, 0x75, 0x6e, 0x6d,
      0x61, 0x70, 0x70, 0x65, 0x64, 0x4a, 0x61, 0x76, 0x61, 0x53, 0x79, 0x6d,
-     0x62, 0x6f, 0x6c, 0x73, 0x2a, 0x06, 0x08, 0xc2, 0x03, 0x10, 0xf4, 0x03,
+     0x62, 0x6f, 0x6c, 0x73, 0x12, 0x52, 0x0a, 0x13, 0x61, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x5f, 0x68, 0x77, 0x75, 0x69, 0x5f, 0x6d, 0x65, 0x74,
+     0x72, 0x69, 0x63, 0x18, 0x14, 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, 0x48,
+     0x77, 0x75, 0x69, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x11, 0x61,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x48, 0x77, 0x75, 0x69, 0x4d, 0x65,
+     0x74, 0x72, 0x69, 0x63, 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}};
diff --git a/src/trace_processor/proto_to_json.cc b/src/trace_processor/proto_to_json.cc
index 5b07889..e6f22e9 100644
--- a/src/trace_processor/proto_to_json.cc
+++ b/src/trace_processor/proto_to_json.cc
@@ -14,9 +14,14 @@
  * limitations under the License.
  */
 
+#include <vector>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/message.h>
 
 #include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_utils.h"
 #include "src/trace_processor/proto_to_json.h"
 
 namespace perfetto {
@@ -160,14 +165,162 @@
   return ret;
 }
 
+// This is a class helps avoid the situation where every function has to take
+// field_options_prototype as an argument, which becomes distracting.
+class OptionsConverter {
+ public:
+  explicit OptionsConverter(
+      const google::protobuf::Message* field_options_prototype)
+      : field_options_prototype_(field_options_prototype) {}
+
+  // Prints all field options for non-empty fields of a message. Example:
+  // --- Message definitions ---
+  // FooMessage {
+  //   repeated int64 foo = 1 [op1 = val1, op2 = val2];
+  //   optional BarMessage bar = 2 [op3 = val3];
+  // }
+  //
+  // BarMessage {
+  //   optional int64 baz = 1 [op4 = val4];
+  // }
+  // --- MessageInstance ---
+  // foo_msg = {  // (As JSON)
+  //   foo: [23, 24, 25],
+  //   bar: {
+  //     baz: 42
+  //   }
+  // }
+  // --- Output of MessageFieldOptionsToJson(foo_msg) ---
+  //   foo: {
+  //     __field_options: {
+  //       op1: val1,
+  //       op2: val2,
+  //     },
+  //     __repeated: true
+  //   }
+  //   bar: {
+  //     __field_options: {
+  //       op3 = val3,
+  //     },
+  //     baz: {
+  //       __field_options: {
+  //         op4 = val4
+  //       },
+  //     }
+  //   }
+  // --- Notes ---
+  // This function does not produce the surrounding braces for easier use in
+  // recursive use cases. The caller needs to surround the output with braces.
+  std::string MessageFieldOptionsToJson(
+      const google::protobuf::Message& message,
+      uint32_t indent) {
+    using google::protobuf::FieldDescriptor;
+    std::vector<const FieldDescriptor*> field_descs;
+    message.GetReflection()->ListFields(message, &field_descs);
+    std::vector<std::string> field_outputs;
+    for (auto* field_desc : field_descs) {
+      std::vector<std::string> field_entries;
+      if (HasFieldOptions(field_desc)) {
+        std::string options_entry;
+        options_entry +=
+            std::string(indent + 2, ' ') + R"("__field_options": )";
+        options_entry += FieldOptionsToJson(field_desc, indent + 4);
+        field_entries.push_back(std::move(options_entry));
+      }
+      std::string nested_fields =
+          NestedMessageFieldOptionsToJson(message, field_desc, indent + 2);
+      if (nested_fields != "") {
+        field_entries.push_back(std::move(nested_fields));
+      }
+      // We don't output annotations for a field if that field and all its
+      // descendants have no field options.
+      if (field_entries.size() > 0) {
+        if (field_desc->is_repeated()) {
+          field_entries.push_back(std::string(indent, ' ') +
+                                  R"("__repeated": true)");
+        }
+        std::string field_output;
+        const std::string& name = field_desc->is_extension()
+                                      ? field_desc->full_name()
+                                      : field_desc->name();
+        field_output += std::string(indent, ' ') + "\"" + name + "\": {\n";
+        field_output += base::Join(field_entries, ",\n") + "\n";
+        field_output += std::string(indent, ' ') + "}";
+        field_outputs.push_back(std::move(field_output));
+      }
+    }
+    return base::Join(field_outputs, ",\n");
+  }
+
+ private:
+  static bool HasFieldOptions(
+      const google::protobuf::FieldDescriptor* field_desc) {
+    return field_desc->options().ByteSizeLong() > 0;
+  }
+
+  std::string NestedMessageFieldOptionsToJson(
+      const google::protobuf::Message& message,
+      const google::protobuf::FieldDescriptor* field_desc,
+      uint32_t indent) {
+    using google::protobuf::FieldDescriptor;
+    if (field_desc->cpp_type() != FieldDescriptor::CppType::CPPTYPE_MESSAGE)
+      return "";
+    const auto* reflection = message.GetReflection();
+    const google::protobuf::Message& nested_message =
+        field_desc->is_repeated()
+            ? reflection->GetRepeatedMessage(message, field_desc, 0)
+            : reflection->GetMessage(message, field_desc);
+    return MessageFieldOptionsToJson(nested_message, indent);
+  }
+
+  std::string FieldOptionsToJson(
+      const google::protobuf::FieldDescriptor* field_desc,
+      uint32_t indent) {
+    PERFETTO_DCHECK(HasFieldOptions(field_desc));
+    std::unique_ptr<google::protobuf::Message> options(
+        field_options_prototype_->New());
+    // Field option extensions are compiled at runtime as opposed to being
+    // compiled in and being part of the generated pool, so the field option
+    // must be re-parsed as a dynamic message for the extensions to show up. If
+    // we do not do this, the extension fields remain "unknown fields" to the
+    // reflection API.
+    options->ParseFromString(field_desc->options().SerializeAsString());
+    return MessageToJson(*options, indent);
+  }
+
+  const google::protobuf::Message* field_options_prototype_;
+};
+
 }  // namespace
 
 std::string MessageToJson(const google::protobuf::Message& message,
                           uint32_t indent) {
-  return "{" + MessageFieldsToJson(message, indent + 2) + "\n" +
+  return "{" + MessageFieldsToJson(message, indent + 2) + '\n' +
          std::string(indent, ' ') + "}";
 }
 
+std::string MessageToJsonWithAnnotations(
+    const google::protobuf::Message& message,
+    const google::protobuf::Message* field_options_prototype,
+    uint32_t indent) {
+  std::string ret;
+  OptionsConverter options_converter(field_options_prototype);
+
+  ret = "{" + MessageFieldsToJson(message, indent + 2);
+  std::string annotation_fields =
+      options_converter.MessageFieldOptionsToJson(message, indent + 4);
+  if (annotation_fields != "") {
+    ret += ",\n";
+    ret += std::string(indent + 2, ' ') + "\"__annotations\": {\n";
+    ret += annotation_fields + "\n";
+    ret += std::string(indent + 2, ' ') + "}\n";
+  } else {
+    ret += "\n";
+  }
+  ret += std::string(indent, ' ') + "}\n";
+  return ret;
+}
+
 }  // namespace proto_to_json
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/proto_to_json.h b/src/trace_processor/proto_to_json.h
index f46f4c1..90cae5c 100644
--- a/src/trace_processor/proto_to_json.h
+++ b/src/trace_processor/proto_to_json.h
@@ -26,6 +26,11 @@
 std::string MessageToJson(const google::protobuf::Message& message,
                           uint32_t indent = 0);
 
+std::string MessageToJsonWithAnnotations(
+    const google::protobuf::Message& message,
+    const google::protobuf::Message* field_options_prototype,
+    uint32_t indent = 0);
+
 }  // namespace proto_to_json
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/sqlite/db_sqlite_table.cc b/src/trace_processor/sqlite/db_sqlite_table.cc
index 054f387..83789ea 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table.cc
@@ -222,9 +222,12 @@
     } else if (sqlite_utils::IsOpEq(c.op)) {
       // If there is only a single equality constraint, we have special logic
       // to sort by that column and then binary search if we see the constraint
-      // set often. Model this by dividing but the log of the number of rows as
+      // set often. Model this by dividing by the log of the number of rows as
       // a good approximation. Otherwise, we'll need to do a full table scan.
-      filter_cost += cs.size() == 1
+      // Alternatively, if the column is sorted, we can use the same binary
+      // search logic so we have the same low cost (even better because we don't
+      // have to sort at all).
+      filter_cost += cs.size() == 1 || col.IsSorted()
                          ? (2 * current_row_count) / log2(current_row_count)
                          : current_row_count;
 
diff --git a/src/trace_processor/sqlite/db_sqlite_table_unittest.cc b/src/trace_processor/sqlite/db_sqlite_table_unittest.cc
index 4f39839..2fbc3e4 100644
--- a/src/trace_processor/sqlite/db_sqlite_table_unittest.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table_unittest.cc
@@ -33,12 +33,18 @@
         Column("a", &a_, Column::Flag::kNoFlag, this, 1u, 0u));
     columns_.emplace_back(
         Column("sorted", &sorted_, Column::Flag::kSorted, this, 2u, 0u));
+    columns_.emplace_back(
+        Column("other", &other_, Column::Flag::kNoFlag, this, 3u, 0u));
+    columns_.emplace_back(
+        Column("other2", &other_, Column::Flag::kNoFlag, this, 4u, 0u));
   }
 
  private:
   StringPool pool_;
   SparseVector<uint32_t> a_;
   SparseVector<uint32_t> sorted_;
+  SparseVector<uint32_t> other_;
+  SparseVector<uint32_t> other2_;
 };
 
 TEST(DbSqliteTable, IdEqCheaperThanOtherEq) {
@@ -95,6 +101,27 @@
   ASSERT_GT(single_cost.rows, multi_cost.rows);
 }
 
+TEST(DbSqliteTable, MultiSortedEqCheaperThanMultiUnsortedEq) {
+  TestTable table(1234);
+
+  QueryConstraints sorted_eq;
+  sorted_eq.AddConstraint(2u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
+  sorted_eq.AddConstraint(3u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
+
+  auto sorted_cost = DbSqliteTable::EstimateCost(table, sorted_eq);
+
+  QueryConstraints unsorted_eq;
+  unsorted_eq.AddConstraint(3u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
+  unsorted_eq.AddConstraint(4u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
+
+  auto unsorted_cost = DbSqliteTable::EstimateCost(table, unsorted_eq);
+
+  // The number of rows should be the same but the cost of the sorted
+  // query should be less.
+  ASSERT_LT(sorted_cost.cost, unsorted_cost.cost);
+  ASSERT_EQ(sorted_cost.rows, unsorted_cost.rows);
+}
+
 TEST(DbSqliteTable, EmptyTableCosting) {
   TestTable table(0u);
 
diff --git a/src/trace_processor/sqlite_experimental_flamegraph_table.cc b/src/trace_processor/sqlite_experimental_flamegraph_table.cc
index 68dd50f..12a9bb6 100644
--- a/src/trace_processor/sqlite_experimental_flamegraph_table.cc
+++ b/src/trace_processor/sqlite_experimental_flamegraph_table.cc
@@ -17,6 +17,7 @@
 
 #include "src/trace_processor/sqlite_experimental_flamegraph_table.h"
 
+#include "src/trace_processor/heap_profile_tracker.h"
 #include "src/trace_processor/importers/proto/heap_graph_tracker.h"
 #include "src/trace_processor/trace_processor_context.h"
 
@@ -154,11 +155,14 @@
   // Get the input column values and compute the flamegraph using them.
   values_ = GetInputValues(qc, argv);
 
-  // TODO(fmayer): extend this to support native profile as well.
   if (values_.profile_type == "graph") {
     auto* tracker = HeapGraphTracker::GetOrCreate(context_);
     table_ = tracker->BuildFlamegraph(values_.ts, values_.upid);
   }
+  if (values_.profile_type == "native") {
+    table_ = BuildNativeFlamegraph(context_->storage.get(),
+                                   values_.upid, values_.ts);
+  }
 
   // table_ can be nullptr precisely where the constraints passed to us don't
   // make sense. Therefore, we can just return this to SQLite.
diff --git a/src/trace_processor/tables/profiler_tables.h b/src/trace_processor/tables/profiler_tables.h
index 5f529eb..04dae8d 100644
--- a/src/trace_processor/tables/profiler_tables.h
+++ b/src/trace_processor/tables/profiler_tables.h
@@ -100,6 +100,10 @@
   C(int64_t, cumulative_count)                                            \
   C(int64_t, size)                                                        \
   C(int64_t, cumulative_size)                                             \
+  C(int64_t, alloc_count)                                                 \
+  C(int64_t, cumulative_alloc_count)                                      \
+  C(int64_t, alloc_size)                                                  \
+  C(int64_t, cumulative_alloc_size)                                       \
   C(base::Optional<uint32_t>, parent_id)
 
 PERFETTO_TP_TABLE(PERFETTO_TP_EXPERIMENTAL_FLAMEGRAPH_NODES);
@@ -124,7 +128,7 @@
 #define PERFETTO_TP_HEAP_GRAPH_REFERENCE_DEF(NAME, PARENT, C) \
   NAME(HeapGraphReferenceTable, "heap_graph_reference")       \
   PERFETTO_TP_ROOT_TABLE(PARENT, C)                           \
-  C(int64_t, reference_set_id)                                \
+  C(int64_t, reference_set_id, Column::Flag::kSorted)         \
   C(int64_t, owner_id)                                        \
   C(int64_t, owned_id)                                        \
   C(StringPool::Id, field_name)                               \
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index 5b8cf62..594e13e 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -36,6 +36,7 @@
 #include "perfetto/ext/base/string_splitter.h"
 #include "perfetto/trace_processor/read_trace.h"
 #include "perfetto/trace_processor/trace_processor.h"
+#include "src/trace_processor/metrics/custom_options.descriptor.h"
 #include "src/trace_processor/metrics/metrics.descriptor.h"
 #include "src/trace_processor/proto_to_json.h"
 
@@ -322,12 +323,12 @@
   ErrorPrinter printer;
   google::protobuf::io::Tokenizer tokenizer(&stream, &printer);
 
-  auto* proto = desc_set.add_file();
+  auto* file_desc = desc_set.add_file();
   google::protobuf::compiler::Parser parser;
-  parser.Parse(&tokenizer, proto);
+  parser.Parse(&tokenizer, file_desc);
 
-  proto->set_name(BaseName(extend_metrics_proto));
-  pool->BuildFile(*proto);
+  file_desc->set_name(BaseName(extend_metrics_proto));
+  pool->BuildFile(*file_desc);
 
   std::vector<uint8_t> metric_proto;
   metric_proto.resize(static_cast<size_t>(desc_set.ByteSize()));
@@ -376,7 +377,13 @@
       break;
     }
     case OutputFormat::kJson: {
-      auto out = proto_to_json::MessageToJson(*metrics) + "\n";
+      // We need to instantiate field options from dynamic message factory
+      // because otherwise it cannot parse our custom extensions.
+      const google::protobuf::Message* field_options_prototype =
+          factory.GetPrototype(
+              pool.FindMessageTypeByName("google.protobuf.FieldOptions"));
+      auto out = proto_to_json::MessageToJsonWithAnnotations(
+          *metrics, field_options_prototype, 0);
       fwrite(out.c_str(), sizeof(char), out.size(), stdout);
       break;
     }
@@ -917,6 +924,16 @@
 
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 
+void ExtendPoolWithBinaryDescriptor(google::protobuf::DescriptorPool& pool,
+                                    const void* data,
+                                    int size) {
+  google::protobuf::FileDescriptorSet desc_set;
+  desc_set.ParseFromArray(data, size);
+  for (const auto& desc : desc_set.file()) {
+    pool.BuildFile(desc);
+  }
+}
+
 int TraceProcessorMain(int argc, char** argv) {
   CommandLineOptions options = ParseCommandLineOptions(argc, argv);
 
@@ -992,13 +1009,14 @@
   auto t_run_start = base::GetWallTimeNs();
 
   // Descriptor pool used for printing output as textproto.
-  google::protobuf::DescriptorPool pool;
-  google::protobuf::FileDescriptorSet root_desc_set;
-  root_desc_set.ParseFromArray(kMetricsDescriptor.data(),
-                               kMetricsDescriptor.size());
-  for (const auto& desc : root_desc_set.file()) {
-    pool.BuildFile(desc);
-  }
+  // Building on top of generated pool so default protos in
+  // google.protobuf.descriptor.proto are available.
+  google::protobuf::DescriptorPool pool(
+      google::protobuf::DescriptorPool::generated_pool());
+  ExtendPoolWithBinaryDescriptor(pool, kMetricsDescriptor.data(),
+                                 kMetricsDescriptor.size());
+  ExtendPoolWithBinaryDescriptor(pool, kCustomOptionsDescriptor.data(),
+                                 kCustomOptionsDescriptor.size());
 
   if (!options.metric_extra.empty()) {
     util::Status status = RegisterExtraMetrics(options.metric_extra, "");
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index db6ac60..67c6358 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -75,6 +75,8 @@
 
 using FrameId = tables::StackProfileFrameTable::Id;
 
+using SymbolId = tables::SymbolTable::Id;
+
 using CallsiteId = tables::StackProfileCallsiteTable::Id;
 
 using MetadataId = tables::MetadataTable::Id;
diff --git a/test/synth_common.py b/test/synth_common.py
index f950294..09bf07e 100644
--- a/test/synth_common.py
+++ b/test/synth_common.py
@@ -19,6 +19,8 @@
 from google.protobuf.pyext import _message
 
 CLONE_THREAD = 0x00010000
+CLONE_VFORK = 0x00004000
+CLONE_VM = 0x00000100
 
 
 class Trace(object):
diff --git a/test/trace_processor/heap_profile_flamegraph.sql b/test/trace_processor/heap_profile_flamegraph.sql
new file mode 100644
index 0000000..fa90b15
--- /dev/null
+++ b/test/trace_processor/heap_profile_flamegraph.sql
@@ -0,0 +1 @@
+select * from experimental_flamegraph(605908369259172, 1, 'native')  limit 10;
diff --git a/test/trace_processor/heap_profile_flamegraph_system-server-native-profile.out b/test/trace_processor/heap_profile_flamegraph_system-server-native-profile.out
new file mode 100644
index 0000000..42ab65d
--- /dev/null
+++ b/test/trace_processor/heap_profile_flamegraph_system-server-native-profile.out
@@ -0,0 +1,11 @@
+"id","type","depth","name","map_name","count","cumulative_count","size","cumulative_size","alloc_count","cumulative_alloc_count","alloc_size","cumulative_alloc_size","parent_id"
+0,"experimental_flamegraph_nodes",0,"__start_thread","/apex/com.android.runtime/lib64/bionic/libc.so",0,8,0,84848,0,210,0,1084996,"[NULL]"
+1,"experimental_flamegraph_nodes",1,"_ZL15__pthread_startPv","/apex/com.android.runtime/lib64/bionic/libc.so",0,8,0,84848,0,210,0,1084996,0
+2,"experimental_flamegraph_nodes",2,"_ZN7android14AndroidRuntime15javaThreadShellEPv","/system/lib64/libandroid_runtime.so",0,5,0,27704,0,77,0,348050,1
+3,"experimental_flamegraph_nodes",3,"_ZN7android6Thread11_threadLoopEPv","/system/lib64/libutils.so",0,5,0,27704,0,77,0,348050,2
+4,"experimental_flamegraph_nodes",4,"_ZN7android10PoolThread10threadLoopEv","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,3
+5,"experimental_flamegraph_nodes",5,"_ZN7android14IPCThreadState14joinThreadPoolEb","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,4
+6,"experimental_flamegraph_nodes",6,"_ZN7android14IPCThreadState20getAndExecuteCommandEv","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,5
+7,"experimental_flamegraph_nodes",7,"_ZN7android14IPCThreadState14executeCommandEi","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,6
+8,"experimental_flamegraph_nodes",8,"_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,7
+9,"experimental_flamegraph_nodes",9,"_ZN11JavaBBinder10onTransactEjRKN7android6ParcelEPS1_j","/system/lib64/libandroid_runtime.so",0,0,0,0,0,60,0,262730,8
diff --git a/test/trace_processor/index b/test/trace_processor/index
index 612d838..afd8064 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -57,6 +57,8 @@
 
 # Rss stats
 rss_stat_mm_id.py rss_stat.sql rss_stat_mm_id.out
+rss_stat_mm_id_clone.py rss_stat.sql rss_stat_mm_id_clone.out
+rss_stat_mm_id_reuse.py rss_stat.sql rss_stat_mm_id_reuse.out
 rss_stat_legacy.py rss_stat.sql rss_stat_legacy.out
 
 # Memory counters
@@ -152,6 +154,7 @@
 heap_graph_interleaved.textproto heap_graph_object.sql heap_graph_interleaved_object.out
 heap_graph_interleaved.textproto heap_graph_reference.sql heap_graph_interleaved_reference.out
 ../data/system-server-heap-graph.pftrace heap_graph_flamegraph.sql heap_graph_flamegraph_system-server-heap-graph.out
+../data/system-server-native-profile heap_profile_flamegraph.sql heap_profile_flamegraph_system-server-native-profile.out
 
 # TrackEvent tests.
 track_event_same_tids.textproto process_tracking.sql track_event_same_tids_threads.out
diff --git a/test/trace_processor/rss_stat_mm_id copy.py b/test/trace_processor/rss_stat_mm_id copy.py
new file mode 100644
index 0000000..d2b5e5a
--- /dev/null
+++ b/test/trace_processor/rss_stat_mm_id copy.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This synthetic trace tests handling of the mm_id field in the rss_stat
+# event.
+
+from os import sys, path
+
+sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+import synth_common
+
+trace = synth_common.create_trace()
+
+trace.add_process_tree_packet(ts=1)
+trace.add_process(10, 0, "process")
+
+trace.add_ftrace_packet(0)
+
+# Create a new child process (treated internally as a thread) of kthreadd.
+trace.add_newtask(ts=50, tid=2, new_tid=3, new_comm="kthread_child", flags=0)
+
+# Add an event on tid 3 which affects its own rss.
+trace.add_rss_stat(ts=90, tid=3, member=0, size=9, mm_id=4321, curr=True)
+
+# Try to add an event for tid 10. However, as we've not seen an event
+# with curr == True for tid == 10, this event will be dropped.
+trace.add_rss_stat(ts=91, tid=3, member=0, size=900, mm_id=1234, curr=False)
+
+# Add an event for tid 3 from tid 10. This emulates e.g. direct reclaim
+# where a process reaches into another process' mm struct.
+trace.add_rss_stat(ts=99, tid=10, member=0, size=10, mm_id=4321, curr=False)
+
+# Add an event on tid 10 which affects its own rss.
+trace.add_rss_stat(ts=100, tid=10, member=0, size=1000, mm_id=1234, curr=True)
+
+# Add an event on tid 10 from tid 3. This emlates e.g. background reclaim
+# where kthreadd is cleaning up the mm struct of another process.
+trace.add_rss_stat(ts=101, tid=3, member=0, size=900, mm_id=1234, curr=False)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/rss_stat_mm_id_clone.out b/test/trace_processor/rss_stat_mm_id_clone.out
new file mode 100644
index 0000000..0969481
--- /dev/null
+++ b/test/trace_processor/rss_stat_mm_id_clone.out
@@ -0,0 +1,9 @@
+"ts","name","pid","name","value"
+100,"mem.rss.file",10,"parent_process",100.000000
+100,"mem.rss.file",2,"kthreadd",10.000000
+102,"mem.rss.file",2,"kthreadd",20.000000
+102,"mem.rss.file",11,"child_process",90.000000
+104,"mem.rss.file",11,"child_process",10.000000
+105,"mem.rss.file",10,"parent_process",95.000000
+107,"mem.rss.file",10,"parent_process",105.000000
+108,"mem.rss.file",10,"parent_process",110.000000
diff --git a/test/trace_processor/rss_stat_mm_id_clone.py b/test/trace_processor/rss_stat_mm_id_clone.py
new file mode 100644
index 0000000..308b6b4
--- /dev/null
+++ b/test/trace_processor/rss_stat_mm_id_clone.py
@@ -0,0 +1,98 @@
+#!/usr/bin/python
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This synthetic trace tests handling of the mm_id field in the rss_stat
+# event during clone events which have various flag combinations set.
+
+from os import sys, path
+
+sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+import synth_common
+
+trace = synth_common.create_trace()
+
+trace.add_process_tree_packet(ts=1)
+trace.add_process(10, 1, "parent_process")
+trace.add_process(3, 2, "kernel_thread")
+
+# In this packet, check what happens to userspace processes with different
+# clone flags.
+trace.add_ftrace_packet(1)
+
+# Emit an rss stat event for the main thread of the process to associate it
+# with an mm_id.
+trace.add_rss_stat(100, tid=10, member=0, size=100, mm_id=0x1234, curr=1)
+
+# Create a newtask event emulating vfork/posix_spawn (i.e. CLONE_VM and
+# CLONE_VFORK set).
+trace.add_newtask(
+    101,
+    tid=10,
+    new_tid=11,
+    new_comm="child_process",
+    flags=synth_common.CLONE_VFORK | synth_common.CLONE_VM)
+
+# The child process will now change its own (and parent's) VM space with
+# |curr| set to 1 (emulating cleaning up some memory in parent).
+trace.add_rss_stat(102, tid=11, member=0, size=90, mm_id=0x1234, curr=1)
+
+# At this point, the child process will obtain a new mm struct. From this
+# point on, all mm_ids from the child should be different from the parent.
+
+# The child process will now change its parents VM space with curr set to
+# 0 (emulating e.g. cleaning up its stack).
+trace.add_rss_stat(103, tid=11, member=0, size=85, mm_id=0x1234, curr=0)
+
+# Now the child process should exec another process.
+
+# The child can now change its own memory.
+trace.add_rss_stat(104, tid=11, member=0, size=10, mm_id=0x5678, curr=1)
+
+# The parent can now resume execution and may emit another rss event.
+trace.add_rss_stat(105, tid=10, member=0, size=95, mm_id=0x1234, curr=1)
+
+# The parent can now go ahead and start a new thread.
+trace.add_newtask(
+    106,
+    tid=10,
+    new_tid=12,
+    new_comm="parent_thread",
+    flags=synth_common.CLONE_VM | synth_common.CLONE_THREAD)
+
+# Since this thread shares mm space with the parent, it should have the
+# same mm id and have curr set to 1.
+trace.add_rss_stat(107, tid=12, member=0, size=105, mm_id=0x1234, curr=1)
+
+# The parent can also emit events with the same mm struct at the same time.
+trace.add_rss_stat(108, tid=10, member=0, size=110, mm_id=0x1234, curr=1)
+
+# In this packet, we check what happens to kernel threads in RSS stat.
+trace.add_ftrace_packet(1)
+
+# Emit an rss stat event for the the existing kernel thread.
+trace.add_rss_stat(100, tid=3, member=0, size=10, mm_id=0x2345, curr=1)
+
+# Start a new kernel thread.
+trace.add_newtask(
+    101,
+    tid=2,
+    new_tid=4,
+    new_comm="kernel_thread2",
+    flags=synth_common.CLONE_VM)
+
+# Emit a rss stat for the new kernel thread.
+trace.add_rss_stat(102, tid=4, member=0, size=20, mm_id=0x2345, curr=1)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/rss_stat_mm_id_reuse.out b/test/trace_processor/rss_stat_mm_id_reuse.out
new file mode 100644
index 0000000..396f5f7
--- /dev/null
+++ b/test/trace_processor/rss_stat_mm_id_reuse.out
@@ -0,0 +1,3 @@
+"ts","name","pid","name","value"
+100,"mem.rss.file",10,"parent_process",100.000000
+103,"mem.rss.file",10,"new_process",10.000000
diff --git a/test/trace_processor/rss_stat_mm_id_reuse.py b/test/trace_processor/rss_stat_mm_id_reuse.py
new file mode 100644
index 0000000..58d7b4d
--- /dev/null
+++ b/test/trace_processor/rss_stat_mm_id_reuse.py
@@ -0,0 +1,43 @@
+#!/usr/bin/python
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This synthetic trace tests handling of the mm_id field in the rss_stat
+# event when mm_structs are reused on process death.
+
+from os import sys, path
+
+sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+import synth_common
+
+trace = synth_common.create_trace()
+
+trace.add_process_tree_packet(ts=1)
+trace.add_process(10, 1, "parent_process")
+
+trace.add_ftrace_packet(1)
+
+# Emit an event for the process.
+trace.add_rss_stat(100, tid=10, member=0, size=100, mm_id=0x1234, curr=1)
+
+# Now kill the process.
+trace.add_process_free(ts=101, tid=10, comm="parent_process", prio=0)
+
+# Create a new thread which reuses the pid and mm struct.
+trace.add_newtask(102, tid=1, new_tid=10, new_comm="new_process", flags=0)
+
+# Emit an event for the new thread.
+trace.add_rss_stat(103, tid=10, member=0, size=10, mm_id=0x1234, curr=1)
+
+print(trace.trace.SerializeToString())
diff --git a/tools/gen_binary_descriptors b/tools/gen_binary_descriptors
index 439d596..839d7c0 100755
--- a/tools/gen_binary_descriptors
+++ b/tools/gen_binary_descriptors
@@ -37,6 +37,8 @@
         'src/protozero/test/example_proto/test_messages.descriptor.h',
     'protos/perfetto/trace/track_event/track_event.proto':
         'src/trace_processor/importers/proto/track_event.descriptor.h',
+    'protos/perfetto/metrics/custom_options.proto':
+        'src/trace_processor/metrics/custom_options.descriptor.h',
 }
 
 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
@@ -83,6 +85,8 @@
         protoc_path,
         '--include_imports',
         '--proto_path=.',
+        '--proto_path=' + \
+            os.path.join(ROOT_DIR, "buildtools", "protobuf", "src"),
         '--descriptor_set_out={}'.format(fdescriptor.name),
         source,
     ],
diff --git a/tools/install-build-deps b/tools/install-build-deps
index db5aa59..1ed1fab 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -146,8 +146,8 @@
     # Example traces for regression tests.
     (
         'buildtools/test_data.zip',
-        'https://storage.googleapis.com/perfetto/test-data-20200121-101157.zip',
-        'ddfe8aa6ceca7be17f222740927dc50aa9f8ed02',
+        'https://storage.googleapis.com/perfetto/test-data-20200122-100845.zip',
+        '56ac45b5239fda50d33cf05bfd329dcb3efb0b2a',
         'all',
     ),
 
diff --git a/ui/src/assets/topbar.scss b/ui/src/assets/topbar.scss
index f5ce2f5..03a907f 100644
--- a/ui/src/assets/topbar.scss
+++ b/ui/src/assets/topbar.scss
@@ -222,3 +222,29 @@
         }
     }
 }
+
+.helpful-hint {
+  position: absolute;
+  right: 5px;
+  top: 5px;
+  width: 300px;
+  background-color: white;
+  font-size: 12px;
+  color: #3f4040;
+  display: grid;
+  border-radius: 5px;
+  padding: 8px;
+  box-shadow: 1px 3px 15px rgba(23, 32, 44, 0.3);
+}
+
+.hint-text {
+  padding-bottom: 5px
+}
+
+.hint-dismiss-button {
+  color: #f4fafb;
+  background-color: #19212b;
+  width: fit-content;
+  padding: 3px;
+  border-radius: 3px;
+}
diff --git a/ui/src/controller/heap_profile_controller.ts b/ui/src/controller/heap_profile_controller.ts
index 973a92f..eadb704 100644
--- a/ui/src/controller/heap_profile_controller.ts
+++ b/ui/src/controller/heap_profile_controller.ts
@@ -177,23 +177,23 @@
     let sizeIndex = 4;
     switch (viewingOption) {
       case SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY:
-        orderBy = `where size > 0 order by depth, parent_hash, size desc, name`;
+        orderBy = `where cumulative_size > 0 order by depth, parent_id,
+            cumulative_size desc, name`;
         sizeIndex = 4;
         break;
       case ALLOC_SPACE_MEMORY_ALLOCATED_KEY:
-        orderBy =
-            `where alloc_size > 0 order by depth, parent_hash, alloc_size desc,
-            name`;
+        orderBy = `where cumulative_alloc_size > 0 order by depth, parent_id,
+            cumulative_alloc_size desc, name`;
         sizeIndex = 5;
         break;
       case OBJECTS_ALLOCATED_NOT_FREED_KEY:
-        orderBy =
-            `where count > 0 order by depth, parent_hash, count desc, name`;
+        orderBy = `where cumulative_count > 0 order by depth, parent_id,
+            cumulative_count desc, name`;
         sizeIndex = 6;
         break;
       case OBJECTS_ALLOCATED_KEY:
-        orderBy = `where alloc_count > 0 order by depth, parent_hash,
-            alloc_count desc, name`;
+        orderBy = `where cumulative_alloc_count > 0 order by depth, parent_id,
+            cumulative_alloc_count desc, name`;
         sizeIndex = 7;
         break;
       default:
@@ -201,8 +201,9 @@
     }
 
     const callsites = await this.args.engine.query(
-        `SELECT hash, name, parent_hash, depth, size, alloc_size, count,
-        alloc_count, map_name, self_size from ${tableName} ${orderBy}`);
+        `SELECT id, name, parent_id, depth, cumulative_size,
+        cumulative_alloc_size, cumulative_count,
+        cumulative_alloc_count, map_name, size from ${tableName} ${orderBy}`);
 
     const flamegraphData: CallsiteInfo[] = new Array();
     const hashToindex: Map<number, number> = new Map();
@@ -230,102 +231,15 @@
       Promise<string> {
     // Creating unique names for views so we can reuse and not delete them
     // for each marker.
-    const tableNameCallsiteNameSize =
-        this.tableName(`callsite_with_name_and_size`);
-    const tableNameCallsiteHashNameSize =
-        this.tableName(`callsite_hash_name_size`);
     const tableNameGroupedCallsitesForFlamegraph =
         this.tableName(`grouped_callsites_for_flamegraph`);
-    // Joining the callsite table with frame table then with alloc table to get
-    // the size and name for each callsite.
-    // TODO(taylori): Make frame name nullable in the trace processor for
-    // consistency with the other columns.
-    await this.args.engine.query(
-        `create view if not exists ${tableNameCallsiteNameSize} as
-         select id, parent_id, depth, IFNULL(DEMANGLE(name), name) as name,
-            map_name, size, alloc_size, count, alloc_count from (
-         select cs.id as id, parent_id, depth,
-            coalesce(symbols.name,
-                case when fr.name != '' then fr.name else map.name end) as name,
-            map.name as map_name,
-            SUM(IFNULL(size, 0)) as size,
-            SUM(IFNULL(size, 0)) as size,
-            SUM(case when size > 0 then size else 0 end) as alloc_size,
-            SUM(IFNULL(count, 0)) as count,
-            SUM(case when count > 0 then count else 0 end) as alloc_count
-         from stack_profile_callsite cs
-         join stack_profile_frame fr on cs.frame_id = fr.id
-         join stack_profile_mapping map on fr.mapping = map.id
-         left join (
-              select symbol_set_id, FIRST_VALUE(name) OVER(PARTITION BY
-                symbol_set_id) as name
-              from stack_profile_symbol GROUP BY symbol_set_id
-            ) as symbols using(symbol_set_id)
-         left join heap_profile_allocation alloc on alloc.callsite_id = cs.id
-         and alloc.ts <= ${ts} and alloc.upid = ${upid} group by cs.id)`);
 
-    // Recursive query to compute the hash for each callsite based on names
-    // rather than ids.
-    // We get all the children of the row in question and emit a row with hash
-    // equal hash(name, parent.hash). Roots without the parent will have -1 as
-    // hash.  Slices will be merged into a big slice.
-    await this.args.engine.query(
-        `create view if not exists ${tableNameCallsiteHashNameSize} as
-        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
-    //  callsite(in terms of hashes) and emit a row with the size of the current
-    //  callsite plus all the info of the parent.
-    // Grouping: For each callsite, our recursive table has n rows where n is
-    //  the number of descendents with a non-zero self size. We need to group on
-    //  the hash and sum all the sizes to get the cumulative size for each
-    //  callsite hash.
     await this.args.engine.query(`create temp table if not exists ${
-        tableNameGroupedCallsitesForFlamegraph}
-        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.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, 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`);
+        tableNameGroupedCallsitesForFlamegraph} as
+        select id, name, map_name, parent_id, depth, cumulative_size,
+          cumulative_alloc_size, cumulative_count, cumulative_alloc_count,
+          size, alloc_size, count, alloc_count
+        from experimental_flamegraph(${ts}, ${upid}, 'native')`);
     return tableNameGroupedCallsitesForFlamegraph;
   }
 
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 88e2190..c5b6130 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -374,10 +374,14 @@
 
     const upidToProcessTracks = new Map();
     const rawProcessTracks = await engine.query(`
-      select id, upid, process_track.name, max(depth) as maxDepth
+      select
+        process_track.id as track_id,
+        process_track.upid,
+        process_track.name,
+        max(slice.depth) as max_depth
       from process_track
-      inner join slice on slice.track_id = process_track.id
-      group by track_id
+      join slice on slice.track_id = process_track.id
+      group by process_track.id
     `);
     for (let i = 0; i < rawProcessTracks.numRecords; i++) {
       const trackId = rawProcessTracks.columns[0].longValues![i];
@@ -467,6 +471,32 @@
       });
     }
 
+    // Add global slice tracks.
+    const globalSliceTracks = await engine.query(`
+      select
+        track.name as track_name,
+        track.id as track_id,
+        max(depth) as max_depth
+      from track
+      join slice on track.id = slice.track_id
+      where track.type = 'track'
+      group by track_id
+    `);
+
+    for (let i = 0; i < globalSliceTracks.numRecords; i++) {
+      const name = globalSliceTracks.columns[0].stringValues![i];
+      const trackId = +globalSliceTracks.columns[1].longValues![i];
+      const maxDepth = +globalSliceTracks.columns[2].longValues![i];
+
+      tracksToAdd.push({
+        engineId: this.engineId,
+        kind: SLICE_TRACK_KIND,
+        name: `${name}`,
+        trackGroup: SCROLLING_TRACK_GROUP,
+        config: {maxDepth, trackId},
+      });
+    }
+
     interface CounterTrack {
       name: string;
       trackId: number;
@@ -687,8 +717,6 @@
           name: `${threadName} [${tid}]`,
           trackGroup: pUuid,
           config: {
-            upid,
-            utid,
             maxDepth: threadTrack.maxDepth,
             trackId: threadTrack.trackId
           },
@@ -839,9 +867,9 @@
       select first_thread.ts as ts,
       coalesce(min(runnable.ts), (select end_ts from trace_bounds)) -
       first_thread.ts as dur,
-      runnable.utid as utid
-      from runnable
-      JOIN first_thread using(utid) group by utid`);
+      first_thread.utid as utid
+      from first_thread
+      LEFT JOIN runnable using(utid) group by utid`);
 
     await engine.query(`create view full_runnable as
         select * from runnable UNION
diff --git a/ui/src/frontend/frontend_local_state.ts b/ui/src/frontend/frontend_local_state.ts
index 0f4a605..97acfd3 100644
--- a/ui/src/frontend/frontend_local_state.ts
+++ b/ui/src/frontend/frontend_local_state.ts
@@ -99,6 +99,7 @@
   showNotePreview = false;
   localOnlyMode = false;
   sidebarVisible = true;
+  showPanningHint = false;
   // This is used to calculate the tracks within a Y range for area selection.
   areaY: Range = {};
   visibleTracks = new Set<string>();
@@ -225,6 +226,7 @@
   selectArea(
       startSec: number, endSec: number,
       tracks = this._selectedArea.area ? this._selectedArea.area.tracks : []) {
+    this.showPanningHint = true;
     this._selectedArea = {
       area: {startSec, endSec, tracks},
       lastUpdate: Date.now() / 1000
diff --git a/ui/src/frontend/topbar.ts b/ui/src/frontend/topbar.ts
index 4fd3c66..a7bd25f 100644
--- a/ui/src/frontend/topbar.ts
+++ b/ui/src/frontend/topbar.ts
@@ -32,6 +32,8 @@
   [COMMAND]: 'e.g. select * from sched left join thread using(utid) limit 10'
 };
 
+export const DISMISSED_PANNING_HINT_KEY = 'dismissedPanningHint';
+
 let selResult = 0;
 let numResults = 0;
 let mode: Mode = SEARCH;
@@ -255,6 +257,31 @@
   }
 }
 
+
+class HelpPanningNotification implements m.ClassComponent {
+  view() {
+    const dismissed = localStorage.getItem(DISMISSED_PANNING_HINT_KEY);
+    if (dismissed === 'true' || !globals.frontendLocalState.showPanningHint) {
+      return;
+    }
+    return m(
+        '.helpful-hint',
+        m('.hint-text',
+          'Are you trying to pan? Use the WASD keys or hold shift to click ' +
+              'and drag. Press \'?\' for more help.'),
+        m('button.hint-dismiss-button',
+          {
+            onclick: () => {
+              globals.frontendLocalState.showPanningHint = false;
+              localStorage.setItem(DISMISSED_PANNING_HINT_KEY, 'true');
+              globals.rafScheduler.scheduleFullRedraw();
+            }
+          },
+          'Dismiss'),
+    );
+  }
+}
+
 export class Topbar implements m.ClassComponent {
   view() {
     return m(
@@ -262,6 +289,7 @@
         globals.frontendLocalState.newVersionAvailable ?
             m(NewVersionNotification) :
             m(Omnibox),
-        m(Progress));
+        m(Progress),
+        m(HelpPanningNotification));
   }
 }
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index 6dc5475..5dd811e 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -32,6 +32,7 @@
 import {TimeAxisPanel} from './time_axis_panel';
 import {computeZoom} from './time_scale';
 import {TimeSelectionPanel} from './time_selection_panel';
+import {DISMISSED_PANNING_HINT_KEY} from './topbar';
 import {TrackGroupPanel} from './track_group_panel';
 import {TrackPanel} from './track_panel';
 import {VideoPanel} from './video_panel';
@@ -167,6 +168,8 @@
           tStart = tEnd - origDelta;
         }
         frontendLocalState.updateVisibleTime(new TimeSpan(tStart, tEnd));
+        // If the user has panned they no longer need the hint.
+        localStorage.setItem(DISMISSED_PANNING_HINT_KEY, 'true');
         globals.rafScheduler.scheduleRedraw();
       },
       onZoomed: (zoomedPositionPx: number, zoomRatio: number) => {
diff --git a/ui/src/tracks/chrome_slices/common.ts b/ui/src/tracks/chrome_slices/common.ts
index faa40c3..41eb3c2 100644
--- a/ui/src/tracks/chrome_slices/common.ts
+++ b/ui/src/tracks/chrome_slices/common.ts
@@ -18,8 +18,6 @@
 
 export interface Config {
   maxDepth: number;
-  upid: number;
-  utid: number;
   trackId: number;
 }