Merge "processor: Ignore misordered slice events."
diff --git a/Android.bp b/Android.bp
index 7be3725..7ec6c76 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1411,6 +1411,7 @@
   name: "perfetto_protos_perfetto_trace_android_lite_gen",
   srcs: [
     "protos/perfetto/trace/android/android_log.proto",
+    "protos/perfetto/trace/android/graphics_frame_event.proto",
     "protos/perfetto/trace/android/packages_list.proto",
   ],
   tools: [
@@ -1419,6 +1420,7 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/android/android_log.pb.cc",
+    "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.pb.cc",
     "external/perfetto/protos/perfetto/trace/android/packages_list.pb.cc",
   ],
 }
@@ -1428,6 +1430,7 @@
   name: "perfetto_protos_perfetto_trace_android_lite_gen_headers",
   srcs: [
     "protos/perfetto/trace/android/android_log.proto",
+    "protos/perfetto/trace/android/graphics_frame_event.proto",
     "protos/perfetto/trace/android/packages_list.proto",
   ],
   tools: [
@@ -1436,6 +1439,7 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/android/android_log.pb.h",
+    "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.pb.h",
     "external/perfetto/protos/perfetto/trace/android/packages_list.pb.h",
   ],
   export_include_dirs: [
@@ -1448,6 +1452,7 @@
   name: "perfetto_protos_perfetto_trace_android_zero_gen",
   srcs: [
     "protos/perfetto/trace/android/android_log.proto",
+    "protos/perfetto/trace/android/graphics_frame_event.proto",
     "protos/perfetto/trace/android/packages_list.proto",
   ],
   tools: [
@@ -1457,6 +1462,7 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protozero_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/android/android_log.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/android/packages_list.pbzero.cc",
   ],
 }
@@ -1466,6 +1472,7 @@
   name: "perfetto_protos_perfetto_trace_android_zero_gen_headers",
   srcs: [
     "protos/perfetto/trace/android/android_log.proto",
+    "protos/perfetto/trace/android/graphics_frame_event.proto",
     "protos/perfetto/trace/android/packages_list.proto",
   ],
   tools: [
@@ -1475,6 +1482,7 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protozero_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/android/android_log.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.pbzero.h",
     "external/perfetto/protos/perfetto/trace/android/packages_list.pbzero.h",
   ],
   export_include_dirs: [
@@ -2109,6 +2117,7 @@
     "protos/perfetto/trace/test_event.proto",
     "protos/perfetto/trace/trace.proto",
     "protos/perfetto/trace/trace_packet.proto",
+    "protos/perfetto/trace/trace_packet_defaults.proto",
   ],
   tools: [
     "aprotoc",
@@ -2118,6 +2127,7 @@
     "external/perfetto/protos/perfetto/trace/test_event.pb.cc",
     "external/perfetto/protos/perfetto/trace/trace.pb.cc",
     "external/perfetto/protos/perfetto/trace/trace_packet.pb.cc",
+    "external/perfetto/protos/perfetto/trace/trace_packet_defaults.pb.cc",
   ],
 }
 
@@ -2128,6 +2138,7 @@
     "protos/perfetto/trace/test_event.proto",
     "protos/perfetto/trace/trace.proto",
     "protos/perfetto/trace/trace_packet.proto",
+    "protos/perfetto/trace/trace_packet_defaults.proto",
   ],
   tools: [
     "aprotoc",
@@ -2137,6 +2148,7 @@
     "external/perfetto/protos/perfetto/trace/test_event.pb.h",
     "external/perfetto/protos/perfetto/trace/trace.pb.h",
     "external/perfetto/protos/perfetto/trace/trace_packet.pb.h",
+    "external/perfetto/protos/perfetto/trace/trace_packet_defaults.pb.h",
   ],
   export_include_dirs: [
     "protos",
@@ -2749,6 +2761,7 @@
     "protos/perfetto/trace/test_event.proto",
     "protos/perfetto/trace/trace.proto",
     "protos/perfetto/trace/trace_packet.proto",
+    "protos/perfetto/trace/trace_packet_defaults.proto",
     "protos/perfetto/trace/trigger.proto",
   ],
   tools: [
@@ -2762,6 +2775,7 @@
     "external/perfetto/protos/perfetto/trace/test_event.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/trace.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/trace_packet.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/trace_packet_defaults.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/trigger.pbzero.cc",
   ],
 }
@@ -2775,6 +2789,7 @@
     "protos/perfetto/trace/test_event.proto",
     "protos/perfetto/trace/trace.proto",
     "protos/perfetto/trace/trace_packet.proto",
+    "protos/perfetto/trace/trace_packet_defaults.proto",
     "protos/perfetto/trace/trigger.proto",
   ],
   tools: [
@@ -2788,6 +2803,7 @@
     "external/perfetto/protos/perfetto/trace/test_event.pbzero.h",
     "external/perfetto/protos/perfetto/trace/trace.pbzero.h",
     "external/perfetto/protos/perfetto/trace/trace_packet.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/trace_packet_defaults.pbzero.h",
     "external/perfetto/protos/perfetto/trace/trigger.pbzero.h",
   ],
   export_include_dirs: [
@@ -3731,6 +3747,7 @@
     "src/trace_processor/counter_values_table.cc",
     "src/trace_processor/event_tracker.cc",
     "src/trace_processor/filtered_row_index.cc",
+    "src/trace_processor/forwarding_trace_parser.cc",
     "src/trace_processor/ftrace_descriptors.cc",
     "src/trace_processor/ftrace_utils.cc",
     "src/trace_processor/fuchsia_provider_view.cc",
@@ -3902,6 +3919,7 @@
     "src/trace_processor/counter_values_table.cc",
     "src/trace_processor/event_tracker.cc",
     "src/trace_processor/filtered_row_index.cc",
+    "src/trace_processor/forwarding_trace_parser.cc",
     "src/trace_processor/ftrace_descriptors.cc",
     "src/trace_processor/ftrace_utils.cc",
     "src/trace_processor/fuchsia_provider_view.cc",
diff --git a/BUILD b/BUILD
index 144c09f..6703ee1 100644
--- a/BUILD
+++ b/BUILD
@@ -299,6 +299,8 @@
         "src/trace_processor/export_json.h",
         "src/trace_processor/filtered_row_index.cc",
         "src/trace_processor/filtered_row_index.h",
+        "src/trace_processor/forwarding_trace_parser.cc",
+        "src/trace_processor/forwarding_trace_parser.h",
         "src/trace_processor/ftrace_descriptors.cc",
         "src/trace_processor/ftrace_descriptors.h",
         "src/trace_processor/ftrace_utils.cc",
@@ -591,6 +593,8 @@
         "src/trace_processor/export_json.h",
         "src/trace_processor/filtered_row_index.cc",
         "src/trace_processor/filtered_row_index.h",
+        "src/trace_processor/forwarding_trace_parser.cc",
+        "src/trace_processor/forwarding_trace_parser.h",
         "src/trace_processor/ftrace_descriptors.cc",
         "src/trace_processor/ftrace_descriptors.h",
         "src/trace_processor/ftrace_utils.cc",
@@ -835,6 +839,8 @@
         "src/trace_processor/export_json.h",
         "src/trace_processor/filtered_row_index.cc",
         "src/trace_processor/filtered_row_index.h",
+        "src/trace_processor/forwarding_trace_parser.cc",
+        "src/trace_processor/forwarding_trace_parser.h",
         "src/trace_processor/ftrace_descriptors.cc",
         "src/trace_processor/ftrace_descriptors.h",
         "src/trace_processor/ftrace_utils.cc",
diff --git a/BUILD.gn b/BUILD.gn
index bf85e54..b14cf0c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -296,11 +296,11 @@
 
 if (perfetto_build_with_embedder) {
   if (build_with_chromium) {
-    libperfetto_target_type = "component"
+    lib_target_type = "component"
   } else {
-    libperfetto_target_type = "source_set"
+    lib_target_type = "source_set"
   }
-  target(libperfetto_target_type, "libperfetto") {
+  target(lib_target_type, "libperfetto") {
     public_configs = [ "gn:public_config" ]
     deps = [
       "src/tracing",
@@ -316,6 +316,17 @@
       "protos/perfetto/trace/track_event:zero",
     ]
   }
+  target(lib_target_type, "libtrace_processor") {
+    public_configs = [ "gn:public_config" ]
+    deps = [
+      "src/trace_processor:lib",
+    ]
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
+    public_deps = [
+      "include/perfetto/trace_processor",
+    ]
+  }
 }
 
 if (perfetto_build_standalone) {
diff --git a/include/perfetto/ext/base/uuid.h b/include/perfetto/ext/base/uuid.h
index c4e8e67..7994021 100644
--- a/include/perfetto/ext/base/uuid.h
+++ b/include/perfetto/ext/base/uuid.h
@@ -18,11 +18,16 @@
 #define INCLUDE_PERFETTO_EXT_BASE_UUID_H_
 
 #include <array>
+#include <string>
 
 namespace perfetto {
 namespace base {
 
-std::array<uint8_t, 16> Uuidv4();
+using Uuid = std::array<uint8_t, 16>;
+Uuid Uuidv4();
+
+Uuid StringToUuid(const std::string&);
+std::string UuidToString(const Uuid&);
 
 }  // namespace base
 }  // namespace perfetto
diff --git a/include/perfetto/ext/base/watchdog.h b/include/perfetto/ext/base/watchdog.h
index 02f1918..a10fde1 100644
--- a/include/perfetto/ext/base/watchdog.h
+++ b/include/perfetto/ext/base/watchdog.h
@@ -21,9 +21,17 @@
 
 #include "perfetto/base/build_config.h"
 
+// The POSIX watchdog is only supported on Linux and Android in non-embedder
+// builds.
 #if (PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||    \
      PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)) && \
     !PERFETTO_BUILDFLAG(PERFETTO_EMBEDDER_BUILD)
+#define PERFETTO_USE_POSIX_WATCHDOG() 1
+#else
+#define PERFETTO_USE_POSIX_WATCHDOG() 0
+#endif
+
+#if PERFETTO_USE_POSIX_WATCHDOG()
 #include "perfetto/ext/base/watchdog_posix.h"
 #else
 #include "perfetto/ext/base/watchdog_noop.h"
diff --git a/include/perfetto/ext/tracing/core/BUILD.gn b/include/perfetto/ext/tracing/core/BUILD.gn
index cac4d6c..5dc8c88 100644
--- a/include/perfetto/ext/tracing/core/BUILD.gn
+++ b/include/perfetto/ext/tracing/core/BUILD.gn
@@ -19,6 +19,7 @@
   ]
   sources = [
     "basic_types.h",
+    "buffer_exhausted_policy.h",
     "commit_data_request.h",
     "consumer.h",
     "observable_events.h",
diff --git a/include/perfetto/ext/tracing/core/buffer_exhausted_policy.h b/include/perfetto/ext/tracing/core/buffer_exhausted_policy.h
new file mode 100644
index 0000000..cd8ec2c
--- /dev/null
+++ b/include/perfetto/ext/tracing/core/buffer_exhausted_policy.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_BUFFER_EXHAUSTED_POLICY_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_BUFFER_EXHAUSTED_POLICY_H_
+
+namespace perfetto {
+
+// Determines how SharedMemoryArbiterImpl::GetNewChunk() behaves when no free
+// chunks are available.
+enum class BufferExhaustedPolicy {
+  // SharedMemoryArbiterImpl::GetNewChunk() will stall if no free SMB chunk is
+  // available and wait for the tracing service to free one. Note that this
+  // requires that messages the arbiter sends to the tracing service (from any
+  // TraceWriter thread) will be received by it, even if all TraceWriter threads
+  // are stalled.
+  kStall,
+
+  // SharedMemoryArbiterImpl::GetNewChunk() will return an invalid chunk if no
+  // free SMB chunk is available. In this case, the TraceWriter will fall back
+  // to a garbage chunk and drop written data until acquiring a future chunk
+  // succeeds again.
+  kDrop,
+
+  // TODO(eseckler): Switch to kDrop by default and change the Android code to
+  // explicitly request kStall instead.
+  kDefault = kStall
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_BUFFER_EXHAUSTED_POLICY_H_
diff --git a/include/perfetto/ext/tracing/core/shared_memory_arbiter.h b/include/perfetto/ext/tracing/core/shared_memory_arbiter.h
index d2a6f73..4e757ee 100644
--- a/include/perfetto/ext/tracing/core/shared_memory_arbiter.h
+++ b/include/perfetto/ext/tracing/core/shared_memory_arbiter.h
@@ -25,6 +25,7 @@
 
 #include "perfetto/base/export.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/ext/tracing/core/buffer_exhausted_policy.h"
 #include "perfetto/ext/tracing/core/tracing_service.h"
 
 namespace perfetto {
@@ -43,26 +44,6 @@
 // from the SharedMemory it receives from the Service-side.
 class PERFETTO_EXPORT SharedMemoryArbiter {
  public:
-  // Determines how GetNewChunk() behaves when no free chunks are available.
-  enum class BufferExhaustedPolicy {
-    // SharedMemoryArbiterImpl::GetNewChunk() will stall if no free SMB chunk is
-    // available and wait for the tracing service to free one. Note that this
-    // requires that messages the arbiter sends to the tracing service (from any
-    // TraceWriter thread) will be received by it, even if all TraceWriter
-    // threads are stalled.
-    kStall,
-
-    // SharedMemoryArbiterImpl::GetNewChunk() will return an invalid chunk if no
-    // free SMB chunk is available. In this case, the TraceWriter will fall back
-    // to a garbage chunk and drop written data until acquiring a future chunk
-    // succeeds again.
-    kDrop,
-
-    // TODO(eseckler): Switch to kDrop by default and change the Android code to
-    // explicitly request kStall instead.
-    kDefault = kStall
-  };
-
   virtual ~SharedMemoryArbiter();
 
   // Creates a new TraceWriter and assigns it a new WriterID. The WriterID is
diff --git a/include/perfetto/ext/tracing/core/startup_trace_writer.h b/include/perfetto/ext/tracing/core/startup_trace_writer.h
index 7503e49..52d18eb 100644
--- a/include/perfetto/ext/tracing/core/startup_trace_writer.h
+++ b/include/perfetto/ext/tracing/core/startup_trace_writer.h
@@ -26,6 +26,7 @@
 #include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/thread_checker.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/ext/tracing/core/buffer_exhausted_policy.h"
 #include "perfetto/ext/tracing/core/shared_memory_abi.h"
 #include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
 #include "perfetto/ext/tracing/core/trace_writer.h"
@@ -125,7 +126,7 @@
   // to by the handle. The writer can later be bound by calling
   // BindToTraceWriter(). The registry handle may be nullptr in tests.
   StartupTraceWriter(std::shared_ptr<StartupTraceWriterRegistryHandle>,
-                     SharedMemoryArbiter::BufferExhaustedPolicy);
+                     BufferExhaustedPolicy);
 
   StartupTraceWriter(const StartupTraceWriter&) = delete;
   StartupTraceWriter& operator=(const StartupTraceWriter&) = delete;
@@ -169,8 +170,8 @@
   // check on later calls to NewTracePacket().
   bool was_bound_ = false;
 
-  const SharedMemoryArbiter::BufferExhaustedPolicy buffer_exhausted_policy_ =
-      SharedMemoryArbiter::BufferExhaustedPolicy::kDefault;
+  const BufferExhaustedPolicy buffer_exhausted_policy_ =
+      BufferExhaustedPolicy::kDefault;
 
   // All variables below this point are protected by |lock_|.
   std::mutex lock_;
diff --git a/include/perfetto/ext/tracing/core/startup_trace_writer_registry.h b/include/perfetto/ext/tracing/core/startup_trace_writer_registry.h
index e49a910..5b839bb 100644
--- a/include/perfetto/ext/tracing/core/startup_trace_writer_registry.h
+++ b/include/perfetto/ext/tracing/core/startup_trace_writer_registry.h
@@ -25,6 +25,7 @@
 #include "perfetto/base/export.h"
 #include "perfetto/ext/base/weak_ptr.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/ext/tracing/core/buffer_exhausted_policy.h"
 #include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
 
 namespace perfetto {
@@ -74,8 +75,7 @@
   // destroyed by the caller directly, but instead returned to the registry by
   // calling StartupTraceWriter::ReturnToRegistry.
   std::unique_ptr<StartupTraceWriter> CreateUnboundTraceWriter(
-      SharedMemoryArbiter::BufferExhaustedPolicy =
-          SharedMemoryArbiter::BufferExhaustedPolicy::kDefault);
+      BufferExhaustedPolicy = BufferExhaustedPolicy::kDefault);
 
   // Binds all StartupTraceWriters created by this registry to the given arbiter
   // and target buffer. Should only be called once and on the passed
diff --git a/include/perfetto/ext/tracing/core/tracing_service.h b/include/perfetto/ext/tracing/core/tracing_service.h
index 0cb7dbd..e1abe58 100644
--- a/include/perfetto/ext/tracing/core/tracing_service.h
+++ b/include/perfetto/ext/tracing/core/tracing_service.h
@@ -26,6 +26,7 @@
 #include "perfetto/base/export.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/ext/tracing/core/buffer_exhausted_policy.h"
 #include "perfetto/ext/tracing/core/shared_memory.h"
 
 namespace perfetto {
@@ -104,7 +105,9 @@
   // upon creation of the data source (StartDataSource()) in the
   // DataSourceConfig.target_buffer().
   virtual std::unique_ptr<TraceWriter> CreateTraceWriter(
-      BufferID target_buffer) = 0;
+      BufferID target_buffer,
+      BufferExhaustedPolicy buffer_exhausted_policy =
+          BufferExhaustedPolicy::kDefault) = 0;
 
   // If TracingService::ConnectProducer is called with |in_process=true|,
   // this returns the producer's SharedMemoryArbiter which can be used
diff --git a/include/perfetto/trace_processor/basic_types.h b/include/perfetto/trace_processor/basic_types.h
index 76d14d6..59fb559 100644
--- a/include/perfetto/trace_processor/basic_types.h
+++ b/include/perfetto/trace_processor/basic_types.h
@@ -22,14 +22,15 @@
 #include <stdint.h>
 #include <string>
 
+#include "perfetto/base/export.h"
+
 namespace perfetto {
 namespace trace_processor {
 
-struct Config {
-};
+struct PERFETTO_EXPORT Config {};
 
 // Represents a dynamically typed value returned by SQL.
-struct SqlValue {
+struct PERFETTO_EXPORT SqlValue {
   // Represents the type of the value.
   enum Type {
     kNull = 0,
diff --git a/include/perfetto/trace_processor/status.h b/include/perfetto/trace_processor/status.h
index 934c01b..ee7271a 100644
--- a/include/perfetto/trace_processor/status.h
+++ b/include/perfetto/trace_processor/status.h
@@ -20,6 +20,8 @@
 #include <stdarg.h>
 #include <string>
 
+#include "perfetto/base/export.h"
+
 namespace perfetto {
 namespace trace_processor {
 
@@ -31,7 +33,7 @@
 // This can used as the return type of functions which would usually return an
 // bool for success or int for errno but also wants to add some string context
 // (ususally for logging).
-class Status {
+class PERFETTO_EXPORT Status {
  public:
   Status() : ok_(true) {}
   explicit Status(std::string error) : ok_(false), message_(std::move(error)) {}
diff --git a/include/perfetto/trace_processor/trace_processor.h b/include/perfetto/trace_processor/trace_processor.h
index 2ab067f..0b879f8 100644
--- a/include/perfetto/trace_processor/trace_processor.h
+++ b/include/perfetto/trace_processor/trace_processor.h
@@ -20,6 +20,7 @@
 #include <memory>
 #include <vector>
 
+#include "perfetto/base/export.h"
 #include "perfetto/trace_processor/basic_types.h"
 #include "perfetto/trace_processor/status.h"
 
@@ -29,7 +30,7 @@
 
 // Coordinates the loading of traces from an arbitrary source and allows
 // execution of SQL queries on the events in these traces.
-class TraceProcessor {
+class PERFETTO_EXPORT TraceProcessor {
  public:
   class IteratorImpl;
 
@@ -118,7 +119,7 @@
 };
 
 // When set, logs SQLite actions on the console.
-void EnableSQLiteVtableDebugging();
+void PERFETTO_EXPORT EnableSQLiteVtableDebugging();
 
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/include/perfetto/tracing/core/trace_config.h b/include/perfetto/tracing/core/trace_config.h
index 7a4b2a8..26cdfcd 100644
--- a/include/perfetto/tracing/core/trace_config.h
+++ b/include/perfetto/tracing/core/trace_config.h
@@ -647,6 +647,12 @@
     return incident_report_config_.get();
   }
 
+  const std::string& trace_uuid() const { return trace_uuid_; }
+  void set_trace_uuid(const std::string& value) { trace_uuid_ = value; }
+  void set_trace_uuid(const void* p, size_t s) {
+    trace_uuid_.assign(reinterpret_cast<const char*>(p), s);
+  }
+
  private:
   std::vector<BufferConfig> buffers_;
   std::vector<DataSource> data_sources_;
@@ -673,6 +679,7 @@
   std::string unique_session_name_{};
   CompressionType compression_type_{};
   ::perfetto::base::CopyablePtr<IncidentReportConfig> incident_report_config_;
+  std::string trace_uuid_{};
 
   // Allows to preserve unknown protobuf fields for compatibility
   // with future versions of .proto files.
diff --git a/include/perfetto/tracing/internal/data_source_internal.h b/include/perfetto/tracing/internal/data_source_internal.h
index 7321aaf..8488cf2 100644
--- a/include/perfetto/tracing/internal/data_source_internal.h
+++ b/include/perfetto/tracing/internal/data_source_internal.h
@@ -79,7 +79,7 @@
   // This is to prevent that accessing the data source on an arbitrary embedder
   // thread races with the internal IPC thread destroying the data source
   // because of a end-of-tracing notification from the service.
-  std::mutex lock;
+  std::recursive_mutex lock;
   std::unique_ptr<DataSourceBase> data_source;
 };
 
diff --git a/include/perfetto/tracing/locked_handle.h b/include/perfetto/tracing/locked_handle.h
index f9ae8e5..3d4c461 100644
--- a/include/perfetto/tracing/locked_handle.h
+++ b/include/perfetto/tracing/locked_handle.h
@@ -27,7 +27,7 @@
 template <typename T>
 class LockedHandle {
  public:
-  LockedHandle(std::mutex* mutex, T* obj) : lock_(*mutex), obj_(obj) {}
+  LockedHandle(std::recursive_mutex* mtx, T* obj) : lock_(*mtx), obj_(obj) {}
   LockedHandle() = default;  // For the invalid case.
   LockedHandle(LockedHandle&&) = default;
   LockedHandle& operator=(LockedHandle&&) = default;
@@ -43,7 +43,7 @@
   T& operator*() { return *(this->operator->()); }
 
  private:
-  std::unique_lock<std::mutex> lock_;
+  std::unique_lock<std::recursive_mutex> lock_;
   T* obj_ = nullptr;
 };
 
diff --git a/infra/ci/worker/Dockerfile b/infra/ci/worker/Dockerfile
index 4157350..8b1788a 100644
--- a/infra/ci/worker/Dockerfile
+++ b/infra/ci/worker/Dockerfile
@@ -23,6 +23,7 @@
 COPY tmp/config.py /home/perfetto/config.py
 COPY tmp/common_utils.py /home/perfetto/common_utils.py
 COPY artifacts_uploader.py /home/perfetto/
+COPY perf_metrics_uploader.py /home/perfetto/
 COPY run_job.py /home/perfetto/
 COPY worker.py /home/perfetto/
 
@@ -42,4 +43,4 @@
 WORKDIR /home/perfetto
 
 ENTRYPOINT [ "tini", "--" ]
-CMD [ "python2", "/home/perfetto/worker.py" ]
\ No newline at end of file
+CMD [ "python2", "/home/perfetto/worker.py" ]
diff --git a/infra/ci/worker/artifacts_uploader.py b/infra/ci/worker/artifacts_uploader.py
index 97b9d37..be9567c 100644
--- a/infra/ci/worker/artifacts_uploader.py
+++ b/infra/ci/worker/artifacts_uploader.py
@@ -28,6 +28,7 @@
 from multiprocessing.pool import ThreadPool
 from oauth2client.client import GoogleCredentials
 
+CUR_DIR = os.path.dirname(__file__)
 RESCAN_PERIOD_SEC = 5  # Scan for new artifact directories every X seconds.
 
 tls = threading.local()
@@ -72,6 +73,16 @@
         yield fpath
 
 
+def scan_and_upload_perf_folder(job_id, dirpath):
+  perf_folder = os.path.join(dirpath, "perf")
+  if not os.path.isdir(perf_folder):
+    return
+
+  uploader = os.path.join(CUR_DIR, 'perf_metrics_uploader.py')
+  for path in list_files(perf_folder):
+    subprocess.call([uploader, '--job-id', job_id, path])
+
+
 def scan_and_uplod_artifacts(pool, remove_after_upload=False):
   root = os.getenv('ARTIFACTS_DIR')
   for job_id in (x for x in os.listdir(root) if not x.endswith('.tmp')):
@@ -88,6 +99,8 @@
       total_size += max(upl_size, 0)
     logging.info('Uploaded artifacts for %s: %d files, %s failures, %d KB',
                  job_id, uploads, failures, total_size / 1e3)
+
+    scan_and_upload_perf_folder(job_id, dirpath)
     if remove_after_upload:
       subprocess.call(['sudo', 'rm', '-rf', dirpath])
 
diff --git a/infra/ci/worker/perf_metrics_uploader.py b/infra/ci/worker/perf_metrics_uploader.py
new file mode 100755
index 0000000..4a43052
--- /dev/null
+++ b/infra/ci/worker/perf_metrics_uploader.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env 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.
+
+import argparse
+import json
+import hashlib
+import sys
+
+from config import DB, PROJECT
+from common_utils import req
+
+'''
+Uploads the performance metrics of the Perfetto tests to StackDriver and
+Firebase.
+
+The expected format of the JSON is as follows:
+{
+  metrics: [
+    {
+      'metric': *metric name*,
+      'value': *metric value*,
+      'unit': *either s (seconds) or b (bytes)*,
+      'tags': {
+        *tag name*: *tag value*,
+        ...
+      },
+      'labels': {
+        *label name*: *label value*,
+        ...
+      }
+    },
+    ...
+  ]
+}
+'''
+
+
+STACKDRIVER_API = 'https://monitoring.googleapis.com/v3/projects/%s' % PROJECT
+
+
+def sha1(obj):
+  hasher = hashlib.sha1()
+  hasher.update(json.dumps(obj, sort_keys=True, separators=(',', ':')))
+  return hasher.hexdigest()
+
+
+def metric_list_to_hash_dict(raw_metrics):
+  metrics = {}
+  for metric in raw_metrics:
+    key = '%s-%s' % (metric['metric'], sha1(metric['tags']))
+    metrics[key] = metric
+  return metrics
+
+
+def create_stackdriver_metrics(ts, metrics):
+  desc = {'timeSeries': []}
+  for _, metric in metrics.iteritems():
+    metric_name = metric['metric']
+    desc['timeSeries'] += [{
+        'metric': {
+          'type': 'custom.googleapis.com/perfetto-ci/perf/%s' % metric_name,
+          'labels': dict(
+            list(metric.get('tags', {}).items()) +
+            list(metric.get('labels', {}).items())
+          ),
+        },
+        'resource': {'type': 'global'},
+        'points': [{
+          'interval': {'endTime': ts},
+          'value': {'doubleValue': str(metric['value'])}
+        }]}]
+  return desc
+
+
+def main():
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--job-id', type=str, required=True,
+                      help='The Perfetto CI job ID to tie this upload to')
+  parser.add_argument('metrics_file', type=str,
+                      help='File containing the metrics to upload')
+  args = parser.parse_args()
+
+  with open(args.metrics_file, 'r') as metrics_file:
+    raw_metrics = json.loads(metrics_file.read())
+
+  job = req('GET', '%s/jobs/%s.json' % (DB, args.job_id))
+  ts = job['time_ended']
+  git_ref = job['env'].get('PERFETTO_TEST_GIT_REF')
+
+  metrics = metric_list_to_hash_dict(raw_metrics['metrics'])
+  req('PUT', '%s/perf/%s.json' % (DB, args.job_id), body=metrics)
+
+  # Only upload Stackdriver metrics for post-submit runs.
+  if git_ref == 'refs/heads/master':
+    sd_metrics = create_stackdriver_metrics(ts, metrics)
+    req('POST', STACKDRIVER_API + '/timeSeries', body=sd_metrics)
+
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/infra/kokoro_ci/dockerfiles/Dockerfile b/infra/kokoro_ci/dockerfiles/Dockerfile
deleted file mode 100644
index 3e37e11..0000000
--- a/infra/kokoro_ci/dockerfiles/Dockerfile
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-# Creates an image that can check out / build / test the perfetto source. The
-# image is used by the Kokoro continuous integration jobs, but is also suitable
-# for local development. There is no pre-defined entrypoint on purpose (to keep
-# it flexible).
-#
-# The built image is available as asia.gcr.io/perfetto-ci/perfetto-ci:latest
-
-FROM debian:latest
-
-ENV DEBIAN_FRONTEND noninteractive
-
-RUN echo deb http://deb.debian.org/debian testing main > /etc/apt/sources.list.d/testing.list
-RUN apt-get update
-RUN apt-get -y install python git curl libxml2 libtinfo5
-# gcc-7 for sysroot
-RUN apt-get -y -t testing install gcc-7
-
-# pip for installing certiain test script dependencies
-RUN curl https://bootstrap.pypa.io/get-pip.py | python -
-
-RUN useradd -m perfetto
-USER perfetto:perfetto
-WORKDIR /home/perfetto
diff --git a/infra/kokoro_ci/kokoro_entry.sh b/infra/kokoro_ci/kokoro_entry.sh
deleted file mode 100755
index 6c3997f..0000000
--- a/infra/kokoro_ci/kokoro_entry.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-# Initial script invoked by Kokoro continuous integration / presubmit jobs.
-# Sets up Kokoro-specific environment, invoking the test script afterwards.
-# What & how to run is carried by environment variables.
-#
-# You shouldn't need to invoke this when running tests locally.
-
-set -eux
-
-SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
-ROOT_DIR="$(realpath ${SCRIPT_DIR}/../..)"
-
-cd ${ROOT_DIR}
-
-# Check that the expected environment variables are present (due to set -u).
-echo PERFETTO_TEST_GN_ARGS: ${PERFETTO_TEST_GN_ARGS}
-echo PERFETTO_TEST_ENTRYPT: ${PERFETTO_TEST_ENTRYPT}
-
-# Make space for docker image by symlinking the hardcoded /var/lib/docker path
-# to a tmpfs mount. Cargo culted from other projects' scripts.
-sudo -n /etc/init.d/docker stop
-sudo -n mv /var/lib/docker /tmpfs/
-sudo -n ln -s /tmpfs/docker /var/lib/docker
-sudo -n /etc/init.d/docker start
-
-# Invoke the tests within a container.
-${SCRIPT_DIR}/run_test_in_container.sh
diff --git a/infra/kokoro_ci/linux/ci-clang-x86_64-asan_lsan_ubsan.cfg b/infra/kokoro_ci/linux/ci-clang-x86_64-asan_lsan_ubsan.cfg
deleted file mode 100644
index 8aa1dba..0000000
--- a/infra/kokoro_ci/linux/ci-clang-x86_64-asan_lsan_ubsan.cfg
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-# Location of the shell script that is the entry point for continuous
-# integration jobs. The first directory in the path is where Kokoro will check
-# out the repository. The rest is the path relative to the repository's root.
-build_file: "perfetto/infra/kokoro_ci/kokoro_entry.sh"
-
-env_vars {
-  key: "PERFETTO_TEST_GN_ARGS"
-  value: "is_debug=false is_ubsan=true is_asan=true is_lsan=true"
-}
-
-env_vars {
-  key: "PERFETTO_TEST_ENTRYPT"
-  value: "infra/kokoro_ci/run_standalone_tests.sh"
-}
-
diff --git a/infra/kokoro_ci/linux/ci-clang-x86_64-msan.cfg b/infra/kokoro_ci/linux/ci-clang-x86_64-msan.cfg
deleted file mode 100644
index 1e85fa4..0000000
--- a/infra/kokoro_ci/linux/ci-clang-x86_64-msan.cfg
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-# Location of the shell script that is the entry point for continuous
-# integration jobs. The first directory in the path is where Kokoro will check
-# out the repository. The rest is the path relative to the repository's root.
-build_file: "perfetto/infra/kokoro_ci/kokoro_entry.sh"
-
-env_vars {
-  key: "PERFETTO_TEST_GN_ARGS"
-  value: "is_debug=false is_msan=true"
-}
-
-env_vars {
-  key: "PERFETTO_TEST_ENTRYPT"
-  value: "infra/kokoro_ci/run_standalone_tests.sh"
-}
-
diff --git a/infra/kokoro_ci/linux/ci-clang-x86_64-tsan.cfg b/infra/kokoro_ci/linux/ci-clang-x86_64-tsan.cfg
deleted file mode 100644
index 22fd946..0000000
--- a/infra/kokoro_ci/linux/ci-clang-x86_64-tsan.cfg
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-# Location of the shell script that is the entry point for continuous
-# integration jobs. The first directory in the path is where Kokoro will check
-# out the repository. The rest is the path relative to the repository's root.
-build_file: "perfetto/infra/kokoro_ci/kokoro_entry.sh"
-
-env_vars {
-  key: "PERFETTO_TEST_GN_ARGS"
-  value: "is_debug=false is_tsan=true"
-}
-
-env_vars {
-  key: "PERFETTO_TEST_ENTRYPT"
-  value: "infra/kokoro_ci/run_standalone_tests.sh"
-}
-
diff --git a/infra/kokoro_ci/linux/ci-ui-clang-x86_64-debug.cfg b/infra/kokoro_ci/linux/ci-ui-clang-x86_64-debug.cfg
deleted file mode 100644
index c67a806..0000000
--- a/infra/kokoro_ci/linux/ci-ui-clang-x86_64-debug.cfg
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-# Location of the shell script that is the entry point for continuous
-# integration jobs. The first directory in the path is where Kokoro will check
-# out the repository. The rest is the path relative to the repository's root.
-build_file: "perfetto/infra/kokoro_ci/kokoro_entry.sh"
-
-env_vars {
-  key: "PERFETTO_TEST_GN_ARGS"
-  value: "is_debug=true"
-}
-
-env_vars {
-  key: "PERFETTO_TEST_ENTRYPT"
-  value: "infra/kokoro_ci/run_ui_tests.sh"
-}
-
diff --git a/infra/kokoro_ci/run_standalone_tests.sh b/infra/kokoro_ci/run_standalone_tests.sh
deleted file mode 100755
index fa3e4e7..0000000
--- a/infra/kokoro_ci/run_standalone_tests.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -eux
-
-SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
-ROOT_DIR="$(realpath ${SCRIPT_DIR}/../..)"
-
-cd ${ROOT_DIR}
-
-# Check that the expected environment variables are present (due to set -u).
-echo PERFETTO_TEST_GN_ARGS: ${PERFETTO_TEST_GN_ARGS}
-
-OUT_PATH="out/dist"
-
-if [[ "$PERFETTO_TEST_GN_ARGS" =~ "android" ]]; then
-tools/install-build-deps
-else
-tools/install-build-deps --no-android
-fi
-
-pip install --quiet --user protobuf
-
-if [[ -e buildtools/clang/bin/llvm-symbolizer ]]; then
-  export ASAN_SYMBOLIZER_PATH="buildtools/clang/bin/llvm-symbolizer"
-  export MSAN_SYMBOLIZER_PATH="buildtools/clang/bin/llvm-symbolizer"
-fi
-
-tools/gn gen ${OUT_PATH} --args="${PERFETTO_TEST_GN_ARGS}" --check
-tools/ninja -C ${OUT_PATH}
-
-# Run the tests
-${OUT_PATH}/perfetto_unittests
-${OUT_PATH}/perfetto_integrationtests
-
-BENCHMARK_FUNCTIONAL_TEST_ONLY=true ${OUT_PATH}/perfetto_benchmarks
-tools/diff_test_trace_processor.py \
-  --test-type=queries ${OUT_PATH}/trace_processor_shell
-tools/diff_test_trace_processor.py \
-  --test-type=metrics ${OUT_PATH}/trace_processor_shell
diff --git a/infra/kokoro_ci/run_test_in_container.sh b/infra/kokoro_ci/run_test_in_container.sh
deleted file mode 100755
index ec743ea..0000000
--- a/infra/kokoro_ci/run_test_in_container.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -eux
-
-SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
-ROOT_DIR="$(realpath ${SCRIPT_DIR}/../..)"
-
-cd ${ROOT_DIR}
-
-# Check that the expected environment variables are present (due to set -u).
-echo PERFETTO_TEST_GN_ARGS: ${PERFETTO_TEST_GN_ARGS}
-echo PERFETTO_TEST_ENTRYPT: ${PERFETTO_TEST_ENTRYPT}
-
-# Run PERFETTO_TEST_ENTRYPOINT inside the container with the following setup:
-# Mount (readonly) the current source directory inside the container. Enter the
-# container as root, make a mutable copy the source tree, and then invoke
-# the test script as that user.
-#
-# SYS_PTRACE capability is added for [at least] the leak sanitizer.
-# TODO(rsavitski): figure out why "su perfetto -c" was messing with the test
-# scripts (at least the output truncation).
-sudo docker run --rm -t \
-  --user=root:root \
-  --cap-add=SYS_PTRACE \
-  -e PERFETTO_TEST_GN_ARGS="${PERFETTO_TEST_GN_ARGS}" \
-  -v ${ROOT_DIR}:/perfetto:ro \
-  asia.gcr.io/perfetto-ci/perfetto-ci:latest \
-  /bin/bash \
-  "-c" \
-  "cp -r /perfetto /home/perfetto/src && \
-  cd /home/perfetto/src && \
-  ${PERFETTO_TEST_ENTRYPT}"
diff --git a/infra/kokoro_ci/run_ui_tests.sh b/infra/kokoro_ci/run_ui_tests.sh
deleted file mode 100755
index 906d9ea..0000000
--- a/infra/kokoro_ci/run_ui_tests.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -eux
-
-SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
-ROOT_DIR="$(realpath ${SCRIPT_DIR}/../..)"
-
-cd ${ROOT_DIR}
-
-# Check that the expected environment variables are present (due to set -u).
-echo PERFETTO_TEST_GN_ARGS: ${PERFETTO_TEST_GN_ARGS}
-
-OUT_PATH="out/dist"
-
-tools/install-build-deps --no-android --ui
-
-tools/gn gen ${OUT_PATH} --args="${PERFETTO_TEST_GN_ARGS}" --check
-tools/ninja -C ${OUT_PATH} ui 2>&1 | grep -v "no version information available"
-
-# Run the tests
-${OUT_PATH}/ui_unittests --ci
diff --git a/protos/BUILD b/protos/BUILD
index 0c88c40..b5ea3bd 100644
--- a/protos/BUILD
+++ b/protos/BUILD
@@ -387,6 +387,7 @@
         "perfetto/trace/test_event.proto",
         "perfetto/trace/trace.proto",
         "perfetto/trace/trace_packet.proto",
+        "perfetto/trace/trace_packet_defaults.proto",
     ],
     has_services = 1,
     cc_api_version = 2,
@@ -418,6 +419,7 @@
     name = "trace_android",
     srcs = [
         "perfetto/trace/android/android_log.proto",
+        "perfetto/trace/android/graphics_frame_event.proto",
         "perfetto/trace/android/packages_list.proto",
     ],
     has_services = 1,
@@ -458,6 +460,7 @@
     name = "trace_android_zero",
     srcs = [
         "perfetto/trace/android/android_log.proto",
+        "perfetto/trace/android/graphics_frame_event.proto",
         "perfetto/trace/android/packages_list.proto",
     ],
     deps = [
@@ -1336,6 +1339,7 @@
         "perfetto/trace/test_event.proto",
         "perfetto/trace/trace.proto",
         "perfetto/trace/trace_packet.proto",
+        "perfetto/trace/trace_packet_defaults.proto",
         "perfetto/trace/trigger.proto",
     ],
     deps = [
diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto
index 7561682..c1c0917 100644
--- a/protos/perfetto/config/perfetto_config.proto
+++ b/protos/perfetto/config/perfetto_config.proto
@@ -518,7 +518,7 @@
 // It contains the general config for the logging buffer(s) and the configs for
 // all the data source being enabled.
 //
-// Next id: 26.
+// Next id: 27.
 message TraceConfig {
   message BufferConfig {
     optional uint32 size_kb = 1;
@@ -793,6 +793,9 @@
     optional bool skip_dropbox = 4;
   }
   optional IncidentReportConfig incident_report_config = 25;
+
+  // An identifier clients can use to tie this trace to other logging.
+  optional bytes trace_uuid = 26;
 }
 
 // End of protos/perfetto/config/trace_config.proto
diff --git a/protos/perfetto/config/trace_config.proto b/protos/perfetto/config/trace_config.proto
index e684c66..a823fbe 100644
--- a/protos/perfetto/config/trace_config.proto
+++ b/protos/perfetto/config/trace_config.proto
@@ -29,7 +29,7 @@
 // It contains the general config for the logging buffer(s) and the configs for
 // all the data source being enabled.
 //
-// Next id: 26.
+// Next id: 27.
 message TraceConfig {
   message BufferConfig {
     optional uint32 size_kb = 1;
@@ -304,4 +304,7 @@
     optional bool skip_dropbox = 4;
   }
   optional IncidentReportConfig incident_report_config = 25;
+
+  // An identifier clients can use to tie this trace to other logging.
+  optional bytes trace_uuid = 26;
 }
diff --git a/protos/perfetto/ipc/producer_port.proto b/protos/perfetto/ipc/producer_port.proto
index 9368912..75a89de 100644
--- a/protos/perfetto/ipc/producer_port.proto
+++ b/protos/perfetto/ipc/producer_port.proto
@@ -114,6 +114,17 @@
 
   // If provided, overrides the service's SMB scraping setting for the producer.
   optional ProducerSMBScrapingMode smb_scraping_mode = 4;
+
+  enum ProducerBuildFlags {
+    BUILD_FLAGS_UNSPECIFIED = 0;
+    BUILD_FLAGS_DCHECKS_ON = 1;
+    BUILD_FLAGS_DCHECKS_OFF = 2;
+  }
+
+  // If provided, reports the build flags of the producer. It's used merely for
+  // error reporting, to print a log message when a producer connects to a
+  // service that has mismatching build flags.
+  optional ProducerBuildFlags build_flags = 5;
 }
 
 message InitializeConnectionResponse {
diff --git a/protos/perfetto/metrics/android/mem_metric.proto b/protos/perfetto/metrics/android/mem_metric.proto
index 25f198b..0443c0d 100644
--- a/protos/perfetto/metrics/android/mem_metric.proto
+++ b/protos/perfetto/metrics/android/mem_metric.proto
@@ -37,6 +37,9 @@
     optional Counter file_rss = 2;
     optional Counter swap = 3;
     optional Counter anon_and_swap = 4;
+
+    // Available when ART trace events are available.
+    optional Counter java_heap = 5;
   }
 
   message Counter {
diff --git a/protos/perfetto/trace/BUILD.gn b/protos/perfetto/trace/BUILD.gn
index bbab12a..8c6934a 100644
--- a/protos/perfetto/trace/BUILD.gn
+++ b/protos/perfetto/trace/BUILD.gn
@@ -28,6 +28,7 @@
 proto_sources_trusted = [ "trusted_packet.proto" ]
 
 proto_sources = [
+  "trace_packet_defaults.proto",
   "test_event.proto",
   "trace_packet.proto",
   "trace.proto",
diff --git a/protos/perfetto/trace/android/BUILD.gn b/protos/perfetto/trace/android/BUILD.gn
index 72a3e3c..9a382aa 100644
--- a/protos/perfetto/trace/android/BUILD.gn
+++ b/protos/perfetto/trace/android/BUILD.gn
@@ -18,6 +18,7 @@
 
 android_proto_names = [
   "android_log.proto",
+  "graphics_frame_event.proto",
   "packages_list.proto",
 ]
 
diff --git a/protos/perfetto/trace/android/graphics_frame_event.proto b/protos/perfetto/trace/android/graphics_frame_event.proto
new file mode 100644
index 0000000..68248f9
--- /dev/null
+++ b/protos/perfetto/trace/android/graphics_frame_event.proto
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+package perfetto.protos;
+
+// Generated by Android's SurfaceFlinger.
+message GraphicsFrameEvent {
+  enum BufferEventType {
+    UNSPECIFIED = 0;
+    DEQUEUE = 1;
+    QUEUE = 2;
+    POST = 3;
+    ACQUIRE_FENCE = 4;
+    LATCH = 5;
+    HWC_COMPOSITION_QUEUED = 6;  // HWC will compose this buffer
+    FALLBACK_COMPOSITION = 7;    // renderEngine composition
+    PRESENT_FENCE = 8;
+    RELEASE_FENCE = 9;
+    MODIFY = 10;
+  }
+
+  message BufferEvent {
+    optional uint32 frame_number = 1;
+    optional BufferEventType type = 2;
+    optional string layer_name = 3;
+    // If no duration is set, the event is an instant event.
+    optional uint64 duration_ns = 4;
+    // Unique buffer identifier.
+    optional uint32 buffer_id = 5;
+  }
+
+  optional BufferEvent buffer_event = 1;
+}
diff --git a/protos/perfetto/trace/clock_snapshot.proto b/protos/perfetto/trace/clock_snapshot.proto
index 7cf74ba..12ce1b6 100644
--- a/protos/perfetto/trace/clock_snapshot.proto
+++ b/protos/perfetto/trace/clock_snapshot.proto
@@ -22,7 +22,7 @@
 // A snapshot of clock readings to allow for trace alignment.
 message ClockSnapshot {
   message Clock {
-    enum Type {
+    enum BuiltinClocks {
       UNKNOWN = 0;
       REALTIME = 1;
       REALTIME_COARSE = 2;
@@ -32,9 +32,35 @@
       BOOTTIME = 6;
       PROCESS_CPUTIME = 7;
       THREAD_CPUTIME = 8;
+      BUILTIN_CLOCK_MAX_ID = 63;
     }
-    optional Type type = 1;
+
+    // Clock IDs have the following semantic:
+    // [1, 63]:    Builtin types, see BuiltinClocks above.
+    // [64, 127]:  User-defined clocks. These clocks are sequence-scoped. They
+    //             are only valid within the same |trusted_packet_sequence_id|
+    //             (i.e. only for TracePacket(s) emitted by the same TraceWriter
+    //             that emitted the clock snapshot).
+    // [128, MAX]: Reserved for future use. The idea is to allow global clock
+    //             IDs and setting this ID to hash(full_clock_name) & ~127.
+    optional uint32 clock_id = 1;
+
+    // Unit is ns unless specified otherwise by the resolution_* fields below.
     optional uint64 timestamp = 2;
+
+    // TODO(eseckler): the fields below and sequence-scoped clock IDs are not
+    // supported yet by the trace processor.
+
+    // When true the timestamp should be interpreted as a delta from the last
+    // TracePacket's timestamp emitted by the same packet_sequence_id.
+    // The first packet timestamp after a ClockSnapshot is relative to the last
+    // ClockSnapshot seen on the packet sequence.
+    // optional bool is_incremental = 3;
+
+    // Allows to specify a custom unit different than the default (ns)
+    // for this clock domain. A multiplier of 1000 means that a timestamp = 3
+    // should be interpreted as 3000 ns = 3 us.
+    // optional uint64 unit_multiplier_ns = 4;
   }
   repeated Clock clocks = 1;
 }
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index e52ed45..b69b9f0 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -389,6 +389,39 @@
 
 // End of protos/perfetto/trace/android/android_log.proto
 
+// Begin of protos/perfetto/trace/android/graphics_frame_event.proto
+
+// Generated by Android's SurfaceFlinger.
+message GraphicsFrameEvent {
+  enum BufferEventType {
+    UNSPECIFIED = 0;
+    DEQUEUE = 1;
+    QUEUE = 2;
+    POST = 3;
+    ACQUIRE_FENCE = 4;
+    LATCH = 5;
+    HWC_COMPOSITION_QUEUED = 6;  // HWC will compose this buffer
+    FALLBACK_COMPOSITION = 7;    // renderEngine composition
+    PRESENT_FENCE = 8;
+    RELEASE_FENCE = 9;
+    MODIFY = 10;
+  }
+
+  message BufferEvent {
+    optional uint32 frame_number = 1;
+    optional BufferEventType type = 2;
+    optional string layer_name = 3;
+    // If no duration is set, the event is an instant event.
+    optional uint64 duration_ns = 4;
+    // Unique buffer identifier.
+    optional uint32 buffer_id = 5;
+  }
+
+  optional BufferEvent buffer_event = 1;
+}
+
+// End of protos/perfetto/trace/android/graphics_frame_event.proto
+
 // Begin of protos/perfetto/trace/android/packages_list.proto
 
 message PackagesList {
@@ -510,7 +543,7 @@
 // A snapshot of clock readings to allow for trace alignment.
 message ClockSnapshot {
   message Clock {
-    enum Type {
+    enum BuiltinClocks {
       UNKNOWN = 0;
       REALTIME = 1;
       REALTIME_COARSE = 2;
@@ -520,9 +553,35 @@
       BOOTTIME = 6;
       PROCESS_CPUTIME = 7;
       THREAD_CPUTIME = 8;
+      BUILTIN_CLOCK_MAX_ID = 63;
     }
-    optional Type type = 1;
+
+    // Clock IDs have the following semantic:
+    // [1, 63]:    Builtin types, see BuiltinClocks above.
+    // [64, 127]:  User-defined clocks. These clocks are sequence-scoped. They
+    //             are only valid within the same |trusted_packet_sequence_id|
+    //             (i.e. only for TracePacket(s) emitted by the same TraceWriter
+    //             that emitted the clock snapshot).
+    // [128, MAX]: Reserved for future use. The idea is to allow global clock
+    //             IDs and setting this ID to hash(full_clock_name) & ~127.
+    optional uint32 clock_id = 1;
+
+    // Unit is ns unless specified otherwise by the resolution_* fields below.
     optional uint64 timestamp = 2;
+
+    // TODO(eseckler): the fields below and sequence-scoped clock IDs are not
+    // supported yet by the trace processor.
+
+    // When true the timestamp should be interpreted as a delta from the last
+    // TracePacket's timestamp emitted by the same packet_sequence_id.
+    // The first packet timestamp after a ClockSnapshot is relative to the last
+    // ClockSnapshot seen on the packet sequence.
+    // optional bool is_incremental = 3;
+
+    // Allows to specify a custom unit different than the default (ns)
+    // for this clock domain. A multiplier of 1000 means that a timestamp = 3
+    // should be interpreted as 3000 ns = 3 us.
+    // optional uint64 unit_multiplier_ns = 4;
   }
   repeated Clock clocks = 1;
 }
@@ -3132,11 +3191,22 @@
 // TracePacket(s).
 //
 // Next reserved id: 13 (up to 15).
-// Next id: 57.
+// Next id: 60.
 message TracePacket {
-  // TODO(primiano): in future we should add a timestamp_clock_domain field to
-  // allow mixing timestamps from different clock domains.
-  optional uint64 timestamp = 8;  // Timestamp [ns].
+  // The timestamp of the TracePacket.
+  // By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
+  // Android). It can be overridden using a different timestamp_clock_id.
+  // The clock domain definition in ClockSnapshot can also override:
+  // - The unit (default: 1ns).
+  // - The absolute vs delta encoding (default: absolute timestamp).
+  optional uint64 timestamp = 8;
+
+  // Specifies the ID of the clock used for the TracePacket |timestamp|. Can be
+  // one of the built-in types from ClockSnapshot::BuiltinClocks, or a
+  // producer-defined clock id.
+  // If unspecified and if no default per-sequence value has been provided via
+  // TracePacketDefaults, it defaults to BuiltinClocks::BOOTTIME.
+  optional uint32 timestamp_clock_id = 58;
 
   oneof data {
     FtraceEventBundle ftrace_events = 1;
@@ -3168,6 +3238,7 @@
     GpuRenderStageEvent gpu_render_stage_event = 53;
     StreamingProfilePacket streaming_profile_packet = 54;
     HeapGraph heap_graph = 56;
+    GraphicsFrameEvent graphics_frame_event = 57;
 
     // Only used in profile packets.
     ProfiledFrameSymbols profiled_frame_symbols = 55;
@@ -3218,22 +3289,47 @@
   // proactively in advance of referring to them in later packets.
   optional InternedData interned_data = 12;
 
-  // Set to true by the writer to indicate that it will re-emit any incremental
-  // data for the packet's sequence before referring to it again. This includes
-  // interned data as well as periodically emitted data like
-  // Process/ThreadDescriptors. This flag only affects the current packet
-  // sequence (see |trusted_packet_sequence_id|).
-  //
-  // When set to true, this TracePacket and subsequent TracePackets on the same
-  // sequence will not refer to any incremental data emitted before this
-  // TracePacket. For example, previously emitted interned data will be
-  // re-emitted if it is referred to again.
-  //
-  // When the reader detects packet loss (|previous_packet_dropped|), it needs
-  // to skip packets in the sequence until the next one with this flag set, to
-  // ensure intact incremental data.
+  enum SequenceFlags {
+    SEQ_UNSPECIFIED = 0;
+
+    // Set by the writer to indicate that it will re-emit any incremental data
+    // for the packet's sequence before referring to it again. This includes
+    // interned data as well as periodically emitted data like
+    // Process/ThreadDescriptors. This flag only affects the current packet
+    // sequence (see |trusted_packet_sequence_id|).
+    //
+    // When set, this TracePacket and subsequent TracePackets on the same
+    // sequence will not refer to any incremental data emitted before this
+    // TracePacket. For example, previously emitted interned data will be
+    // re-emitted if it is referred to again.
+    //
+    // When the reader detects packet loss (|previous_packet_dropped|), it needs
+    // to skip packets in the sequence until the next one with this flag set, to
+    // ensure intact incremental data.
+    SEQ_INCREMENTAL_STATE_CLEARED = 1;
+
+    // This packet requires incremental state, such as TracePacketDefaults or
+    // InternedData, to be parsed correctly. The trace reader should skip this
+    // packet if incremental state is not valid on this sequence, i.e. if no
+    // packet with the SEQ_INCREMENTAL_STATE_CLEARED flag has been seen on the
+    // current |trusted_packet_sequence_id|.
+    SEQ_NEEDS_INCREMENTAL_STATE = 2;
+  };
+  optional uint32 sequence_flags = 13;
+
+  // DEPRECATED. Moved to SequenceFlags::SEQ_INCREMENTAL_STATE_CLEARED.
   optional bool incremental_state_cleared = 41;
 
+  // Default values for fields of later TracePackets emitted on this packet's
+  // sequence (TracePackets with the same |trusted_packet_sequence_id|).
+  // It must be reemitted when incremental state is cleared (see
+  // |incremental_state_cleared|).
+  // Requires that any future packet emitted on the same sequence specifies
+  // the SEQ_NEEDS_INCREMENTAL_STATE flag.
+  // TracePacketDefaults always override the global defaults for any future
+  // packet on this sequence (regardless of SEQ_NEEDS_INCREMENTAL_STATE).
+  optional TracePacketDefaults trace_packet_defaults = 59;
+
   // Flag set by the service if, for the current packet sequence (see
   // |trusted_packet_sequence_id|), either:
   // * this is the first packet, or
@@ -3250,6 +3346,24 @@
 
 // End of protos/perfetto/trace/trace_packet.proto
 
+// Begin of protos/perfetto/trace/trace_packet_defaults.proto
+
+// Default values for TracePacket fields that hold for a particular TraceWriter
+// packet sequence. This message contains a subset of the TracePacket fields
+// with matching IDs. When provided, these fields define the default values
+// that should be applied, at import time, to all TracePacket(s) with the same
+// |trusted_packet_sequence_id|, unless otherwise specified in each packet.
+message TracePacketDefaults {
+  optional uint32 timestamp_clock_id = 58;
+
+  // TODO(eseckler): Add default values for TrackEvents (e.g. default track).
+  message TrackEventDefaults {
+    // optional int32 tid = ...;
+  }
+  optional TrackEventDefaults track_event = 11;
+}
+// End of protos/perfetto/trace/trace_packet_defaults.proto
+
 // Begin of protos/perfetto/trace/track_event/debug_annotation.proto
 
 // Key/value annotations provided in untyped TRACE_EVENT macros. These
@@ -3450,7 +3564,7 @@
 // association) are emitted as part of ProcessDescriptor and ThreadDescriptor
 // messages in separate TracePackets instead.
 //
-// Next reserved id: 8 (up to 15).
+// Next reserved id: 10 (up to 15).
 // Next id: 22.
 message TrackEvent {
   // Timestamp in microseconds (usually CLOCK_MONOTONIC).
@@ -3489,11 +3603,33 @@
     int64 thread_instruction_count_absolute = 20;
   }
 
+  // TODO(eseckler): Add a way to specify Tracks.
+
   // We intend to add a binary symbol version of this in the future.
   repeated uint64 category_iids = 3;  // interned EventCategoryName.
 
   // TODO(eseckler): May also want a debug_name for untyped debug-only events.
 
+  // Type of the TrackEvent (required if |phase| in LegacyEvent is not set).
+  enum Type {
+    TYPE_UNSPECIFIED = 0;
+
+    // Slice events are always formed by a pair of BEGIN + END events. END
+    // events do not need to repeat any TrackEvent fields they have in common
+    // with their corresponding BEGIN event. Arguments and debug annotations of
+    // the BEGIN + END pair will be merged during trace import.
+    //
+    // Note that we deliberately chose not to support COMPLETE events since
+    // clients would need to delay writing them until the slice is completed,
+    // which can result in reordered events in the trace and loss of unfinished
+    // events at the end of a trace.
+    TYPE_SLICE_BEGIN = 1;
+    TYPE_SLICE_END = 2;
+
+    // TODO(eseckler): Add support for counters.
+  }
+  optional Type type = 9;
+
   // Unstable key/value annotations shown in the trace viewer but not intended
   // for metrics use.
   repeated DebugAnnotation debug_annotations = 4;
@@ -4171,7 +4307,7 @@
 // It contains the general config for the logging buffer(s) and the configs for
 // all the data source being enabled.
 //
-// Next id: 26.
+// Next id: 27.
 message TraceConfig {
   message BufferConfig {
     optional uint32 size_kb = 1;
@@ -4446,6 +4582,9 @@
     optional bool skip_dropbox = 4;
   }
   optional IncidentReportConfig incident_report_config = 25;
+
+  // An identifier clients can use to tie this trace to other logging.
+  optional bytes trace_uuid = 26;
 }
 
 // End of protos/perfetto/config/trace_config.proto
diff --git a/protos/perfetto/trace/trace_packet.proto b/protos/perfetto/trace/trace_packet.proto
index 8b79a22..7bd383a 100644
--- a/protos/perfetto/trace/trace_packet.proto
+++ b/protos/perfetto/trace/trace_packet.proto
@@ -20,6 +20,7 @@
 import "perfetto/common/trace_stats.proto";
 import "perfetto/config/trace_config.proto";
 import "perfetto/trace/android/android_log.proto";
+import "perfetto/trace/android/graphics_frame_event.proto";
 import "perfetto/trace/android/packages_list.proto";
 import "perfetto/trace/chrome/chrome_benchmark_metadata.proto";
 import "perfetto/trace/chrome/chrome_metadata.proto";
@@ -41,6 +42,7 @@
 import "perfetto/trace/ps/process_tree.proto";
 import "perfetto/trace/sys_stats/sys_stats.proto";
 import "perfetto/trace/system_info.proto";
+import "perfetto/trace/trace_packet_defaults.proto";
 import "perfetto/trace/track_event/process_descriptor.proto";
 import "perfetto/trace/track_event/thread_descriptor.proto";
 import "perfetto/trace/track_event/track_event.proto";
@@ -53,11 +55,22 @@
 // TracePacket(s).
 //
 // Next reserved id: 13 (up to 15).
-// Next id: 57.
+// Next id: 60.
 message TracePacket {
-  // TODO(primiano): in future we should add a timestamp_clock_domain field to
-  // allow mixing timestamps from different clock domains.
-  optional uint64 timestamp = 8;  // Timestamp [ns].
+  // The timestamp of the TracePacket.
+  // By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
+  // Android). It can be overridden using a different timestamp_clock_id.
+  // The clock domain definition in ClockSnapshot can also override:
+  // - The unit (default: 1ns).
+  // - The absolute vs delta encoding (default: absolute timestamp).
+  optional uint64 timestamp = 8;
+
+  // Specifies the ID of the clock used for the TracePacket |timestamp|. Can be
+  // one of the built-in types from ClockSnapshot::BuiltinClocks, or a
+  // producer-defined clock id.
+  // If unspecified and if no default per-sequence value has been provided via
+  // TracePacketDefaults, it defaults to BuiltinClocks::BOOTTIME.
+  optional uint32 timestamp_clock_id = 58;
 
   oneof data {
     FtraceEventBundle ftrace_events = 1;
@@ -89,6 +102,7 @@
     GpuRenderStageEvent gpu_render_stage_event = 53;
     StreamingProfilePacket streaming_profile_packet = 54;
     HeapGraph heap_graph = 56;
+    GraphicsFrameEvent graphics_frame_event = 57;
 
     // Only used in profile packets.
     ProfiledFrameSymbols profiled_frame_symbols = 55;
@@ -139,22 +153,47 @@
   // proactively in advance of referring to them in later packets.
   optional InternedData interned_data = 12;
 
-  // Set to true by the writer to indicate that it will re-emit any incremental
-  // data for the packet's sequence before referring to it again. This includes
-  // interned data as well as periodically emitted data like
-  // Process/ThreadDescriptors. This flag only affects the current packet
-  // sequence (see |trusted_packet_sequence_id|).
-  //
-  // When set to true, this TracePacket and subsequent TracePackets on the same
-  // sequence will not refer to any incremental data emitted before this
-  // TracePacket. For example, previously emitted interned data will be
-  // re-emitted if it is referred to again.
-  //
-  // When the reader detects packet loss (|previous_packet_dropped|), it needs
-  // to skip packets in the sequence until the next one with this flag set, to
-  // ensure intact incremental data.
+  enum SequenceFlags {
+    SEQ_UNSPECIFIED = 0;
+
+    // Set by the writer to indicate that it will re-emit any incremental data
+    // for the packet's sequence before referring to it again. This includes
+    // interned data as well as periodically emitted data like
+    // Process/ThreadDescriptors. This flag only affects the current packet
+    // sequence (see |trusted_packet_sequence_id|).
+    //
+    // When set, this TracePacket and subsequent TracePackets on the same
+    // sequence will not refer to any incremental data emitted before this
+    // TracePacket. For example, previously emitted interned data will be
+    // re-emitted if it is referred to again.
+    //
+    // When the reader detects packet loss (|previous_packet_dropped|), it needs
+    // to skip packets in the sequence until the next one with this flag set, to
+    // ensure intact incremental data.
+    SEQ_INCREMENTAL_STATE_CLEARED = 1;
+
+    // This packet requires incremental state, such as TracePacketDefaults or
+    // InternedData, to be parsed correctly. The trace reader should skip this
+    // packet if incremental state is not valid on this sequence, i.e. if no
+    // packet with the SEQ_INCREMENTAL_STATE_CLEARED flag has been seen on the
+    // current |trusted_packet_sequence_id|.
+    SEQ_NEEDS_INCREMENTAL_STATE = 2;
+  };
+  optional uint32 sequence_flags = 13;
+
+  // DEPRECATED. Moved to SequenceFlags::SEQ_INCREMENTAL_STATE_CLEARED.
   optional bool incremental_state_cleared = 41;
 
+  // Default values for fields of later TracePackets emitted on this packet's
+  // sequence (TracePackets with the same |trusted_packet_sequence_id|).
+  // It must be reemitted when incremental state is cleared (see
+  // |incremental_state_cleared|).
+  // Requires that any future packet emitted on the same sequence specifies
+  // the SEQ_NEEDS_INCREMENTAL_STATE flag.
+  // TracePacketDefaults always override the global defaults for any future
+  // packet on this sequence (regardless of SEQ_NEEDS_INCREMENTAL_STATE).
+  optional TracePacketDefaults trace_packet_defaults = 59;
+
   // Flag set by the service if, for the current packet sequence (see
   // |trusted_packet_sequence_id|), either:
   // * this is the first packet, or
diff --git a/protos/perfetto/trace/trace_packet_defaults.proto b/protos/perfetto/trace/trace_packet_defaults.proto
new file mode 100644
index 0000000..8b973de
--- /dev/null
+++ b/protos/perfetto/trace/trace_packet_defaults.proto
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+// Default values for TracePacket fields that hold for a particular TraceWriter
+// packet sequence. This message contains a subset of the TracePacket fields
+// with matching IDs. When provided, these fields define the default values
+// that should be applied, at import time, to all TracePacket(s) with the same
+// |trusted_packet_sequence_id|, unless otherwise specified in each packet.
+message TracePacketDefaults {
+  optional uint32 timestamp_clock_id = 58;
+
+  // TODO(eseckler): Add default values for TrackEvents (e.g. default track).
+  message TrackEventDefaults {
+    // optional int32 tid = ...;
+  }
+  optional TrackEventDefaults track_event = 11;
+}
\ No newline at end of file
diff --git a/protos/perfetto/trace/track_event/track_event.proto b/protos/perfetto/trace/track_event/track_event.proto
index 414bb8b7..6cd4e8a 100644
--- a/protos/perfetto/trace/track_event/track_event.proto
+++ b/protos/perfetto/trace/track_event/track_event.proto
@@ -40,7 +40,7 @@
 // association) are emitted as part of ProcessDescriptor and ThreadDescriptor
 // messages in separate TracePackets instead.
 //
-// Next reserved id: 8 (up to 15).
+// Next reserved id: 10 (up to 15).
 // Next id: 22.
 message TrackEvent {
   // Timestamp in microseconds (usually CLOCK_MONOTONIC).
@@ -79,11 +79,33 @@
     int64 thread_instruction_count_absolute = 20;
   }
 
+  // TODO(eseckler): Add a way to specify Tracks.
+
   // We intend to add a binary symbol version of this in the future.
   repeated uint64 category_iids = 3;  // interned EventCategoryName.
 
   // TODO(eseckler): May also want a debug_name for untyped debug-only events.
 
+  // Type of the TrackEvent (required if |phase| in LegacyEvent is not set).
+  enum Type {
+    TYPE_UNSPECIFIED = 0;
+
+    // Slice events are always formed by a pair of BEGIN + END events. END
+    // events do not need to repeat any TrackEvent fields they have in common
+    // with their corresponding BEGIN event. Arguments and debug annotations of
+    // the BEGIN + END pair will be merged during trace import.
+    //
+    // Note that we deliberately chose not to support COMPLETE events since
+    // clients would need to delay writing them until the slice is completed,
+    // which can result in reordered events in the trace and loss of unfinished
+    // events at the end of a trace.
+    TYPE_SLICE_BEGIN = 1;
+    TYPE_SLICE_END = 2;
+
+    // TODO(eseckler): Add support for counters.
+  }
+  optional Type type = 9;
+
   // Unstable key/value annotations shown in the trace viewer but not intended
   // for metrics use.
   repeated DebugAnnotation debug_annotations = 4;
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index 0afcd5e..1d2e8a3 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -36,6 +36,7 @@
     "uuid.cc",
     "virtual_destructors.cc",
     "waitable_event.cc",
+    "watchdog_posix.cc",
   ]
 
   # TODO(brucedawson): Enable these for Windows when possible.
@@ -49,10 +50,6 @@
     ]
   }
 
-  if ((perfetto_build_standalone || perfetto_build_with_android) &&
-      (is_linux || is_android) && !is_wasm) {
-    sources += [ "watchdog_posix.cc" ]
-  }
   if (is_debug && perfetto_build_standalone && !is_wasm) {
     deps += [ ":debug_crash_stack_trace" ]
   }
diff --git a/src/base/uuid.cc b/src/base/uuid.cc
index 32eea20..3375661 100644
--- a/src/base/uuid.cc
+++ b/src/base/uuid.cc
@@ -24,9 +24,9 @@
 namespace base {
 
 // See https://www.ietf.org/rfc/rfc4122.txt
-std::array<uint8_t, 16> Uuidv4() {
+Uuid Uuidv4() {
   static std::minstd_rand rng(static_cast<uint32_t>(GetBootTimeNs().count()));
-  std::array<uint8_t, 16> uuid;
+  Uuid uuid;
   for (size_t i = 0; i < 16; ++i)
     uuid[i] = static_cast<uint8_t>(rng());
 
@@ -38,5 +38,18 @@
   return uuid;
 }
 
+std::string UuidToString(const Uuid& uuid) {
+  return std::string(reinterpret_cast<const char*>(uuid.data()), uuid.size());
+}
+
+Uuid StringToUuid(const std::string& s) {
+  Uuid uuid;
+  PERFETTO_CHECK(s.size() == uuid.size());
+  for (size_t i = 0; i < uuid.size(); ++i) {
+    uuid[i] = static_cast<uint8_t>(s[i]);
+  }
+  return uuid;
+}
+
 }  // namespace base
 }  // namespace perfetto
diff --git a/src/base/uuid_unittest.cc b/src/base/uuid_unittest.cc
index 913e755..aa03837 100644
--- a/src/base/uuid_unittest.cc
+++ b/src/base/uuid_unittest.cc
@@ -23,11 +23,16 @@
 namespace {
 
 TEST(Uuid, TwoUuidsShouldBeDifferent) {
-  std::array<uint8_t, 16> a = Uuidv4();
-  std::array<uint8_t, 16> b = Uuidv4();
+  Uuid a = Uuidv4();
+  Uuid b = Uuidv4();
   EXPECT_NE(a, b);
 }
 
+TEST(Uuid, CanRoundTripUuid) {
+  Uuid uuid = Uuidv4();
+  EXPECT_EQ(StringToUuid(UuidToString(uuid)), uuid);
+}
+
 }  // namespace
 }  // namespace base
 }  // namespace perfetto
diff --git a/src/base/watchdog_posix.cc b/src/base/watchdog_posix.cc
index 9a8965e..98a3d3c 100644
--- a/src/base/watchdog_posix.cc
+++ b/src/base/watchdog_posix.cc
@@ -14,16 +14,9 @@
  * limitations under the License.
  */
 
-#include "perfetto/base/build_config.h"
+#include "perfetto/ext/base/watchdog.h"
 
-// Watchdog is currently not supported on Mac. This ifdef-based exclusion is
-// here only for the Mac build in AOSP. The standalone and chromium builds
-// exclude this file at the GN level. However, propagating the per-os exclusion
-// through our GN -> BP build file translator is not worth the effort for a
-// one-off case.
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
-
-#include "perfetto/ext/base/watchdog_posix.h"
+#if PERFETTO_USE_POSIX_WATCHDOG()
 
 #include <fcntl.h>
 #include <inttypes.h>
@@ -38,10 +31,6 @@
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/thread_utils.h"
 
-#if PERFETTO_BUILDFLAG(PERFETTO_EMBEDDER_BUILD)
-#error perfetto::base::Watchdog should not be used in Chromium or embedders
-#endif
-
 namespace perfetto {
 namespace base {
 
@@ -270,4 +259,4 @@
 }  // namespace base
 }  // namespace perfetto
 
-#endif  // PERFETTO_OS_MACOSX
+#endif  // PERFETTO_USE_POSIX_WATCHDOG()
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index 4078a88..523067d 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -452,6 +452,10 @@
     return 1;
   }
 
+  if (trace_config_->trace_uuid().empty() || !dropbox_tag_.empty()) {
+    trace_config_->set_trace_uuid(base::UuidToString(base::Uuidv4()));
+  }
+
   if (!trace_config_->incident_report_config().destination_package().empty()) {
     if (dropbox_tag_.empty()) {
       PERFETTO_ELOG("Unexpected IncidentReportConfig without --dropbox.");
diff --git a/src/perfetto_cmd/perfetto_cmd.h b/src/perfetto_cmd/perfetto_cmd.h
index 7395936..ce4ef6b 100644
--- a/src/perfetto_cmd/perfetto_cmd.h
+++ b/src/perfetto_cmd/perfetto_cmd.h
@@ -28,6 +28,7 @@
 #include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/scoped_file.h"
 #include "perfetto/ext/base/unix_task_runner.h"
+#include "perfetto/ext/base/uuid.h"
 #include "perfetto/ext/tracing/core/consumer.h"
 #include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
 #include "src/perfetto_cmd/rate_limiter.h"
diff --git a/src/perfetto_cmd/perfetto_config.descriptor.h b/src/perfetto_cmd/perfetto_config.descriptor.h
index a007470..a088984 100644
--- a/src/perfetto_cmd/perfetto_config.descriptor.h
+++ b/src/perfetto_cmd/perfetto_config.descriptor.h
@@ -12,15 +12,15 @@
 // SHA1(tools/gen_binary_descriptors)
 // 750d7d8f95621b45d4b6430d6f8808087a8702e6
 // SHA1(protos/perfetto/config/perfetto_config.proto)
-// f2788058e253eabce51edb438294ceb1a1256c29
+// 52d9cff0b3e68b039fbf8cfacd4976c4cc5c10d4
 
 // This is the proto PerfettoConfig encoded as a ProtoFileDescriptor to allow
 // for reflection without libprotobuf full/non-lite protos.
 
 namespace perfetto {
 
-constexpr std::array<uint8_t, 12319> kPerfettoConfigDescriptor{
-    {0x0a, 0x9c, 0x60, 0x0a, 0x25, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+constexpr std::array<uint8_t, 12350> kPerfettoConfigDescriptor{
+    {0x0a, 0xbb, 0x60, 0x0a, 0x25, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
      0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x70, 0x65, 0x72,
      0x66, 0x65, 0x74, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
      0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66,
@@ -374,7 +374,7 @@
      0x72, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c,
      0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28,
      0x0c, 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x79, 0x74, 0x65,
-     0x73, 0x22, 0xb2, 0x1a, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43,
+     0x73, 0x22, 0xd1, 0x1a, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43,
      0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x43, 0x0a, 0x07, 0x62, 0x75, 0x66,
      0x66, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29,
      0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
@@ -506,547 +506,550 @@
      0x69, 0x67, 0x2e, 0x49, 0x6e, 0x63, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x52,
      0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
      0x14, 0x69, 0x6e, 0x63, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x70,
-     0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0xc7, 0x01,
-     0x0a, 0x0c, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66,
-     0x69, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6b,
-     0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, 0x69, 0x7a,
-     0x65, 0x4b, 0x62, 0x12, 0x55, 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x6c, 0x5f,
-     0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e,
-     0x32, 0x34, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1d, 0x0a,
+     0x0a, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18,
+     0x1a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x74, 0x72, 0x61, 0x63, 0x65,
+     0x55, 0x75, 0x69, 0x64, 0x1a, 0xc7, 0x01, 0x0a, 0x0c, 0x42, 0x75, 0x66,
+     0x66, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x17, 0x0a,
+     0x07, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6b, 0x62, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x0d, 0x52, 0x06, 0x73, 0x69, 0x7a, 0x65, 0x4b, 0x62, 0x12, 0x55,
+     0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x6c, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63,
+     0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x34, 0x2e, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+     0x67, 0x2e, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x2e, 0x46, 0x69, 0x6c, 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63,
+     0x79, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63,
+     0x79, 0x22, 0x3b, 0x0a, 0x0a, 0x46, 0x69, 0x6c, 0x6c, 0x50, 0x6f, 0x6c,
+     0x69, 0x63, 0x79, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45,
+     0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b,
+     0x52, 0x49, 0x4e, 0x47, 0x5f, 0x42, 0x55, 0x46, 0x46, 0x45, 0x52, 0x10,
+     0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x49, 0x53, 0x43, 0x41, 0x52, 0x44,
+     0x10, 0x02, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03,
+     0x10, 0x04, 0x1a, 0x79, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f,
+     0x75, 0x72, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63,
+     0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e,
+     0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, 0x14, 0x70, 0x72, 0x6f, 0x64, 0x75,
+     0x63, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x69, 0x6c,
+     0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x70,
+     0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x46,
+     0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0xb3, 0x01, 0x0a, 0x11, 0x42, 0x75,
+     0x69, 0x6c, 0x74, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75,
+     0x72, 0x63, 0x65, 0x12, 0x3c, 0x0a, 0x1a, 0x64, 0x69, 0x73, 0x61, 0x62,
+     0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x6e, 0x61,
+     0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x08, 0x52, 0x18, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
+     0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f,
+     0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x14, 0x64, 0x69, 0x73,
+     0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x63,
+     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52,
+     0x12, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x63,
+     0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x0a, 0x13, 0x64,
+     0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65,
+     0x6d, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
+     0x52, 0x11, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x79, 0x73,
+     0x74, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x77, 0x0a, 0x0e, 0x50,
+     0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+     0x67, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65,
+     0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+     0x52, 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x4e, 0x61,
+     0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x73, 0x68, 0x6d, 0x5f, 0x73, 0x69,
+     0x7a, 0x65, 0x5f, 0x6b, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52,
+     0x09, 0x73, 0x68, 0x6d, 0x53, 0x69, 0x7a, 0x65, 0x4b, 0x62, 0x12, 0x20,
+     0x0a, 0x0c, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f,
+     0x6b, 0x62, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x70, 0x61,
+     0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x4b, 0x62, 0x1a, 0xe4, 0x01, 0x0a,
+     0x0e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64,
+     0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x72, 0x69, 0x67, 0x67,
+     0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x5f,
+     0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x74, 0x72,
+     0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x41, 0x6c, 0x65, 0x72,
+     0x74, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x74, 0x72, 0x69, 0x67, 0x67,
+     0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+     0x5f, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13,
+     0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f,
+     0x6e, 0x66, 0x69, 0x67, 0x55, 0x69, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x74,
+     0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f,
+     0x6e, 0x66, 0x69, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+     0x03, 0x52, 0x12, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e,
+     0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x49, 0x64, 0x12, 0x3c, 0x0a,
+     0x1a, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f,
+     0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+     0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x74,
+     0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x75, 0x62,
+     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x1a,
+     0x4c, 0x0a, 0x12, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c,
+     0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x36, 0x0a,
+     0x18, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f,
+     0x70, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x79, 0x5f, 0x62, 0x79, 0x74, 0x65,
+     0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x6d, 0x61, 0x78,
+     0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x65, 0x72, 0x44, 0x61, 0x79,
+     0x42, 0x79, 0x74, 0x65, 0x73, 0x1a, 0xa0, 0x03, 0x0a, 0x0d, 0x54, 0x72,
+     0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
+     0x59, 0x0a, 0x0c, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x6d,
+     0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e,
+     0x66, 0x69, 0x67, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43,
+     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65,
+     0x72, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0b, 0x74, 0x72, 0x69, 0x67, 0x67,
+     0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x4e, 0x0a, 0x08, 0x74, 0x72,
+     0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
+     0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
      0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65,
-     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x42, 0x75, 0x66, 0x66, 0x65,
-     0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x46, 0x69, 0x6c, 0x6c,
-     0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x6c,
-     0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x3b, 0x0a, 0x0a, 0x46, 0x69,
-     0x6c, 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0f, 0x0a, 0x0b,
-     0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
-     0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x42, 0x55,
-     0x46, 0x46, 0x45, 0x52, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x49,
-     0x53, 0x43, 0x41, 0x52, 0x44, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x02, 0x10,
-     0x03, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x1a, 0x79, 0x0a, 0x0a, 0x44,
-     0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x39, 0x0a,
-     0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61,
-     0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, 0x14,
-     0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d,
-     0x65, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03,
-     0x28, 0x09, 0x52, 0x12, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72,
-     0x4e, 0x61, 0x6d, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0xb3,
-     0x01, 0x0a, 0x11, 0x42, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x44, 0x61,
-     0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x3c, 0x0a, 0x1a,
-     0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x6f, 0x63,
-     0x6b, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x69,
-     0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x64, 0x69,
-     0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6e,
-     0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x30,
-     0x0a, 0x14, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x72,
-     0x61, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02,
-     0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
-     0x65, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x12, 0x2e, 0x0a, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f,
-     0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18,
-     0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x64, 0x69, 0x73, 0x61, 0x62,
-     0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f,
-     0x1a, 0x77, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72,
-     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72,
-     0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
-     0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75,
-     0x63, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x73,
-     0x68, 0x6d, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6b, 0x62, 0x18, 0x02,
-     0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x68, 0x6d, 0x53, 0x69, 0x7a,
-     0x65, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x70, 0x61, 0x67, 0x65, 0x5f,
-     0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6b, 0x62, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x0d, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x4b,
-     0x62, 0x1a, 0xe4, 0x01, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x64,
-     0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x13,
-     0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x61,
-     0x6c, 0x65, 0x72, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
-     0x03, 0x52, 0x11, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e,
-     0x67, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15,
-     0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x63,
-     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20,
-     0x01, 0x28, 0x05, 0x52, 0x13, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72,
-     0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x55, 0x69, 0x64,
-     0x12, 0x30, 0x0a, 0x14, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69,
-     0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x69, 0x64,
-     0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x74, 0x72, 0x69, 0x67,
-     0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1a, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65,
-     0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
-     0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x18, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69,
-     0x6e, 0x67, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
-     0x6f, 0x6e, 0x49, 0x64, 0x1a, 0x4c, 0x0a, 0x12, 0x47, 0x75, 0x61, 0x72,
-     0x64, 0x72, 0x61, 0x69, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
-     0x65, 0x73, 0x12, 0x36, 0x0a, 0x18, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x70,
-     0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x79,
-     0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
-     0x52, 0x14, 0x6d, 0x61, 0x78, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50,
-     0x65, 0x72, 0x44, 0x61, 0x79, 0x42, 0x79, 0x74, 0x65, 0x73, 0x1a, 0xa0,
-     0x03, 0x0a, 0x0d, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x6f,
-     0x6e, 0x66, 0x69, 0x67, 0x12, 0x59, 0x0a, 0x0c, 0x74, 0x72, 0x69, 0x67,
-     0x67, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01,
-     0x28, 0x0e, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61,
-     0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, 0x72, 0x69,
-     0x67, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54,
-     0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0b,
-     0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x12,
-     0x4e, 0x0a, 0x08, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x18,
-     0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
-     0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-     0x67, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x08, 0x74,
-     0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x74,
-     0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f,
-     0x75, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52,
-     0x10, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65,
-     0x6f, 0x75, 0x74, 0x4d, 0x73, 0x1a, 0x71, 0x0a, 0x07, 0x54, 0x72, 0x69,
-     0x67, 0x67, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
-     0x12, 0x2e, 0x0a, 0x13, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72,
-     0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18,
-     0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x64, 0x75,
-     0x63, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x67, 0x65, 0x78,
-     0x12, 0x22, 0x0a, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x64, 0x65, 0x6c,
-     0x61, 0x79, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52,
-     0x0b, 0x73, 0x74, 0x6f, 0x70, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x73,
-     0x22, 0x43, 0x0a, 0x0b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x4d,
-     0x6f, 0x64, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45,
-     0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d,
-     0x53, 0x54, 0x41, 0x52, 0x54, 0x5f, 0x54, 0x52, 0x41, 0x43, 0x49, 0x4e,
-     0x47, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x4f, 0x50, 0x5f,
-     0x54, 0x52, 0x41, 0x43, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x1a, 0x40, 0x0a,
-     0x16, 0x49, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c,
-     0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
-     0x26, 0x0a, 0x0f, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x5f, 0x70, 0x65, 0x72,
-     0x69, 0x6f, 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
-     0x52, 0x0d, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x50, 0x65, 0x72, 0x69, 0x6f,
-     0x64, 0x4d, 0x73, 0x1a, 0xbc, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x63, 0x69,
-     0x64, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f,
-     0x6e, 0x66, 0x69, 0x67, 0x12, 0x2f, 0x0a, 0x13, 0x64, 0x65, 0x73, 0x74,
-     0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x63, 0x6b,
-     0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x64,
-     0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61,
-     0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x64, 0x65, 0x73,
-     0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6c, 0x61,
-     0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x64, 0x65,
-     0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x61,
-     0x73, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x76, 0x61, 0x63,
-     0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x05, 0x52, 0x0c, 0x70, 0x72, 0x69, 0x76, 0x61, 0x63, 0x79, 0x4c, 0x65,
-     0x76, 0x65, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x5f,
-     0x64, 0x72, 0x6f, 0x70, 0x62, 0x6f, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28,
-     0x08, 0x52, 0x0b, 0x73, 0x6b, 0x69, 0x70, 0x44, 0x72, 0x6f, 0x70, 0x62,
-     0x6f, 0x78, 0x22, 0x55, 0x0a, 0x15, 0x4c, 0x6f, 0x63, 0x6b, 0x64, 0x6f,
-     0x77, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74,
-     0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x4f, 0x43, 0x4b, 0x44,
-     0x4f, 0x57, 0x4e, 0x5f, 0x55, 0x4e, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45,
-     0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x4f, 0x43, 0x4b, 0x44,
-     0x4f, 0x57, 0x4e, 0x5f, 0x43, 0x4c, 0x45, 0x41, 0x52, 0x10, 0x01, 0x12,
-     0x10, 0x0a, 0x0c, 0x4c, 0x4f, 0x43, 0x4b, 0x44, 0x4f, 0x57, 0x4e, 0x5f,
-     0x53, 0x45, 0x54, 0x10, 0x02, 0x22, 0x51, 0x0a, 0x0f, 0x43, 0x6f, 0x6d,
-     0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65,
-     0x12, 0x20, 0x0a, 0x1c, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53,
-     0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53,
-     0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c,
-     0x0a, 0x18, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f,
-     0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x46, 0x4c, 0x41,
-     0x54, 0x45, 0x10, 0x01, 0x4a, 0x04, 0x08, 0x0f, 0x10, 0x10, 0x22, 0xed,
-     0x04, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x64,
-     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x61,
-     0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72,
-     0x76, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20,
-     0x01, 0x28, 0x04, 0x52, 0x15, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e,
-     0x67, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x42, 0x79, 0x74,
-     0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
-     0x73, 0x5f, 0x63, 0x6d, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02, 0x20,
-     0x03, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-     0x43, 0x6d, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x70,
-     0x69, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x52, 0x03, 0x70, 0x69,
-     0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x05, 0x20, 0x01,
-     0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x73,
-     0x6b, 0x69, 0x70, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x5f, 0x70,
-     0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52,
-     0x10, 0x73, 0x6b, 0x69, 0x70, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x50,
-     0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x6b, 0x0a, 0x16, 0x63, 0x6f, 0x6e,
-     0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x5f, 0x64, 0x75, 0x6d, 0x70,
-     0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x35, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70,
-     0x70, 0x72, 0x6f, 0x66, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
-     0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75,
-     0x6d, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x14, 0x63, 0x6f,
-     0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70,
-     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x68,
-     0x6d, 0x65, 0x6d, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74,
-     0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x73, 0x68,
-     0x6d, 0x65, 0x6d, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73,
-     0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6c,
-     0x69, 0x65, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b,
-     0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12,
-     0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75,
-     0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6e, 0x6f, 0x53,
-     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f,
-     0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x0b, 0x20, 0x01,
-     0x28, 0x08, 0x52, 0x09, 0x6e, 0x6f, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e,
-     0x67, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x6c, 0x65, 0x5f, 0x61, 0x6c,
-     0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20,
-     0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x64, 0x6c, 0x65, 0x41, 0x6c, 0x6c,
-     0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0b,
-     0x64, 0x75, 0x6d, 0x70, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x61, 0x78, 0x18,
-     0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x64, 0x75, 0x6d, 0x70, 0x41,
-     0x74, 0x4d, 0x61, 0x78, 0x1a, 0x64, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x74,
-     0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70, 0x43, 0x6f,
-     0x6e, 0x66, 0x69, 0x67, 0x12, 0x22, 0x0a, 0x0d, 0x64, 0x75, 0x6d, 0x70,
-     0x5f, 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20,
-     0x01, 0x28, 0x0d, 0x52, 0x0b, 0x64, 0x75, 0x6d, 0x70, 0x50, 0x68, 0x61,
-     0x73, 0x65, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x64, 0x75, 0x6d, 0x70,
-     0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x73,
-     0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x64, 0x75, 0x6d, 0x70,
-     0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x73, 0x22, 0x5f,
-     0x0a, 0x10, 0x47, 0x70, 0x75, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
-     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6f,
-     0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64,
-     0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x63,
-     0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64,
-     0x4e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65,
-     0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0d, 0x52,
-     0x0a, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22,
-     0x44, 0x0a, 0x12, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x4c,
-     0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x0a,
-     0x13, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d,
-     0x65, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03,
-     0x28, 0x09, 0x52, 0x11, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e,
-     0x61, 0x6d, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2a, 0x8e, 0x01,
-     0x0a, 0x0c, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6f, 0x67,
-     0x49, 0x64, 0x12, 0x0f, 0x0a, 0x0b, 0x4c, 0x49, 0x44, 0x5f, 0x44, 0x45,
-     0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4c,
-     0x49, 0x44, 0x5f, 0x52, 0x41, 0x44, 0x49, 0x4f, 0x10, 0x01, 0x12, 0x0e,
-     0x0a, 0x0a, 0x4c, 0x49, 0x44, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x53,
-     0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x49, 0x44, 0x5f, 0x53, 0x59,
-     0x53, 0x54, 0x45, 0x4d, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x49,
-     0x44, 0x5f, 0x43, 0x52, 0x41, 0x53, 0x48, 0x10, 0x04, 0x12, 0x0d, 0x0a,
-     0x09, 0x4c, 0x49, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x53, 0x10, 0x05,
-     0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x49, 0x44, 0x5f, 0x53, 0x45, 0x43, 0x55,
-     0x52, 0x49, 0x54, 0x59, 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x49,
-     0x44, 0x5f, 0x4b, 0x45, 0x52, 0x4e, 0x45, 0x4c, 0x10, 0x07, 0x2a, 0x9b,
-     0x01, 0x0a, 0x12, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6f,
-     0x67, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x14, 0x0a,
-     0x10, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
-     0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x50,
-     0x52, 0x49, 0x4f, 0x5f, 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x10, 0x01,
-     0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x56, 0x45, 0x52,
-     0x42, 0x4f, 0x53, 0x45, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52,
-     0x49, 0x4f, 0x5f, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x03, 0x12, 0x0d,
-     0x0a, 0x09, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10,
-     0x04, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x57, 0x41,
-     0x52, 0x4e, 0x10, 0x05, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x49, 0x4f,
-     0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a,
-     0x50, 0x52, 0x49, 0x4f, 0x5f, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x07,
-     0x2a, 0xbf, 0x06, 0x0a, 0x0f, 0x4d, 0x65, 0x6d, 0x69, 0x6e, 0x66, 0x6f,
-     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x17, 0x0a, 0x13,
-     0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x55, 0x4e, 0x53, 0x50,
-     0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a,
-     0x11, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x45, 0x4d,
-     0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10,
-     0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x5f,
-     0x46, 0x52, 0x45, 0x45, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45,
-     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x41, 0x56,
-     0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x03, 0x12, 0x13, 0x0a,
-     0x0f, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x42, 0x55, 0x46,
-     0x46, 0x45, 0x52, 0x53, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45,
-     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x44,
-     0x10, 0x05, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46,
-     0x4f, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45,
-     0x44, 0x10, 0x06, 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
-     0x46, 0x4f, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x07, 0x12,
-     0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49,
-     0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x08, 0x12, 0x17, 0x0a,
-     0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x43, 0x54,
-     0x49, 0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x09, 0x12, 0x19,
-     0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49, 0x4e,
-     0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10,
-     0x0a, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
-     0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45,
-     0x10, 0x0b, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46,
-     0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46,
-     0x49, 0x4c, 0x45, 0x10, 0x0c, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d,
-     0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54,
-     0x41, 0x42, 0x4c, 0x45, 0x10, 0x0d, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x45,
-     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x45,
-     0x44, 0x10, 0x0e, 0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
-     0x46, 0x4f, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x5f, 0x54, 0x4f, 0x54, 0x41,
-     0x4c, 0x10, 0x0f, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
-     0x46, 0x4f, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x5f, 0x46, 0x52, 0x45, 0x45,
-     0x10, 0x10, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46,
-     0x4f, 0x5f, 0x44, 0x49, 0x52, 0x54, 0x59, 0x10, 0x11, 0x12, 0x15, 0x0a,
-     0x11, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x57, 0x52, 0x49,
-     0x54, 0x45, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x12, 0x12, 0x16, 0x0a, 0x12,
-     0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x4e, 0x4f, 0x4e,
-     0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x13, 0x12, 0x12, 0x0a, 0x0e,
-     0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x41, 0x50, 0x50,
-     0x45, 0x44, 0x10, 0x14, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x45, 0x4d, 0x49,
-     0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x48, 0x4d, 0x45, 0x4d, 0x10, 0x15, 0x12,
-     0x10, 0x0a, 0x0c, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53,
-     0x4c, 0x41, 0x42, 0x10, 0x16, 0x12, 0x1c, 0x0a, 0x18, 0x4d, 0x45, 0x4d,
-     0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x5f, 0x52, 0x45,
-     0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x17, 0x12,
-     0x1e, 0x0a, 0x1a, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53,
-     0x4c, 0x41, 0x42, 0x5f, 0x55, 0x4e, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49,
-     0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x18, 0x12, 0x18, 0x0a, 0x14, 0x4d,
-     0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4b, 0x45, 0x52, 0x4e, 0x45,
-     0x4c, 0x5f, 0x53, 0x54, 0x41, 0x43, 0x4b, 0x10, 0x19, 0x12, 0x17, 0x0a,
-     0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x50, 0x41, 0x47,
-     0x45, 0x5f, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x53, 0x10, 0x1a, 0x12, 0x18,
-     0x0a, 0x14, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4f,
-     0x4d, 0x4d, 0x49, 0x54, 0x5f, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x10, 0x1b,
+     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67,
+     0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, 0x72, 0x69,
+     0x67, 0x67, 0x65, 0x72, 0x52, 0x08, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65,
+     0x72, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65,
+     0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x6d, 0x73,
+     0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x74, 0x72, 0x69, 0x67,
+     0x67, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73,
+     0x1a, 0x71, 0x0a, 0x07, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12,
+     0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x70,
+     0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+     0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+     0x52, 0x11, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x4e, 0x61,
+     0x6d, 0x65, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x22, 0x0a, 0x0d, 0x73,
+     0x74, 0x6f, 0x70, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x73,
+     0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x73, 0x74, 0x6f, 0x70,
+     0x44, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x73, 0x22, 0x43, 0x0a, 0x0b, 0x54,
+     0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0f,
+     0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
+     0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x54, 0x41, 0x52, 0x54,
+     0x5f, 0x54, 0x52, 0x41, 0x43, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x10,
+     0x0a, 0x0c, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x54, 0x52, 0x41, 0x43, 0x49,
+     0x4e, 0x47, 0x10, 0x02, 0x1a, 0x40, 0x0a, 0x16, 0x49, 0x6e, 0x63, 0x72,
+     0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65,
+     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x26, 0x0a, 0x0f, 0x63, 0x6c,
+     0x65, 0x61, 0x72, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d,
+     0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x63, 0x6c, 0x65,
+     0x61, 0x72, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73, 0x1a, 0xbc,
+     0x01, 0x0a, 0x14, 0x49, 0x6e, 0x63, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x52,
+     0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
+     0x2f, 0x0a, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69,
+     0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01,
+     0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e,
+     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
+     0x12, 0x2b, 0x0a, 0x11, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
+     0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x02, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61,
+     0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x23, 0x0a,
+     0x0d, 0x70, 0x72, 0x69, 0x76, 0x61, 0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76,
+     0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x70, 0x72,
+     0x69, 0x76, 0x61, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x21,
+     0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x62,
+     0x6f, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x73, 0x6b,
+     0x69, 0x70, 0x44, 0x72, 0x6f, 0x70, 0x62, 0x6f, 0x78, 0x22, 0x55, 0x0a,
+     0x15, 0x4c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x4d, 0x6f, 0x64,
+     0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16,
+     0x0a, 0x12, 0x4c, 0x4f, 0x43, 0x4b, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x55,
+     0x4e, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12,
+     0x0a, 0x0e, 0x4c, 0x4f, 0x43, 0x4b, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x43,
+     0x4c, 0x45, 0x41, 0x52, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x4f,
+     0x43, 0x4b, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x53, 0x45, 0x54, 0x10, 0x02,
+     0x22, 0x51, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73,
+     0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x43,
+     0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x54,
+     0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
+     0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x4f, 0x4d,
+     0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50,
+     0x45, 0x5f, 0x44, 0x45, 0x46, 0x4c, 0x41, 0x54, 0x45, 0x10, 0x01, 0x4a,
+     0x04, 0x08, 0x0f, 0x10, 0x10, 0x22, 0xed, 0x04, 0x0a, 0x0f, 0x48, 0x65,
+     0x61, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+     0x67, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e,
+     0x67, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x62,
+     0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15,
+     0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x74, 0x65,
+     0x72, 0x76, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x27, 0x0a,
+     0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6d, 0x64,
+     0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6d, 0x64, 0x6c, 0x69,
+     0x6e, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x04, 0x20,
+     0x03, 0x28, 0x04, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03,
+     0x61, 0x6c, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61,
+     0x6c, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x73,
+     0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
+     0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73, 0x6b, 0x69, 0x70,
+     0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78,
+     0x12, 0x6b, 0x0a, 0x16, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f,
+     0x75, 0x73, 0x5f, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x64,
+     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x69,
+     0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70, 0x43, 0x6f, 0x6e,
+     0x66, 0x69, 0x67, 0x52, 0x14, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75,
+     0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+     0x67, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x68, 0x6d, 0x65, 0x6d, 0x5f, 0x73,
+     0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20,
+     0x01, 0x28, 0x04, 0x52, 0x0e, 0x73, 0x68, 0x6d, 0x65, 0x6d, 0x53, 0x69,
+     0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x62,
+     0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18,
+     0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+     0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f,
+     0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x18, 0x0a, 0x20, 0x01,
+     0x28, 0x08, 0x52, 0x09, 0x6e, 0x6f, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75,
+     0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x5f, 0x72, 0x75, 0x6e, 0x6e,
+     0x69, 0x6e, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6e,
+     0x6f, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x0a, 0x10,
+     0x69, 0x64, 0x6c, 0x65, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74,
+     0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f,
+     0x69, 0x64, 0x6c, 0x65, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
+     0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x64, 0x75, 0x6d, 0x70, 0x5f,
+     0x61, 0x74, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08,
+     0x52, 0x09, 0x64, 0x75, 0x6d, 0x70, 0x41, 0x74, 0x4d, 0x61, 0x78, 0x1a,
+     0x64, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75,
+     0x73, 0x44, 0x75, 0x6d, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
+     0x22, 0x0a, 0x0d, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x70, 0x68, 0x61, 0x73,
+     0x65, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b,
+     0x64, 0x75, 0x6d, 0x70, 0x50, 0x68, 0x61, 0x73, 0x65, 0x4d, 0x73, 0x12,
+     0x28, 0x0a, 0x10, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x69, 0x6e, 0x74, 0x65,
+     0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28,
+     0x0d, 0x52, 0x0e, 0x64, 0x75, 0x6d, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72,
+     0x76, 0x61, 0x6c, 0x4d, 0x73, 0x22, 0x5f, 0x0a, 0x10, 0x47, 0x70, 0x75,
+     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+     0x67, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
+     0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6e, 0x73, 0x18, 0x01,
+     0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65,
+     0x72, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4e, 0x73, 0x12, 0x1f, 0x0a,
+     0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73,
+     0x18, 0x02, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0a, 0x63, 0x6f, 0x75, 0x6e,
+     0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x44, 0x0a, 0x12, 0x50, 0x61,
+     0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f,
+     0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x0a, 0x13, 0x70, 0x61, 0x63, 0x6b,
+     0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x69, 0x6c,
+     0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x70,
+     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x46, 0x69,
+     0x6c, 0x74, 0x65, 0x72, 0x2a, 0x8e, 0x01, 0x0a, 0x0c, 0x41, 0x6e, 0x64,
+     0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6f, 0x67, 0x49, 0x64, 0x12, 0x0f, 0x0a,
+     0x0b, 0x4c, 0x49, 0x44, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54,
+     0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x49, 0x44, 0x5f, 0x52, 0x41,
+     0x44, 0x49, 0x4f, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x49, 0x44,
+     0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x53, 0x10, 0x02, 0x12, 0x0e, 0x0a,
+     0x0a, 0x4c, 0x49, 0x44, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x10,
+     0x03, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x49, 0x44, 0x5f, 0x43, 0x52, 0x41,
+     0x53, 0x48, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x49, 0x44, 0x5f,
+     0x53, 0x54, 0x41, 0x54, 0x53, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x4c,
+     0x49, 0x44, 0x5f, 0x53, 0x45, 0x43, 0x55, 0x52, 0x49, 0x54, 0x59, 0x10,
+     0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x49, 0x44, 0x5f, 0x4b, 0x45, 0x52,
+     0x4e, 0x45, 0x4c, 0x10, 0x07, 0x2a, 0x9b, 0x01, 0x0a, 0x12, 0x41, 0x6e,
+     0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6f, 0x67, 0x50, 0x72, 0x69, 0x6f,
+     0x72, 0x69, 0x74, 0x79, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x52, 0x49, 0x4f,
+     0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
+     0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x55,
+     0x4e, 0x55, 0x53, 0x45, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x50,
+     0x52, 0x49, 0x4f, 0x5f, 0x56, 0x45, 0x52, 0x42, 0x4f, 0x53, 0x45, 0x10,
+     0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x44, 0x45,
+     0x42, 0x55, 0x47, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x52, 0x49,
+     0x4f, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09,
+     0x50, 0x52, 0x49, 0x4f, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x05, 0x12,
+     0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x45, 0x52, 0x52, 0x4f,
+     0x52, 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x49, 0x4f, 0x5f,
+     0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x07, 0x2a, 0xbf, 0x06, 0x0a, 0x0f,
+     0x4d, 0x65, 0x6d, 0x69, 0x6e, 0x66, 0x6f, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+     0x65, 0x72, 0x73, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+     0x46, 0x4f, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
+     0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x4d, 0x49,
+     0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x54, 0x4f, 0x54, 0x41,
+     0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+     0x46, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x10,
+     0x02, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+     0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42,
+     0x4c, 0x45, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x45, 0x4d, 0x49,
+     0x4e, 0x46, 0x4f, 0x5f, 0x42, 0x55, 0x46, 0x46, 0x45, 0x52, 0x53, 0x10,
+     0x04, 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+     0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x44, 0x10, 0x05, 0x12, 0x17, 0x0a,
+     0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x57, 0x41,
+     0x50, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x44, 0x10, 0x06, 0x12, 0x12,
+     0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x43,
+     0x54, 0x49, 0x56, 0x45, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45,
+     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49,
+     0x56, 0x45, 0x10, 0x08, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49,
+     0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41,
+     0x4e, 0x4f, 0x4e, 0x10, 0x09, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d,
+     0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56,
+     0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x0a, 0x12, 0x17, 0x0a, 0x13,
+     0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x43, 0x54, 0x49,
+     0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x0b, 0x12, 0x19, 0x0a,
+     0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49, 0x4e, 0x41,
+     0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x0c,
      0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
-     0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x45, 0x44, 0x5f, 0x41, 0x53, 0x10,
-     0x1c, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
-     0x5f, 0x56, 0x4d, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x54, 0x4f, 0x54,
-     0x41, 0x4c, 0x10, 0x1d, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x4d, 0x49,
-     0x4e, 0x46, 0x4f, 0x5f, 0x56, 0x4d, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f,
-     0x55, 0x53, 0x45, 0x44, 0x10, 0x1e, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45,
-     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x56, 0x4d, 0x41, 0x4c, 0x4c, 0x4f,
-     0x43, 0x5f, 0x43, 0x48, 0x55, 0x4e, 0x4b, 0x10, 0x1f, 0x12, 0x15, 0x0a,
-     0x11, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4d, 0x41,
-     0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x20, 0x12, 0x14, 0x0a, 0x10,
-     0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4d, 0x41, 0x5f,
-     0x46, 0x52, 0x45, 0x45, 0x10, 0x21, 0x2a, 0xc6, 0x15, 0x0a, 0x0e, 0x56,
-     0x6d, 0x73, 0x74, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
-     0x73, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
-     0x00, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x4e, 0x52, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x41, 0x47, 0x45,
-     0x53, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41,
-     0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x42,
-     0x41, 0x54, 0x43, 0x48, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d,
-     0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x4e, 0x41, 0x43,
-     0x54, 0x49, 0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x03, 0x12,
-     0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
-     0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e,
-     0x10, 0x04, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45,
-     0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x43, 0x54,
-     0x49, 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x06, 0x12, 0x19,
-     0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
      0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10,
-     0x07, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x4e, 0x52, 0x5f, 0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x08, 0x12, 0x18,
-     0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
-     0x41, 0x4e, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x09,
-     0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e,
-     0x52, 0x5f, 0x4d, 0x41, 0x50, 0x50, 0x45, 0x44, 0x10, 0x0a, 0x12, 0x18,
-     0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
-     0x46, 0x49, 0x4c, 0x45, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x0b,
-     0x12, 0x13, 0x0a, 0x0f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e,
-     0x52, 0x5f, 0x44, 0x49, 0x52, 0x54, 0x59, 0x10, 0x0c, 0x12, 0x17, 0x0a,
-     0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x57,
-     0x52, 0x49, 0x54, 0x45, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x0d, 0x12, 0x1e,
-     0x0a, 0x1a, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
+     0x0d, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+     0x5f, 0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x0e, 0x12, 0x16,
+     0x0a, 0x12, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x57,
+     0x41, 0x50, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x0f, 0x12, 0x15,
+     0x0a, 0x11, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x57,
+     0x41, 0x50, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x10, 0x10, 0x12, 0x11, 0x0a,
+     0x0d, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x44, 0x49, 0x52,
+     0x54, 0x59, 0x10, 0x11, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x4d, 0x49,
+     0x4e, 0x46, 0x4f, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x42, 0x41, 0x43,
+     0x4b, 0x10, 0x12, 0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+     0x46, 0x4f, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x47, 0x45,
+     0x53, 0x10, 0x13, 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+     0x46, 0x4f, 0x5f, 0x4d, 0x41, 0x50, 0x50, 0x45, 0x44, 0x10, 0x14, 0x12,
+     0x11, 0x0a, 0x0d, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53,
+     0x48, 0x4d, 0x45, 0x4d, 0x10, 0x15, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x45,
+     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x10, 0x16,
+     0x12, 0x1c, 0x0a, 0x18, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
      0x53, 0x4c, 0x41, 0x42, 0x5f, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d,
-     0x41, 0x42, 0x4c, 0x45, 0x10, 0x0e, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d,
-     0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x4c, 0x41, 0x42,
-     0x5f, 0x55, 0x4e, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42,
-     0x4c, 0x45, 0x10, 0x0f, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x5f, 0x54,
-     0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x10,
-     0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e,
-     0x52, 0x5f, 0x4b, 0x45, 0x52, 0x4e, 0x45, 0x4c, 0x5f, 0x53, 0x54, 0x41,
-     0x43, 0x4b, 0x10, 0x11, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x48, 0x45,
-     0x41, 0x44, 0x10, 0x12, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x54, 0x41, 0x42,
-     0x4c, 0x45, 0x10, 0x13, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x42, 0x4f, 0x55, 0x4e, 0x43, 0x45,
-     0x10, 0x14, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x4e, 0x52, 0x5f, 0x56, 0x4d, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x57,
-     0x52, 0x49, 0x54, 0x45, 0x10, 0x15, 0x12, 0x26, 0x0a, 0x22, 0x56, 0x4d,
-     0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x56, 0x4d, 0x53, 0x43,
-     0x41, 0x4e, 0x5f, 0x49, 0x4d, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x54, 0x45,
-     0x5f, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x10, 0x16, 0x12, 0x1c,
-     0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
-     0x57, 0x52, 0x49, 0x54, 0x45, 0x42, 0x41, 0x43, 0x4b, 0x5f, 0x54, 0x45,
-     0x4d, 0x50, 0x10, 0x17, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x53, 0x4f, 0x4c, 0x41, 0x54,
-     0x45, 0x44, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x18, 0x12, 0x1b, 0x0a,
+     0x41, 0x42, 0x4c, 0x45, 0x10, 0x17, 0x12, 0x1e, 0x0a, 0x1a, 0x4d, 0x45,
+     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x5f, 0x55,
+     0x4e, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45,
+     0x10, 0x18, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46,
+     0x4f, 0x5f, 0x4b, 0x45, 0x52, 0x4e, 0x45, 0x4c, 0x5f, 0x53, 0x54, 0x41,
+     0x43, 0x4b, 0x10, 0x19, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49,
+     0x4e, 0x46, 0x4f, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x41, 0x42,
+     0x4c, 0x45, 0x53, 0x10, 0x1a, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x4d,
+     0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x5f,
+     0x4c, 0x49, 0x4d, 0x49, 0x54, 0x10, 0x1b, 0x12, 0x17, 0x0a, 0x13, 0x4d,
+     0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49,
+     0x54, 0x45, 0x44, 0x5f, 0x41, 0x53, 0x10, 0x1c, 0x12, 0x19, 0x0a, 0x15,
+     0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x56, 0x4d, 0x41, 0x4c,
+     0x4c, 0x4f, 0x43, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x1d, 0x12,
+     0x18, 0x0a, 0x14, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x56,
+     0x4d, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x55, 0x53, 0x45, 0x44, 0x10,
+     0x1e, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+     0x5f, 0x56, 0x4d, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x43, 0x48, 0x55,
+     0x4e, 0x4b, 0x10, 0x1f, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x4d, 0x49,
+     0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4d, 0x41, 0x5f, 0x54, 0x4f, 0x54, 0x41,
+     0x4c, 0x10, 0x20, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+     0x46, 0x4f, 0x5f, 0x43, 0x4d, 0x41, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x10,
+     0x21, 0x2a, 0xc6, 0x15, 0x0a, 0x0e, 0x56, 0x6d, 0x73, 0x74, 0x61, 0x74,
+     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x16, 0x0a, 0x12,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
+     0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x52,
+     0x45, 0x45, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x01, 0x12, 0x19,
+     0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
+     0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x42, 0x41, 0x54, 0x43, 0x48, 0x10,
+     0x02, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x4e, 0x52, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f,
+     0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d,
+     0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49,
+     0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x04, 0x12, 0x1b, 0x0a,
      0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49,
-     0x53, 0x4f, 0x4c, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45,
-     0x10, 0x19, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x48, 0x4d, 0x45, 0x4d, 0x10, 0x1a, 0x12,
-     0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
-     0x5f, 0x44, 0x49, 0x52, 0x54, 0x49, 0x45, 0x44, 0x10, 0x1b, 0x12, 0x15,
-     0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
-     0x57, 0x52, 0x49, 0x54, 0x54, 0x45, 0x4e, 0x10, 0x1c, 0x12, 0x1b, 0x0a,
-     0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x50,
-     0x41, 0x47, 0x45, 0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44,
-     0x10, 0x1d, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x49, 0x4e, 0x47, 0x53, 0x45, 0x54, 0x5f,
-     0x52, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x1e, 0x12, 0x1e, 0x0a,
-     0x1a, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x57, 0x4f, 0x52, 0x4b,
-     0x49, 0x4e, 0x47, 0x53, 0x45, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56,
-     0x41, 0x54, 0x45, 0x10, 0x1f, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53,
-     0x54, 0x41, 0x54, 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x49, 0x4e, 0x47, 0x53,
-     0x45, 0x54, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x52, 0x45, 0x43, 0x4c, 0x41,
-     0x49, 0x4d, 0x10, 0x20, 0x12, 0x28, 0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x5f, 0x54,
-     0x52, 0x41, 0x4e, 0x53, 0x50, 0x41, 0x52, 0x45, 0x4e, 0x54, 0x5f, 0x48,
-     0x55, 0x47, 0x45, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x21, 0x12, 0x16,
-     0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
-     0x46, 0x52, 0x45, 0x45, 0x5f, 0x43, 0x4d, 0x41, 0x10, 0x22, 0x12, 0x17,
-     0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
-     0x53, 0x57, 0x41, 0x50, 0x43, 0x41, 0x43, 0x48, 0x45, 0x10, 0x23, 0x12,
-     0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
-     0x5f, 0x44, 0x49, 0x52, 0x54, 0x59, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x53,
-     0x48, 0x4f, 0x4c, 0x44, 0x10, 0x24, 0x12, 0x28, 0x0a, 0x24, 0x56, 0x4d,
+     0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45,
+     0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46,
+     0x49, 0x4c, 0x45, 0x10, 0x06, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49,
+     0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x07, 0x12, 0x13, 0x0a, 0x0f,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4d, 0x4c,
+     0x4f, 0x43, 0x4b, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x5f,
+     0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x09, 0x12, 0x14, 0x0a, 0x10, 0x56,
+     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4d, 0x41, 0x50,
+     0x50, 0x45, 0x44, 0x10, 0x0a, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x5f,
+     0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x0b, 0x12, 0x13, 0x0a, 0x0f, 0x56,
+     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49, 0x52,
+     0x54, 0x59, 0x10, 0x0c, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x42,
+     0x41, 0x43, 0x4b, 0x10, 0x0d, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x5f,
+     0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10,
+     0x0e, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x4e, 0x52, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x5f, 0x55, 0x4e, 0x52, 0x45,
+     0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x0f, 0x12,
+     0x1e, 0x0a, 0x1a, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
+     0x5f, 0x50, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f,
+     0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x10, 0x12, 0x1a, 0x0a, 0x16, 0x56,
+     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4b, 0x45, 0x52,
+     0x4e, 0x45, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x43, 0x4b, 0x10, 0x11, 0x12,
+     0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
+     0x5f, 0x4f, 0x56, 0x45, 0x52, 0x48, 0x45, 0x41, 0x44, 0x10, 0x12, 0x12,
+     0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
+     0x5f, 0x55, 0x4e, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x13, 0x12,
+     0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
+     0x5f, 0x42, 0x4f, 0x55, 0x4e, 0x43, 0x45, 0x10, 0x14, 0x12, 0x1a, 0x0a,
+     0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x56,
+     0x4d, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10,
+     0x15, 0x12, 0x26, 0x0a, 0x22, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x4e, 0x52, 0x5f, 0x56, 0x4d, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x49, 0x4d,
+     0x4d, 0x45, 0x44, 0x49, 0x41, 0x54, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x4c,
+     0x41, 0x49, 0x4d, 0x10, 0x16, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45,
+     0x42, 0x41, 0x43, 0x4b, 0x5f, 0x54, 0x45, 0x4d, 0x50, 0x10, 0x17, 0x12,
+     0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
+     0x5f, 0x49, 0x53, 0x4f, 0x4c, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x41, 0x4e,
+     0x4f, 0x4e, 0x10, 0x18, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x53, 0x4f, 0x4c, 0x41, 0x54,
+     0x45, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x19, 0x12, 0x13, 0x0a,
+     0x0f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53,
+     0x48, 0x4d, 0x45, 0x4d, 0x10, 0x1a, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d,
      0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49, 0x52, 0x54,
-     0x59, 0x5f, 0x42, 0x41, 0x43, 0x4b, 0x47, 0x52, 0x4f, 0x55, 0x4e, 0x44,
-     0x5f, 0x54, 0x48, 0x52, 0x45, 0x53, 0x48, 0x4f, 0x4c, 0x44, 0x10, 0x25,
-     0x12, 0x11, 0x0a, 0x0d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50,
-     0x47, 0x50, 0x47, 0x49, 0x4e, 0x10, 0x26, 0x12, 0x12, 0x0a, 0x0e, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x50, 0x47, 0x4f, 0x55,
-     0x54, 0x10, 0x27, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41,
-     0x54, 0x5f, 0x50, 0x47, 0x50, 0x47, 0x4f, 0x55, 0x54, 0x43, 0x4c, 0x45,
-     0x41, 0x4e, 0x10, 0x28, 0x12, 0x11, 0x0a, 0x0d, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x50, 0x53, 0x57, 0x50, 0x49, 0x4e, 0x10, 0x29, 0x12,
-     0x12, 0x0a, 0x0e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x53,
-     0x57, 0x50, 0x4f, 0x55, 0x54, 0x10, 0x2a, 0x12, 0x16, 0x0a, 0x12, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f,
-     0x43, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x2b, 0x12, 0x19, 0x0a, 0x15, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f,
-     0x43, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x2c, 0x12, 0x1a,
-     0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41,
-     0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45,
-     0x10, 0x2d, 0x12, 0x11, 0x0a, 0x0d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x50, 0x47, 0x46, 0x52, 0x45, 0x45, 0x10, 0x2e, 0x12, 0x15, 0x0a,
-     0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x43,
-     0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x2f, 0x12, 0x17, 0x0a, 0x13,
-     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x44, 0x45, 0x41,
-     0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x30, 0x12, 0x12, 0x0a,
-     0x0e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x46, 0x41,
-     0x55, 0x4c, 0x54, 0x10, 0x31, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53,
-     0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x4d, 0x41, 0x4a, 0x46, 0x41, 0x55,
-     0x4c, 0x54, 0x10, 0x32, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x50, 0x47, 0x52, 0x45, 0x46, 0x49, 0x4c, 0x4c, 0x5f,
-     0x44, 0x4d, 0x41, 0x10, 0x33, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53,
-     0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x52, 0x45, 0x46, 0x49, 0x4c, 0x4c,
-     0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x34, 0x12, 0x1b, 0x0a,
-     0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x52, 0x45,
-     0x46, 0x49, 0x4c, 0x4c, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45,
-     0x10, 0x35, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x4b, 0x53, 0x57,
-     0x41, 0x50, 0x44, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x36, 0x12, 0x20, 0x0a,
-     0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54,
-     0x45, 0x41, 0x4c, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4e,
-     0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x37, 0x12, 0x21, 0x0a, 0x1d, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41,
-     0x4c, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4d, 0x4f, 0x56,
-     0x41, 0x42, 0x4c, 0x45, 0x10, 0x38, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d,
-     0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c,
-     0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x44, 0x4d, 0x41, 0x10,
-     0x39, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x44, 0x49, 0x52, 0x45,
-     0x43, 0x54, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x3a, 0x12,
-     0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
-     0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54,
-     0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x3b, 0x12, 0x1c,
-     0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53,
-     0x43, 0x41, 0x4e, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x44,
-     0x4d, 0x41, 0x10, 0x3c, 0x12, 0x1f, 0x0a, 0x1b, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x4b, 0x53,
-     0x57, 0x41, 0x50, 0x44, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10,
-     0x3d, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50,
-     0x44, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x3e, 0x12,
-     0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
-     0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f,
-     0x44, 0x4d, 0x41, 0x10, 0x3f, 0x12, 0x1f, 0x0a, 0x1b, 0x56, 0x4d, 0x53,
-     0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44,
-     0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c,
-     0x10, 0x40, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45,
-     0x43, 0x54, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x41,
-     0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50,
-     0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54,
-     0x5f, 0x54, 0x48, 0x52, 0x4f, 0x54, 0x54, 0x4c, 0x45, 0x10, 0x42, 0x12,
+     0x49, 0x45, 0x44, 0x10, 0x1b, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x54,
+     0x45, 0x4e, 0x10, 0x1c, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x5f,
+     0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x1d, 0x12, 0x1d, 0x0a,
+     0x19, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x57, 0x4f, 0x52, 0x4b,
+     0x49, 0x4e, 0x47, 0x53, 0x45, 0x54, 0x5f, 0x52, 0x45, 0x46, 0x41, 0x55,
+     0x4c, 0x54, 0x10, 0x1e, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x49, 0x4e, 0x47, 0x53, 0x45,
+     0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x1f,
+     0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x57,
+     0x4f, 0x52, 0x4b, 0x49, 0x4e, 0x47, 0x53, 0x45, 0x54, 0x5f, 0x4e, 0x4f,
+     0x44, 0x45, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x10, 0x20, 0x12,
+     0x28, 0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
+     0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x50,
+     0x41, 0x52, 0x45, 0x4e, 0x54, 0x5f, 0x48, 0x55, 0x47, 0x45, 0x50, 0x41,
+     0x47, 0x45, 0x53, 0x10, 0x21, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x5f,
+     0x43, 0x4d, 0x41, 0x10, 0x22, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x43,
+     0x41, 0x43, 0x48, 0x45, 0x10, 0x23, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d,
+     0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49, 0x52, 0x54,
+     0x59, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x53, 0x48, 0x4f, 0x4c, 0x44, 0x10,
+     0x24, 0x12, 0x28, 0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x4e, 0x52, 0x5f, 0x44, 0x49, 0x52, 0x54, 0x59, 0x5f, 0x42, 0x41, 0x43,
+     0x4b, 0x47, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x54, 0x48, 0x52, 0x45,
+     0x53, 0x48, 0x4f, 0x4c, 0x44, 0x10, 0x25, 0x12, 0x11, 0x0a, 0x0d, 0x56,
+     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x50, 0x47, 0x49, 0x4e,
+     0x10, 0x26, 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x50, 0x47, 0x50, 0x47, 0x4f, 0x55, 0x54, 0x10, 0x27, 0x12, 0x17,
+     0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x50,
+     0x47, 0x4f, 0x55, 0x54, 0x43, 0x4c, 0x45, 0x41, 0x4e, 0x10, 0x28, 0x12,
+     0x11, 0x0a, 0x0d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x53,
+     0x57, 0x50, 0x49, 0x4e, 0x10, 0x29, 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4d,
+     0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x53, 0x57, 0x50, 0x4f, 0x55, 0x54,
+     0x10, 0x2a, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x44, 0x4d, 0x41,
+     0x10, 0x2b, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x4e, 0x4f, 0x52,
+     0x4d, 0x41, 0x4c, 0x10, 0x2c, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f,
+     0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x2d, 0x12, 0x11, 0x0a,
+     0x0d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x46, 0x52,
+     0x45, 0x45, 0x10, 0x2e, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54,
+     0x45, 0x10, 0x2f, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41,
+     0x54, 0x5f, 0x50, 0x47, 0x44, 0x45, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41,
+     0x54, 0x45, 0x10, 0x30, 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4d, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x50, 0x47, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x31,
+     0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50,
+     0x47, 0x4d, 0x41, 0x4a, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x32, 0x12,
      0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
-     0x49, 0x4e, 0x4f, 0x44, 0x45, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x10, 0x43,
-     0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x53,
-     0x4c, 0x41, 0x42, 0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44,
-     0x10, 0x44, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x49, 0x4e, 0x4f, 0x44,
-     0x45, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x10, 0x45, 0x12, 0x27, 0x0a, 0x23,
+     0x52, 0x45, 0x46, 0x49, 0x4c, 0x4c, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x33,
+     0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50,
+     0x47, 0x52, 0x45, 0x46, 0x49, 0x4c, 0x4c, 0x5f, 0x4e, 0x4f, 0x52, 0x4d,
+     0x41, 0x4c, 0x10, 0x34, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x50, 0x47, 0x52, 0x45, 0x46, 0x49, 0x4c, 0x4c, 0x5f,
+     0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x35, 0x12, 0x1d, 0x0a,
+     0x19, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54,
+     0x45, 0x41, 0x4c, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x44,
+     0x4d, 0x41, 0x10, 0x36, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x4b,
+     0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c,
+     0x10, 0x37, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x4b, 0x53, 0x57,
+     0x41, 0x50, 0x44, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10,
+     0x38, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x44, 0x49, 0x52, 0x45,
+     0x43, 0x54, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x39, 0x12, 0x20, 0x0a, 0x1c,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45,
+     0x41, 0x4c, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4e, 0x4f,
+     0x52, 0x4d, 0x41, 0x4c, 0x10, 0x3a, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d,
+     0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c,
+     0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4d, 0x4f, 0x56, 0x41,
+     0x42, 0x4c, 0x45, 0x10, 0x3b, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x4b,
+     0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x3c, 0x12,
+     0x1f, 0x0a, 0x1b, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
+     0x53, 0x43, 0x41, 0x4e, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f,
+     0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x3d, 0x12, 0x20, 0x0a, 0x1c,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41,
+     0x4e, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4d, 0x4f, 0x56,
+     0x41, 0x42, 0x4c, 0x45, 0x10, 0x3e, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d,
+     0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f,
+     0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x3f,
+     0x12, 0x1f, 0x0a, 0x1b, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50,
+     0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54,
+     0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x40, 0x12, 0x20, 0x0a,
+     0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43,
+     0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4d, 0x4f,
+     0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x41, 0x12, 0x21, 0x0a, 0x1d, 0x56,
+     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e,
+     0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x54, 0x48, 0x52, 0x4f,
+     0x54, 0x54, 0x4c, 0x45, 0x10, 0x42, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d,
+     0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x49, 0x4e, 0x4f, 0x44, 0x45,
+     0x53, 0x54, 0x45, 0x41, 0x4c, 0x10, 0x43, 0x12, 0x18, 0x0a, 0x14, 0x56,
+     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x53, 0x5f,
+     0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x44, 0x12, 0x1c, 0x0a,
+     0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53, 0x57, 0x41,
+     0x50, 0x44, 0x5f, 0x49, 0x4e, 0x4f, 0x44, 0x45, 0x53, 0x54, 0x45, 0x41,
+     0x4c, 0x10, 0x45, 0x12, 0x27, 0x0a, 0x23, 0x56, 0x4d, 0x53, 0x54, 0x41,
+     0x54, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4c, 0x4f, 0x57,
+     0x5f, 0x57, 0x4d, 0x41, 0x52, 0x4b, 0x5f, 0x48, 0x49, 0x54, 0x5f, 0x51,
+     0x55, 0x49, 0x43, 0x4b, 0x4c, 0x59, 0x10, 0x46, 0x12, 0x28, 0x0a, 0x24,
      0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50,
-     0x44, 0x5f, 0x4c, 0x4f, 0x57, 0x5f, 0x57, 0x4d, 0x41, 0x52, 0x4b, 0x5f,
-     0x48, 0x49, 0x54, 0x5f, 0x51, 0x55, 0x49, 0x43, 0x4b, 0x4c, 0x59, 0x10,
-     0x46, 0x12, 0x28, 0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x48, 0x49, 0x47, 0x48, 0x5f,
-     0x57, 0x4d, 0x41, 0x52, 0x4b, 0x5f, 0x48, 0x49, 0x54, 0x5f, 0x51, 0x55,
-     0x49, 0x43, 0x4b, 0x4c, 0x59, 0x10, 0x47, 0x12, 0x15, 0x0a, 0x11, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x4f, 0x55,
-     0x54, 0x52, 0x55, 0x4e, 0x10, 0x48, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d,
-     0x53, 0x54, 0x41, 0x54, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x53, 0x54,
-     0x41, 0x4c, 0x4c, 0x10, 0x49, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53,
-     0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x52, 0x4f, 0x54, 0x41, 0x54, 0x45,
-     0x44, 0x10, 0x4a, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41,
-     0x54, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x43,
-     0x41, 0x43, 0x48, 0x45, 0x10, 0x4b, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d,
-     0x53, 0x54, 0x41, 0x54, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x5f, 0x53, 0x4c,
-     0x41, 0x42, 0x10, 0x4c, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x50, 0x47, 0x4d, 0x49, 0x47, 0x52, 0x41, 0x54, 0x45,
-     0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x4d, 0x12, 0x19,
-     0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x4d,
-     0x49, 0x47, 0x52, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x10,
-     0x4e, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x4d, 0x49, 0x47, 0x52,
-     0x41, 0x54, 0x45, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10,
-     0x4f, 0x12, 0x1f, 0x0a, 0x1b, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x46, 0x52, 0x45, 0x45,
-     0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x50, 0x12, 0x1b,
-     0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d,
-     0x50, 0x41, 0x43, 0x54, 0x5f, 0x49, 0x53, 0x4f, 0x4c, 0x41, 0x54, 0x45,
-     0x44, 0x10, 0x51, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41,
-     0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x53, 0x54,
-     0x41, 0x4c, 0x4c, 0x10, 0x52, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53,
+     0x44, 0x5f, 0x48, 0x49, 0x47, 0x48, 0x5f, 0x57, 0x4d, 0x41, 0x52, 0x4b,
+     0x5f, 0x48, 0x49, 0x54, 0x5f, 0x51, 0x55, 0x49, 0x43, 0x4b, 0x4c, 0x59,
+     0x10, 0x47, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x50, 0x41, 0x47, 0x45, 0x4f, 0x55, 0x54, 0x52, 0x55, 0x4e, 0x10,
+     0x48, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x53, 0x54, 0x41, 0x4c, 0x4c, 0x10, 0x49,
+     0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50,
+     0x47, 0x52, 0x4f, 0x54, 0x41, 0x54, 0x45, 0x44, 0x10, 0x4a, 0x12, 0x19,
+     0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x44, 0x52, 0x4f,
+     0x50, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x43, 0x41, 0x43, 0x48, 0x45, 0x10,
+     0x4b, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x44, 0x52, 0x4f, 0x50, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x10, 0x4c, 0x12,
+     0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
+     0x4d, 0x49, 0x47, 0x52, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x55, 0x43, 0x43,
+     0x45, 0x53, 0x53, 0x10, 0x4d, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x4d, 0x49, 0x47, 0x52, 0x41, 0x54,
+     0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x4e, 0x12, 0x22, 0x0a, 0x1e,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41,
+     0x43, 0x54, 0x5f, 0x4d, 0x49, 0x47, 0x52, 0x41, 0x54, 0x45, 0x5f, 0x53,
+     0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x4f, 0x12, 0x1f, 0x0a, 0x1b,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41,
+     0x43, 0x54, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x5f, 0x53, 0x43, 0x41, 0x4e,
+     0x4e, 0x45, 0x44, 0x10, 0x50, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53,
      0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f,
-     0x46, 0x41, 0x49, 0x4c, 0x10, 0x53, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d,
-     0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54,
-     0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x54, 0x12, 0x1e,
-     0x0a, 0x1a, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d,
-     0x50, 0x41, 0x43, 0x54, 0x5f, 0x44, 0x41, 0x45, 0x4d, 0x4f, 0x4e, 0x5f,
-     0x57, 0x41, 0x4b, 0x45, 0x10, 0x55, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d,
-     0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54,
-     0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x43, 0x55, 0x4c,
-     0x4c, 0x45, 0x44, 0x10, 0x56, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53,
-     0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41,
-     0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e,
-     0x4e, 0x45, 0x44, 0x10, 0x57, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53,
-     0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41,
-     0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x52, 0x45, 0x53, 0x43,
-     0x55, 0x45, 0x44, 0x10, 0x58, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53,
-     0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41,
-     0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x4d, 0x4c, 0x4f, 0x43,
-     0x4b, 0x45, 0x44, 0x10, 0x59, 0x12, 0x24, 0x0a, 0x20, 0x56, 0x4d, 0x53,
-     0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41,
-     0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x4d, 0x55, 0x4e, 0x4c,
-     0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x5a, 0x12, 0x22, 0x0a, 0x1e, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43,
-     0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x43, 0x4c,
-     0x45, 0x41, 0x52, 0x45, 0x44, 0x10, 0x5b, 0x12, 0x23, 0x0a, 0x1f, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43,
-     0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x53, 0x54,
-     0x52, 0x41, 0x4e, 0x44, 0x45, 0x44, 0x10, 0x5c, 0x12, 0x15, 0x0a, 0x11,
-     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x5a, 0x53,
-     0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x5d, 0x12, 0x16, 0x0a, 0x12, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x4f, 0x4e,
-     0x5f, 0x48, 0x45, 0x41, 0x50, 0x10, 0x5e, 0x12, 0x16, 0x0a, 0x12, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x47, 0x50, 0x55,
-     0x5f, 0x48, 0x45, 0x41, 0x50, 0x10, 0x5f}};
+     0x49, 0x53, 0x4f, 0x4c, 0x41, 0x54, 0x45, 0x44, 0x10, 0x51, 0x12, 0x18,
+     0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d,
+     0x50, 0x41, 0x43, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x4c, 0x4c, 0x10, 0x52,
+     0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43,
+     0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x10,
+     0x53, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x53, 0x55, 0x43, 0x43,
+     0x45, 0x53, 0x53, 0x10, 0x54, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f,
+     0x44, 0x41, 0x45, 0x4d, 0x4f, 0x4e, 0x5f, 0x57, 0x41, 0x4b, 0x45, 0x10,
+     0x55, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f,
+     0x50, 0x47, 0x53, 0x5f, 0x43, 0x55, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x56,
+     0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55,
+     0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50,
+     0x47, 0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x57,
+     0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55,
+     0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50,
+     0x47, 0x53, 0x5f, 0x52, 0x45, 0x53, 0x43, 0x55, 0x45, 0x44, 0x10, 0x58,
+     0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55,
+     0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50,
+     0x47, 0x53, 0x5f, 0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x59,
+     0x12, 0x24, 0x0a, 0x20, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55,
+     0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50,
+     0x47, 0x53, 0x5f, 0x4d, 0x55, 0x4e, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44,
+     0x10, 0x5a, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45,
+     0x5f, 0x50, 0x47, 0x53, 0x5f, 0x43, 0x4c, 0x45, 0x41, 0x52, 0x45, 0x44,
+     0x10, 0x5b, 0x12, 0x23, 0x0a, 0x1f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45,
+     0x5f, 0x50, 0x47, 0x53, 0x5f, 0x53, 0x54, 0x52, 0x41, 0x4e, 0x44, 0x45,
+     0x44, 0x10, 0x5c, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41,
+     0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x5a, 0x53, 0x50, 0x41, 0x47, 0x45, 0x53,
+     0x10, 0x5d, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x4f, 0x4e, 0x5f, 0x48, 0x45, 0x41, 0x50,
+     0x10, 0x5e, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x4e, 0x52, 0x5f, 0x47, 0x50, 0x55, 0x5f, 0x48, 0x45, 0x41, 0x50,
+     0x10, 0x5f}};
 
 }  // namespace perfetto
 
diff --git a/src/profiling/memory/heapprofd_producer_unittest.cc b/src/profiling/memory/heapprofd_producer_unittest.cc
index 1ff9a21..0f67b0e 100644
--- a/src/profiling/memory/heapprofd_producer_unittest.cc
+++ b/src/profiling/memory/heapprofd_producer_unittest.cc
@@ -42,7 +42,8 @@
 
   MOCK_CONST_METHOD0(shared_memory, SharedMemory*());
   MOCK_CONST_METHOD0(shared_buffer_page_size_kb, size_t());
-  MOCK_METHOD1(CreateTraceWriter, std::unique_ptr<TraceWriter>(BufferID));
+  MOCK_METHOD2(CreateTraceWriter,
+               std::unique_ptr<TraceWriter>(BufferID, BufferExhaustedPolicy));
   MOCK_METHOD0(GetInProcessShmemArbiter, SharedMemoryArbiter*());
   MOCK_METHOD1(ActivateTriggers, void(const std::vector<std::string>&));
 
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index ef0d92f..e7b4a97 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -63,6 +63,8 @@
     "event_tracker.h",
     "filtered_row_index.cc",
     "filtered_row_index.h",
+    "forwarding_trace_parser.cc",
+    "forwarding_trace_parser.h",
     "ftrace_descriptors.cc",
     "ftrace_descriptors.h",
     "ftrace_utils.cc",
@@ -237,6 +239,7 @@
     "clock_tracker_unittest.cc",
     "event_tracker_unittest.cc",
     "filtered_row_index_unittest.cc",
+    "forwarding_trace_parser_unittest.cc",
     "ftrace_utils_unittest.cc",
     "fuchsia_trace_utils_unittest.cc",
     "heap_profile_tracker_unittest.cc",
@@ -254,7 +257,6 @@
     "syscall_tracker_unittest.cc",
     "systrace_parser_unittest.cc",
     "thread_table_unittest.cc",
-    "trace_processor_impl_unittest.cc",
     "trace_sorter_unittest.cc",
   ]
   deps = [
diff --git a/src/trace_processor/export_json.cc b/src/trace_processor/export_json.cc
index 2034561..93ef520 100644
--- a/src/trace_processor/export_json.cc
+++ b/src/trace_processor/export_json.cc
@@ -28,6 +28,8 @@
 
 namespace {
 
+using IndexMap = perfetto::trace_processor::TraceStorage::Stats::IndexMap;
+
 class TraceFormatWriter {
  public:
   TraceFormatWriter(FILE* output) : output_(output), first_event_(true) {
@@ -69,6 +71,12 @@
     first_event_ = false;
   }
 
+  void MergeMetadata(const Json::Value& value) {
+    for (const auto& member : value.getMemberNames()) {
+      metadata_[member] = value[member];
+    }
+  }
+
   void AppendTelemetryMetadataString(const char* key, const char* value) {
     metadata_["telemetry"][key].append(value);
   }
@@ -85,6 +93,17 @@
     metadata_["telemetry"][key] = value / 1000.0;
   }
 
+  void SetPerfettoStats(const char* key, int64_t value) {
+    metadata_["perfetto_trace_stats"][key] = Json::Int64(value);
+  }
+
+  void SetPerfettoBufferStats(const char* key, const IndexMap& indexed_values) {
+    for (const auto& value : indexed_values) {
+      metadata_["perfetto_trace_stats"]["buffer_stats"][value.first][key] =
+          Json::Int64(value.second);
+    }
+  }
+
  private:
   void WriteHeader() { fputs("{\"traceEvents\":[\n", output_); }
 
@@ -545,6 +564,24 @@
   return kResultOk;
 }
 
+ResultCode ExportChromeMetadata(const TraceStorage* storage,
+                                const ArgsBuilder& args_builder,
+                                TraceFormatWriter* writer) {
+  base::Optional<StringId> raw_chrome_metadata_event_id =
+      storage->string_pool().GetId("chrome_event.metadata");
+  if (!raw_chrome_metadata_event_id)
+    return kResultOk;
+
+  const auto& events = storage->raw_events();
+  for (uint32_t i = 0; i < events.raw_event_count(); ++i) {
+    if (events.name_ids()[i] != *raw_chrome_metadata_event_id)
+      continue;
+    Json::Value args = args_builder.GetArgs(events.arg_set_ids()[i]);
+    writer->MergeMetadata(args);
+  }
+  return kResultOk;
+}
+
 ResultCode ExportMetadata(const TraceStorage* storage,
                           TraceFormatWriter* writer) {
   const auto& trace_metadata = storage->metadata();
@@ -610,6 +647,78 @@
   return kResultOk;
 }
 
+ResultCode ExportStats(const TraceStorage* storage, TraceFormatWriter* writer) {
+  const auto& stats = storage->stats();
+
+  writer->SetPerfettoStats("producers_connected",
+                           stats[stats::traced_producers_connected].value);
+  writer->SetPerfettoStats("producers_seen",
+                           stats[stats::traced_producers_seen].value);
+  writer->SetPerfettoStats("data_sources_registered",
+                           stats[stats::traced_data_sources_registered].value);
+  writer->SetPerfettoStats("data_sources_seen",
+                           stats[stats::traced_data_sources_seen].value);
+  writer->SetPerfettoStats("tracing_sessions",
+                           stats[stats::traced_tracing_sessions].value);
+  writer->SetPerfettoStats("total_buffers",
+                           stats[stats::traced_total_buffers].value);
+  writer->SetPerfettoStats("chunks_discarded",
+                           stats[stats::traced_chunks_discarded].value);
+  writer->SetPerfettoStats("patches_discarded",
+                           stats[stats::traced_patches_discarded].value);
+
+  writer->SetPerfettoBufferStats(
+      "buffer_size", stats[stats::traced_buf_buffer_size].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "bytes_written", stats[stats::traced_buf_bytes_written].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "bytes_overwritten",
+      stats[stats::traced_buf_bytes_overwritten].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "bytes_read", stats[stats::traced_buf_bytes_read].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "padding_bytes_written",
+      stats[stats::traced_buf_padding_bytes_written].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "padding_bytes_cleared",
+      stats[stats::traced_buf_padding_bytes_cleared].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "chunks_written", stats[stats::traced_buf_chunks_written].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "chunks_rewritten",
+      stats[stats::traced_buf_chunks_rewritten].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "chunks_overwritten",
+      stats[stats::traced_buf_chunks_overwritten].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "chunks_discarded",
+      stats[stats::traced_buf_chunks_discarded].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "chunks_read", stats[stats::traced_buf_chunks_read].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "chunks_committed_out_of_order",
+      stats[stats::traced_buf_chunks_committed_out_of_order].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "write_wrap_count",
+      stats[stats::traced_buf_write_wrap_count].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "patches_succeeded",
+      stats[stats::traced_buf_patches_succeeded].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "patches_failed", stats[stats::traced_buf_patches_failed].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "readaheads_succeeded",
+      stats[stats::traced_buf_readaheads_succeeded].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "readaheads_failed",
+      stats[stats::traced_buf_readaheads_failed].indexed_values);
+  writer->SetPerfettoBufferStats(
+      "trace_writer_packet_loss",
+      stats[stats::traced_buf_trace_writer_packet_loss].indexed_values);
+
+  return kResultOk;
+}
+
 }  // anonymous namespace
 
 ResultCode ExportJson(const TraceStorage* storage, FILE* output) {
@@ -632,10 +741,18 @@
   if (code != kResultOk)
     return code;
 
+  code = ExportChromeMetadata(storage, args_builder, &writer);
+  if (code != kResultOk)
+    return code;
+
   code = ExportMetadata(storage, &writer);
   if (code != kResultOk)
     return code;
 
+  code = ExportStats(storage, &writer);
+  if (code != kResultOk)
+    return code;
+
   return kResultOk;
 }
 
diff --git a/src/trace_processor/export_json_unittest.cc b/src/trace_processor/export_json_unittest.cc
index 8e5a289..0b0fa86 100644
--- a/src/trace_processor/export_json_unittest.cc
+++ b/src/trace_processor/export_json_unittest.cc
@@ -268,6 +268,73 @@
   EXPECT_EQ(telemetry_metadata["hadFailures"][0].asBool(), kHadFailures);
 }
 
+TEST(ExportJsonTest, StorageWithStats) {
+  int64_t kProducers = 10;
+  int64_t kBufferSize0 = 1000;
+  int64_t kBufferSize1 = 2000;
+
+  TraceStorage storage;
+
+  storage.SetStats(stats::traced_producers_connected, kProducers);
+  storage.SetIndexedStats(stats::traced_buf_buffer_size, 0, kBufferSize0);
+  storage.SetIndexedStats(stats::traced_buf_buffer_size, 1, kBufferSize1);
+
+  base::TempFile temp_file = base::TempFile::Create();
+  FILE* output = fopen(temp_file.path().c_str(), "w+");
+  int code = ExportJson(&storage, output);
+  EXPECT_EQ(code, kResultOk);
+
+  Json::Reader reader;
+  Json::Value result;
+
+  EXPECT_TRUE(reader.parse(ReadFile(output), result));
+  EXPECT_TRUE(result.isMember("metadata"));
+  EXPECT_TRUE(result["metadata"].isMember("perfetto_trace_stats"));
+  Json::Value stats = result["metadata"]["perfetto_trace_stats"];
+
+  EXPECT_EQ(stats["producers_connected"].asInt(), kProducers);
+  EXPECT_EQ(stats["buffer_stats"].size(), 2u);
+  EXPECT_EQ(stats["buffer_stats"][0]["buffer_size"].asInt(), kBufferSize0);
+  EXPECT_EQ(stats["buffer_stats"][1]["buffer_size"].asInt(), kBufferSize1);
+}
+
+TEST(ExportJsonTest, StorageWithChromeMetadata) {
+  const char* kName1 = "name1";
+  const char* kName2 = "name2";
+  const char* kValue1 = "value1";
+  const int kValue2 = 222;
+
+  TraceProcessorContext context;
+  context.storage.reset(new TraceStorage());
+  TraceStorage* storage = context.storage.get();
+  ArgsTracker args(&context);
+
+  RowId row_id = storage->mutable_raw_events()->AddRawEvent(
+      0, storage->InternString("chrome_event.metadata"), 0, 0);
+
+  StringId name1_id = storage->InternString(base::StringView(kName1));
+  StringId name2_id = storage->InternString(base::StringView(kName2));
+  StringId value1_id = storage->InternString(base::StringView(kValue1));
+  args.AddArg(row_id, name1_id, name1_id, Variadic::String(value1_id));
+  args.AddArg(row_id, name2_id, name2_id, Variadic::Integer(kValue2));
+  args.Flush();
+
+  base::TempFile temp_file = base::TempFile::Create();
+  FILE* output = fopen(temp_file.path().c_str(), "w+");
+  int code = ExportJson(storage, output);
+  EXPECT_EQ(code, kResultOk);
+
+  Json::Reader reader;
+  Json::Value result;
+
+  EXPECT_TRUE(reader.parse(ReadFile(output), result));
+  EXPECT_TRUE(result.isMember("metadata"));
+  Json::Value metadata = result["metadata"];
+
+  EXPECT_EQ(metadata[kName1].asString(), kValue1);
+  EXPECT_EQ(metadata[kName2].asInt(), kValue2);
+}
+
 TEST(ExportJsonTest, StorageWithArgs) {
   const char* kCategory = "cat";
   const char* kName = "name";
diff --git a/src/trace_processor/forwarding_trace_parser.cc b/src/trace_processor/forwarding_trace_parser.cc
new file mode 100644
index 0000000..ca657f8
--- /dev/null
+++ b/src/trace_processor/forwarding_trace_parser.cc
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/forwarding_trace_parser.h"
+
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_utils.h"
+#include "src/trace_processor/fuchsia_trace_parser.h"
+#include "src/trace_processor/fuchsia_trace_tokenizer.h"
+#include "src/trace_processor/gzip_trace_parser.h"
+#include "src/trace_processor/proto_trace_parser.h"
+#include "src/trace_processor/proto_trace_tokenizer.h"
+#include "src/trace_processor/systrace_trace_parser.h"
+
+// JSON parsing and exporting is only supported in the standalone and
+// Chromium builds.
+#if PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD) || \
+    PERFETTO_BUILD_WITH_CHROMIUM
+#include "src/trace_processor/json_trace_parser.h"
+#include "src/trace_processor/json_trace_tokenizer.h"
+#endif
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+std::string RemoveWhitespace(const std::string& input) {
+  std::string str(input);
+  str.erase(std::remove_if(str.begin(), str.end(), ::isspace), str.end());
+  return str;
+}
+
+// Fuchsia traces have a magic number as documented here:
+// https://fuchsia.googlesource.com/fuchsia/+/HEAD/docs/development/tracing/trace-format/README.md#magic-number-record-trace-info-type-0
+constexpr uint64_t kFuchsiaMagicNumber = 0x0016547846040010;
+
+}  // namespace
+
+ForwardingTraceParser::ForwardingTraceParser(TraceProcessorContext* context)
+    : context_(context) {}
+
+ForwardingTraceParser::~ForwardingTraceParser() {}
+
+util::Status ForwardingTraceParser::Parse(std::unique_ptr<uint8_t[]> data,
+                                          size_t size) {
+  // If this is the first Parse() call, guess the trace type and create the
+  // appropriate parser.
+
+  if (!reader_) {
+    TraceType trace_type;
+    {
+      auto scoped_trace = context_->storage->TraceExecutionTimeIntoStats(
+          stats::guess_trace_type_duration_ns);
+      trace_type = GuessTraceType(data.get(), size);
+    }
+    switch (trace_type) {
+      case kJsonTraceType: {
+        PERFETTO_DLOG("JSON trace detected");
+#if PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD) || \
+    PERFETTO_BUILD_WITH_CHROMIUM
+        reader_.reset(new JsonTraceTokenizer(context_));
+        // JSON traces have no guarantees about the order of events in them.
+        int64_t window_size_ns = std::numeric_limits<int64_t>::max();
+        context_->sorter.reset(new TraceSorter(context_, window_size_ns));
+        context_->parser.reset(new JsonTraceParser(context_));
+#else
+        PERFETTO_FATAL("JSON traces not supported.");
+#endif
+        break;
+      }
+      case kProtoTraceType: {
+        PERFETTO_DLOG("Proto trace detected");
+        // This will be reduced once we read the trace config and we see flush
+        // period being set.
+        int64_t window_size_ns = std::numeric_limits<int64_t>::max();
+        reader_.reset(new ProtoTraceTokenizer(context_));
+        context_->sorter.reset(new TraceSorter(context_, window_size_ns));
+        context_->parser.reset(new ProtoTraceParser(context_));
+        break;
+      }
+      case kFuchsiaTraceType: {
+        PERFETTO_DLOG("Fuchsia trace detected");
+        // Fuschia traces can have massively out of order events.
+        int64_t window_size_ns = std::numeric_limits<int64_t>::max();
+        reader_.reset(new FuchsiaTraceTokenizer(context_));
+        context_->sorter.reset(new TraceSorter(context_, window_size_ns));
+        context_->parser.reset(new FuchsiaTraceParser(context_));
+        break;
+      }
+      case kSystraceTraceType:
+        PERFETTO_DLOG("Systrace trace detected");
+        reader_.reset(new SystraceTraceParser(context_));
+        break;
+      case kGzipTraceType:
+        PERFETTO_DLOG("gzip trace detected");
+        reader_.reset(new GzipTraceParser(context_));
+        break;
+      case kCtraceTraceType:
+        PERFETTO_DLOG("ctrace trace detected");
+        reader_.reset(new GzipTraceParser(context_));
+        break;
+      case kUnknownTraceType:
+        return util::ErrStatus("Unknown trace type provided");
+    }
+  }
+
+  return reader_->Parse(std::move(data), size);
+}
+
+TraceType GuessTraceType(const uint8_t* data, size_t size) {
+  if (size == 0)
+    return kUnknownTraceType;
+  std::string start(reinterpret_cast<const char*>(data),
+                    std::min<size_t>(size, 20));
+  std::string start_minus_white_space = RemoveWhitespace(start);
+  if (base::StartsWith(start_minus_white_space, "{\"traceEvents\":["))
+    return kJsonTraceType;
+  if (base::StartsWith(start_minus_white_space, "[{"))
+    return kJsonTraceType;
+  if (size >= 8) {
+    uint64_t first_word = *reinterpret_cast<const uint64_t*>(data);
+    if (first_word == kFuchsiaMagicNumber)
+      return kFuchsiaTraceType;
+  }
+
+  // Systrace with header but no leading HTML.
+  if (base::StartsWith(start, "# tracer"))
+    return kSystraceTraceType;
+
+  // Systrace with leading HTML.
+  if (base::StartsWith(start, "<!DOCTYPE html>") ||
+      base::StartsWith(start, "<html>"))
+    return kSystraceTraceType;
+
+  // Systrace with no header or leading HTML.
+  if (base::StartsWith(start, " "))
+    return kSystraceTraceType;
+
+  // Ctrace is deflate'ed systrace.
+  if (base::StartsWith(start, "TRACE:"))
+    return kCtraceTraceType;
+
+  // gzip'ed trace containing one of the other formats.
+  if (base::StartsWith(start, "\x1f\x8b"))
+    return kGzipTraceType;
+
+  return kProtoTraceType;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/forwarding_trace_parser.h b/src/trace_processor/forwarding_trace_parser.h
new file mode 100644
index 0000000..f7216b3
--- /dev/null
+++ b/src/trace_processor/forwarding_trace_parser.h
@@ -0,0 +1,55 @@
+/*
+ * 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_FORWARDING_TRACE_PARSER_H_
+#define SRC_TRACE_PROCESSOR_FORWARDING_TRACE_PARSER_H_
+
+#include "src/trace_processor/chunked_trace_reader.h"
+
+#include "src/trace_processor/trace_processor_context.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+enum TraceType {
+  kUnknownTraceType,
+  kProtoTraceType,
+  kJsonTraceType,
+  kFuchsiaTraceType,
+  kSystraceTraceType,
+  kGzipTraceType,
+  kCtraceTraceType,
+};
+
+TraceType GuessTraceType(const uint8_t* data, size_t size);
+
+class ForwardingTraceParser : public ChunkedTraceReader {
+ public:
+  explicit ForwardingTraceParser(TraceProcessorContext*);
+  ~ForwardingTraceParser() override;
+
+  // ChunkedTraceReader implementation
+  util::Status Parse(std::unique_ptr<uint8_t[]>, size_t) override;
+
+ private:
+  TraceProcessorContext* const context_;
+  std::unique_ptr<ChunkedTraceReader> reader_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_FORWARDING_TRACE_PARSER_H_
diff --git a/src/trace_processor/trace_processor_impl_unittest.cc b/src/trace_processor/forwarding_trace_parser_unittest.cc
similarity index 96%
rename from src/trace_processor/trace_processor_impl_unittest.cc
rename to src/trace_processor/forwarding_trace_parser_unittest.cc
index 24611d0..df4c013 100644
--- a/src/trace_processor/trace_processor_impl_unittest.cc
+++ b/src/trace_processor/forwarding_trace_parser_unittest.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "src/trace_processor/trace_processor_impl.h"
+#include "src/trace_processor/forwarding_trace_parser.h"
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
diff --git a/src/trace_processor/gzip_trace_parser.cc b/src/trace_processor/gzip_trace_parser.cc
index 7b93af9..a374019 100644
--- a/src/trace_processor/gzip_trace_parser.cc
+++ b/src/trace_processor/gzip_trace_parser.cc
@@ -18,7 +18,8 @@
 
 #include <zlib.h>
 
-#include "src/trace_processor/systrace_trace_parser.h"
+#include "perfetto/base/logging.h"
+#include "src/trace_processor/forwarding_trace_parser.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -28,7 +29,7 @@
   z_stream_->zalloc = Z_NULL;
   z_stream_->zfree = Z_NULL;
   z_stream_->opaque = Z_NULL;
-  inflateInit(z_stream_.get());
+  inflateInit2(z_stream_.get(), 32 + 15);
 }
 
 GzipTraceParser::~GzipTraceParser() {
@@ -41,13 +42,17 @@
   uint8_t* start = data.get();
   size_t len = size;
 
-  static const char kSystraceFilerHeader[] = "TRACE:\n";
   if (!inner_) {
-    inner_.reset(new SystraceTraceParser(context_));
+    inner_.reset(new ForwardingTraceParser(context_));
 
-    // Strip the header by ignoring the associated bytes.
-    start += strlen(kSystraceFilerHeader);
-    len -= strlen(kSystraceFilerHeader);
+    // .ctrace files begin with "TRACE:" strip this if present.
+    static const char kSystraceFileHeader[] = "TRACE:\n";
+    if (size >= strlen(kSystraceFileHeader) &&
+        strncmp(reinterpret_cast<char*>(start), kSystraceFileHeader,
+                strlen(kSystraceFileHeader)) == 0) {
+      start += strlen(kSystraceFileHeader);
+      len -= strlen(kSystraceFileHeader);
+    }
   }
 
   z_stream_->next_in = start;
diff --git a/src/trace_processor/metrics/android/android_mem.sql b/src/trace_processor/metrics/android/android_mem.sql
index 4f9f5a4..34c948a 100644
--- a/src/trace_processor/metrics/android/android_mem.sql
+++ b/src/trace_processor/metrics/android/android_mem.sql
@@ -24,6 +24,8 @@
 
 SELECT RUN_METRIC('android/span_view_stats.sql', 'table_name', 'anon_and_swap');
 
+SELECT RUN_METRIC('android/span_view_stats.sql', 'table_name', 'java_heap');
+
 SELECT RUN_METRIC('android/mem_stats_priority_breakdown.sql', 'table_name', 'anon_rss');
 
 SELECT RUN_METRIC('android/mem_stats_priority_breakdown.sql', 'table_name', 'file_rss');
@@ -32,76 +34,83 @@
 
 SELECT RUN_METRIC('android/mem_stats_priority_breakdown.sql', 'table_name', 'anon_and_swap');
 
+SELECT RUN_METRIC('android/mem_stats_priority_breakdown.sql', 'table_name', 'java_heap');
+
+-- Find out all process + priority pairs with data to drive the joins (no outer join in sqlite).
+CREATE VIEW mem_all_processes AS
+SELECT DISTINCT process_name
+FROM
+(
+  SELECT process_name FROM anon_rss_stats_proto
+  UNION
+  SELECT process_name FROM file_rss_stats_proto
+  UNION
+  SELECT process_name FROM swap_stats_proto
+  UNION
+  SELECT process_name FROM anon_and_swap_stats_proto
+  UNION
+  SELECT process_name FROM java_heap_stats_proto
+);
+
+CREATE VIEW mem_all_process_priorities AS
+SELECT DISTINCT process_name, priority
+FROM
+(
+  SELECT process_name, priority FROM anon_rss_by_priority_stats_proto
+  UNION
+  SELECT process_name, priority FROM file_rss_by_priority_stats_proto
+  UNION
+  SELECT process_name, priority FROM swap_by_priority_stats_proto
+  UNION
+  SELECT process_name, priority FROM anon_and_swap_by_priority_stats_proto
+  UNION
+  SELECT process_name, priority FROM java_heap_by_priority_stats_proto
+);
+
 CREATE VIEW process_priority_view AS
 SELECT
   process_name,
   AndroidMemoryMetric_PriorityBreakdown(
     'priority', priority,
     'counters', AndroidMemoryMetric_ProcessMemoryCounters(
-      'anon_rss', AndroidMemoryMetric_Counter(
-        'min', anon_rss_by_priority_stats.min_value,
-        'max', anon_rss_by_priority_stats.max_value,
-        'avg', anon_rss_by_priority_stats.avg_value
-      ),
-      'file_rss', AndroidMemoryMetric_Counter(
-        'min', file_rss_by_priority_stats.min_value,
-        'max', file_rss_by_priority_stats.max_value,
-        'avg', file_rss_by_priority_stats.avg_value
-      ),
-      'swap', AndroidMemoryMetric_Counter(
-        'min', swap_by_priority_stats.min_value,
-        'max', swap_by_priority_stats.max_value,
-        'avg', swap_by_priority_stats.avg_value
-      ),
-      'anon_and_swap', AndroidMemoryMetric_Counter(
-        'min', anon_and_swap_by_priority_stats.min_value,
-        'max', anon_and_swap_by_priority_stats.max_value,
-        'avg', anon_and_swap_by_priority_stats.avg_value
-      )
+      'anon_rss', anon_rss_by_priority_stats_proto.proto,
+      'file_rss', file_rss_by_priority_stats_proto.proto,
+      'swap', swap_by_priority_stats_proto.proto,
+      'anon_and_swap', anon_and_swap_by_priority_stats_proto.proto,
+      'java_heap', java_heap_by_priority_stats_proto.proto
     )
   ) AS priority_breakdown_proto
-FROM anon_rss_by_priority_stats
-JOIN file_rss_by_priority_stats USING (process_name, priority)
-JOIN swap_by_priority_stats USING (process_name, priority)
-JOIN anon_and_swap_by_priority_stats USING (process_name, priority);
+FROM mem_all_process_priorities
+LEFT JOIN anon_rss_by_priority_stats_proto USING (process_name, priority)
+LEFT JOIN file_rss_by_priority_stats_proto USING (process_name, priority)
+LEFT JOIN swap_by_priority_stats_proto USING (process_name, priority)
+LEFT JOIN anon_and_swap_by_priority_stats_proto USING (process_name, priority)
+LEFT JOIN java_heap_by_priority_stats_proto USING (process_name, priority);
 
 CREATE VIEW process_metrics_view AS
 SELECT
   AndroidMemoryMetric_ProcessMetrics(
     'process_name', process_name,
     'total_counters', AndroidMemoryMetric_ProcessMemoryCounters(
-      'anon_rss', AndroidMemoryMetric_Counter(
-        'min', anon_rss_stats.min_value,
-        'max', anon_rss_stats.max_value,
-        'avg', anon_rss_stats.avg_value
-      ),
-      'file_rss', AndroidMemoryMetric_Counter(
-        'min', file_rss_stats.min_value,
-        'max', file_rss_stats.max_value,
-        'avg', file_rss_stats.avg_value
-      ),
-      'swap', AndroidMemoryMetric_Counter(
-        'min', swap_stats.min_value,
-        'max', swap_stats.max_value,
-        'avg', swap_stats.avg_value
-      ),
-      'anon_and_swap', AndroidMemoryMetric_Counter(
-        'min', anon_and_swap_stats.min_value,
-        'max', anon_and_swap_stats.max_value,
-        'avg', anon_and_swap_stats.avg_value
-      )
+      'anon_rss', anon_rss_stats_proto.proto,
+      'file_rss', file_rss_stats_proto.proto,
+      'swap', swap_stats_proto.proto,
+      'anon_and_swap', anon_and_swap_stats_proto.proto,
+      'java_heap', java_heap_stats_proto.proto
     ),
     'priority_breakdown', (
       SELECT RepeatedField(priority_breakdown_proto)
       FROM process_priority_view AS ppv
-      WHERE anon_rss_stats.process_name = ppv.process_name
+      WHERE anon_rss_stats_proto.process_name = ppv.process_name
     )
   ) AS metric
 FROM
-  anon_rss_stats
-  JOIN file_rss_stats USING (process_name)
-  JOIN swap_stats USING (process_name)
-  JOIN anon_and_swap_stats USING (process_name);
+  mem_all_processes
+  LEFT JOIN anon_rss_stats_proto USING (process_name)
+  LEFT JOIN file_rss_stats_proto USING (process_name)
+  LEFT JOIN swap_stats_proto USING (process_name)
+  LEFT JOIN anon_and_swap_stats_proto USING (process_name)
+  LEFT JOIN java_heap_stats_proto USING (process_name);
 
 CREATE VIEW android_mem_output AS
 SELECT
diff --git a/src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql b/src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql
index 8db50f4..f7ef71b 100644
--- a/src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql
+++ b/src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql
@@ -51,3 +51,16 @@
 WHERE process.name IS NOT NULL
 GROUP BY 1, 2
 ORDER BY 1, 2;
+
+DROP VIEW IF EXISTS {{table_name}}_by_priority_stats_proto;
+
+CREATE VIEW {{table_name}}_by_priority_stats_proto AS
+SELECT
+  process_name,
+  priority,
+  AndroidMemoryMetric_Counter(
+    'min', min_value,
+    'max', max_value,
+    'avg', avg_value
+  ) AS proto
+FROM {{table_name}}_by_priority_stats;
diff --git a/src/trace_processor/metrics/android/process_mem.sql b/src/trace_processor/metrics/android/process_mem.sql
index d6a8454..131e942 100644
--- a/src/trace_processor/metrics/android/process_mem.sql
+++ b/src/trace_processor/metrics/android/process_mem.sql
@@ -44,6 +44,17 @@
   IFNULL(anon_rss_val, 0) + IFNULL(swap_val, 0) AS anon_and_swap_val
 FROM anon_and_swap_join;
 
+-- If we have dalvik events enabled (for ART trace points) we can construct the java heap timeline.
+SELECT RUN_METRIC('android/upid_span_view.sql',
+  'table_name', 'java_heap_kb',
+  'counter_name', 'Heap size (KB)');
+
+DROP VIEW IF EXISTS java_heap_span;
+
+CREATE VIEW java_heap_span AS
+SELECT ts, dur, upid, java_heap_kb_val * 1024 AS java_heap_val
+FROM java_heap_kb_span;
+
 -- Create a track for process OOM scores.
 DROP VIEW IF EXISTS oom_score_span;
 
@@ -76,3 +87,8 @@
 
 CREATE VIRTUAL TABLE anon_and_swap_by_oom_span
 USING SPAN_JOIN(anon_and_swap_span PARTITIONED upid, oom_score_span PARTITIONED upid);
+
+DROP TABLE IF EXISTS java_heap_by_oom_span;
+
+CREATE VIRTUAL TABLE java_heap_by_oom_span
+USING SPAN_JOIN(java_heap_span PARTITIONED upid, oom_score_span PARTITIONED upid);
diff --git a/src/trace_processor/metrics/android/span_view_stats.sql b/src/trace_processor/metrics/android/span_view_stats.sql
index 52f6d15..ff85408 100644
--- a/src/trace_processor/metrics/android/span_view_stats.sql
+++ b/src/trace_processor/metrics/android/span_view_stats.sql
@@ -33,3 +33,15 @@
 WHERE process.name IS NOT NULL
 GROUP BY 1
 ORDER BY 1;
+
+DROP VIEW IF EXISTS {{table_name}}_stats_proto;
+
+CREATE VIEW {{table_name}}_stats_proto AS
+SELECT
+  process_name,
+  AndroidMemoryMetric_Counter(
+    'min', min_value,
+    'max', max_value,
+    'avg', avg_value
+  ) AS proto
+FROM {{table_name}}_stats;
diff --git a/src/trace_processor/metrics/metrics.descriptor.h b/src/trace_processor/metrics/metrics.descriptor.h
index d7e9337..19593fb 100644
--- a/src/trace_processor/metrics/metrics.descriptor.h
+++ b/src/trace_processor/metrics/metrics.descriptor.h
@@ -19,7 +19,7 @@
 
 namespace perfetto {
 
-constexpr std::array<uint8_t, 8768> kMetricsDescriptor{
+constexpr std::array<uint8_t, 8843> kMetricsDescriptor{
     {0x0a, 0x91, 0x03, 0x0a, 0x2a, 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,
@@ -98,12 +98,12 @@
      0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
      0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54, 0x68,
      0x72, 0x65, 0x61, 0x64, 0x52, 0x07, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64,
-     0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xc1, 0x07, 0x0a, 0x29, 0x70, 0x65,
+     0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x8c, 0x08, 0x0a, 0x29, 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, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xfe, 0x06, 0x0a,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xc9, 0x07, 0x0a,
      0x13, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f,
      0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x5c, 0x0a, 0x0f,
      0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72,
@@ -146,7 +146,7 @@
      0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f,
      0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x6f,
      0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x08, 0x63, 0x6f, 0x75, 0x6e,
-     0x74, 0x65, 0x72, 0x73, 0x1a, 0xbd, 0x02, 0x0a, 0x15, 0x50, 0x72, 0x6f,
+     0x74, 0x65, 0x72, 0x73, 0x1a, 0x88, 0x03, 0x0a, 0x15, 0x50, 0x72, 0x6f,
      0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x6f,
      0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x47, 0x0a, 0x08, 0x61, 0x6e,
      0x6f, 0x6e, 0x5f, 0x72, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
@@ -173,584 +173,590 @@
      0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74,
      0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52,
      0x0b, 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x53, 0x77, 0x61, 0x70,
-     0x1a, 0x3f, 0x0a, 0x07, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12,
-     0x10, 0x0a, 0x03, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01,
-     0x52, 0x03, 0x6d, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x78,
-     0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x6d, 0x61, 0x78, 0x12,
-     0x10, 0x0a, 0x03, 0x61, 0x76, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01,
-     0x52, 0x03, 0x61, 0x76, 0x67, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x9d, 0x06,
-     0x0a, 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, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xd4, 0x05, 0x0a, 0x1f, 0x41,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
-     0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64,
-     0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x65, 0x0a, 0x0e, 0x70, 0x72,
-     0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73,
-     0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f,
-     0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74,
-     0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f,
-     0x63, 0x65, 0x73, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x0d,
-     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65,
-     0x73, 0x1a, 0x97, 0x01, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
-     0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 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, 0x63, 0x0a, 0x0a, 0x6d, 0x65,
-     0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x44, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e,
-     0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-     0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73,
-     0x52, 0x09, 0x6d, 0x65, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a,
-     0xe3, 0x02, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d,
-     0x65, 0x6d, 0x6f, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12,
-     0x51, 0x0a, 0x08, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x72, 0x73, 0x73, 0x18,
-     0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x12, 0x49, 0x0a, 0x09, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61,
+     0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d,
+     0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f,
+     0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x08, 0x6a, 0x61, 0x76, 0x61, 0x48,
+     0x65, 0x61, 0x70, 0x1a, 0x3f, 0x0a, 0x07, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+     0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x01, 0x52, 0x03, 0x6d, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03,
+     0x6d, 0x61, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x6d,
+     0x61, 0x78, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x76, 0x67, 0x18, 0x03, 0x20,
+     0x01, 0x28, 0x01, 0x52, 0x03, 0x61, 0x76, 0x67, 0x42, 0x02, 0x48, 0x03,
+     0x0a, 0x9d, 0x06, 0x0a, 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, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xd4, 0x05,
+     0x0a, 0x1f, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d,
+     0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61,
+     0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x65, 0x0a,
+     0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x76, 0x61, 0x6c,
+     0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d,
+     0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65,
+     0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+     0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65,
+     0x73, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x56, 0x61,
+     0x6c, 0x75, 0x65, 0x73, 0x1a, 0x97, 0x01, 0x0a, 0x0d, 0x50, 0x72, 0x6f,
+     0x63, 0x65, 0x73, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 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, 0x63, 0x0a,
+     0x0a, 0x6d, 0x65, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18,
+     0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x70, 0x65, 0x72, 0x66,
      0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
      0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72,
      0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65,
-     0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x56, 0x61, 0x6c, 0x75,
-     0x65, 0x52, 0x07, 0x61, 0x6e, 0x6f, 0x6e, 0x52, 0x73, 0x73, 0x12, 0x51,
-     0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x72, 0x73, 0x73, 0x18, 0x02,
-     0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
-     0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64,
-     0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65,
-     0x52, 0x07, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x73, 0x73, 0x12, 0x4a, 0x0a,
-     0x04, 0x73, 0x77, 0x61, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
-     0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67,
-     0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x73, 0x77, 0x61,
-     0x70, 0x12, 0x5a, 0x0a, 0x0d, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x61, 0x6e,
-     0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b,
-     0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67,
-     0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0b, 0x61, 0x6e,
-     0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x53, 0x77, 0x61, 0x70, 0x1a, 0x4a, 0x0a,
-     0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x73,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x74, 0x73, 0x12, 0x1b,
-     0x0a, 0x09, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18,
-     0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6f, 0x6f, 0x6d, 0x53, 0x63,
-     0x6f, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
-     0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
-     0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x89, 0x04, 0x0a, 0x2d, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x77, 0x74,
-     0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x22, 0xc2, 0x03, 0x0a, 0x14, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74,
-     0x68, 0x12, 0x60, 0x0a, 0x10, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
-     0x65, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x01, 0x20,
-     0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x56, 0x61, 0x6c,
+     0x75, 0x65, 0x73, 0x52, 0x09, 0x6d, 0x65, 0x6d, 0x56, 0x61, 0x6c, 0x75,
+     0x65, 0x73, 0x1a, 0xe3, 0x02, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x63, 0x65,
+     0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x75,
+     0x65, 0x73, 0x12, 0x51, 0x0a, 0x08, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x72,
+     0x73, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65,
+     0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67,
+     0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x56,
+     0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x61, 0x6e, 0x6f, 0x6e, 0x52, 0x73,
+     0x73, 0x12, 0x51, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x72, 0x73,
+     0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d,
+     0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61,
+     0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x56, 0x61,
+     0x6c, 0x75, 0x65, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x73, 0x73,
+     0x12, 0x4a, 0x0a, 0x04, 0x73, 0x77, 0x61, 0x70, 0x18, 0x03, 0x20, 0x03,
+     0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
+     0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e,
+     0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65,
+     0x74, 0x72, 0x69, 0x63, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04,
+     0x73, 0x77, 0x61, 0x70, 0x12, 0x5a, 0x0a, 0x0d, 0x61, 0x6e, 0x6f, 0x6e,
+     0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x18, 0x04, 0x20,
+     0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
      0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-     0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61,
-     0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x0f,
-     0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x73, 0x1a, 0xc7, 0x02, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x74,
-     0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12,
-     0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
-     0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f,
-     0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
-     0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-     0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x19, 0x61, 0x6e, 0x6f, 0x6e,
-     0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x73, 0x74,
-     0x61, 0x72, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20,
-     0x01, 0x28, 0x03, 0x52, 0x15, 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e, 0x64,
-     0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x72, 0x74, 0x56, 0x61, 0x6c,
-     0x75, 0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x61,
-     0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x63, 0x68, 0x61, 0x6e,
-     0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x16, 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x53,
-     0x77, 0x61, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x79, 0x74,
-     0x65, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63,
-     0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x63, 0x68, 0x61, 0x6e,
-     0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x17, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x4d, 0x65,
-     0x6d, 0x6f, 0x72, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x79,
-     0x74, 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x23, 0x6d, 0x61, 0x6c, 0x6c, 0x6f,
-     0x63, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x74, 0x6f, 0x74,
-     0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64,
-     0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
-     0x52, 0x1f, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x4d, 0x65, 0x6d, 0x6f,
-     0x72, 0x79, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
-     0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x02, 0x48,
-     0x03, 0x0a, 0xa8, 0x02, 0x0a, 0x29, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x69, 0x6f, 0x6e, 0x5f, 0x6d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
-     0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x12, 0x40, 0x0a, 0x06, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x18,
-     0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55,
+     0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
+     0x0b, 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x53, 0x77, 0x61, 0x70,
+     0x1a, 0x4a, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x0e, 0x0a,
+     0x02, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x74,
+     0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f,
+     0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6f, 0x6f,
+     0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
+     0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76,
+     0x61, 0x6c, 0x75, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x89, 0x04, 0x0a,
+     0x2d, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
+     0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72,
+     0x6f, 0x77, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x22, 0xc2, 0x03, 0x0a, 0x14, 0x41, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72,
+     0x6f, 0x77, 0x74, 0x68, 0x12, 0x60, 0x0a, 0x10, 0x69, 0x6e, 0x73, 0x74,
+     0x61, 0x6e, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+     0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2e, 0x49, 0x6e,
+     0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x73, 0x52, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x1a, 0xc7, 0x02, 0x0a, 0x0f, 0x49,
+     0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69,
+     0x63, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x0d, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x19, 0x61,
+     0x6e, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70,
+     0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
+     0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x61, 0x6e, 0x6f, 0x6e,
+     0x41, 0x6e, 0x64, 0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x72, 0x74,
+     0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x61, 0x6e, 0x6f,
+     0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x63,
+     0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18,
+     0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x61, 0x6e, 0x6f, 0x6e, 0x41,
+     0x6e, 0x64, 0x53, 0x77, 0x61, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65,
+     0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x6d, 0x61, 0x6c,
+     0x6c, 0x6f, 0x63, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x63,
+     0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18,
+     0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x6d, 0x61, 0x6c, 0x6c, 0x6f,
+     0x63, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x67,
+     0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x23, 0x6d, 0x61,
+     0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f,
+     0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61,
+     0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x1f, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x4d,
+     0x65, 0x6d, 0x6f, 0x72, 0x79, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c,
+     0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73,
+     0x42, 0x02, 0x48, 0x03, 0x0a, 0xa8, 0x02, 0x0a, 0x29, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x69, 0x6f,
+     0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x10,
      0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x2e, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x52,
-     0x06, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x1a, 0x8e, 0x01, 0x0a, 0x06,
-     0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
-     0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
-     0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x76, 0x67, 0x5f, 0x73, 0x69,
-     0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01,
-     0x28, 0x01, 0x52, 0x0c, 0x61, 0x76, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x42,
-     0x79, 0x74, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x69, 0x6e, 0x5f,
-     0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03,
-     0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x6d, 0x69, 0x6e, 0x53, 0x69, 0x7a,
-     0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x61,
-     0x78, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73,
-     0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x53,
-     0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x02, 0x48, 0x03,
-     0x0a, 0x8e, 0x02, 0x0a, 0x29, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x74, 0x72, 0x69, 0x63, 0x12, 0x40, 0x0a, 0x06, 0x62, 0x75, 0x66, 0x66,
+     0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f,
+     0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x42, 0x75, 0x66, 0x66,
+     0x65, 0x72, 0x52, 0x06, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x1a, 0x8e,
+     0x01, 0x0a, 0x06, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x12, 0x12, 0x0a,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x76, 0x67,
+     0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18,
+     0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x61, 0x76, 0x67, 0x53, 0x69,
+     0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d,
+     0x69, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65,
+     0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x6d, 0x69, 0x6e,
+     0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x24, 0x0a,
+     0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79,
+     0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x6d,
+     0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42,
+     0x02, 0x48, 0x03, 0x0a, 0x8e, 0x02, 0x0a, 0x29, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+     0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b,
+     0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xcb, 0x01, 0x0a, 0x10, 0x41,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74,
+     0x72, 0x69, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c,
+     0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
+     0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+     0x12, 0x4e, 0x0a, 0x0c, 0x62, 0x79, 0x5f, 0x6f, 0x6f, 0x6d, 0x5f, 0x73,
+     0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c,
+     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x42, 0x79,
+     0x4f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x0a, 0x62, 0x79,
+     0x4f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x0a,
+     0x42, 0x79, 0x4f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x22,
+     0x0a, 0x0d, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f,
+     0x61, 0x64, 0x6a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f,
+     0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12, 0x14,
+     0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
+     0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x02, 0x48, 0x03,
+     0x0a, 0xed, 0x02, 0x0a, 0x2e, 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,
+     0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69,
+     0x6c, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xa5, 0x02, 0x0a,
+     0x11, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65,
+     0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0b, 0x70, 0x6f,
+     0x77, 0x65, 0x72, 0x5f, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x01, 0x20,
+     0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
+     0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61,
+     0x69, 0x6c, 0x73, 0x2e, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69,
+     0x6c, 0x73, 0x52, 0x0a, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69,
+     0x6c, 0x73, 0x1a, 0x4e, 0x0a, 0x0a, 0x45, 0x6e, 0x65, 0x72, 0x67, 0x79,
+     0x44, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65,
+     0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+     0x70, 0x4d, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6e, 0x65, 0x72, 0x67,
+     0x79, 0x5f, 0x75, 0x77, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52,
+     0x09, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x55, 0x77, 0x73, 0x1a, 0x70,
+     0x0a, 0x0a, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73,
+     0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x0b,
+     0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18,
+     0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72,
+     0x52, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x6e, 0x65, 0x72, 0x67, 0x79,
+     0x44, 0x61, 0x74, 0x61, 0x52, 0x0a, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79,
+     0x44, 0x61, 0x74, 0x61, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xa5, 0x0e, 0x0a,
+     0x2d, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
+     0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x2f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x6d, 0x65,
      0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
      0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x22, 0xcb, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f,
-     0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x74,
-     0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x4e, 0x0a,
-     0x0c, 0x62, 0x79, 0x5f, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72,
-     0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b,
-     0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x42, 0x79, 0x4f, 0x6f, 0x6d,
-     0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x0a, 0x62, 0x79, 0x4f, 0x6f, 0x6d,
-     0x53, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x0a, 0x42, 0x79, 0x4f,
-     0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6f,
-     0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x64, 0x6a,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6f, 0x6d, 0x53,
-     0x63, 0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12, 0x14, 0x0a, 0x05, 0x63,
-     0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05,
-     0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xed, 0x02,
-     0x0a, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x2f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x5f,
-     0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xa5, 0x02, 0x0a, 0x11, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61,
-     0x69, 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0b, 0x70, 0x6f, 0x77, 0x65, 0x72,
-     0x5f, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
-     0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73,
-     0x2e, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x52,
-     0x0a, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x1a,
-     0x4e, 0x0a, 0x0a, 0x45, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74,
-     0x61, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
-     0x6d, 0x70, 0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
-     0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x73,
-     0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x5f, 0x75,
-     0x77, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x65, 0x6e,
-     0x65, 0x72, 0x67, 0x79, 0x55, 0x77, 0x73, 0x1a, 0x70, 0x0a, 0x0a, 0x50,
-     0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x12, 0x0a,
-     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
-     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x0b, 0x65, 0x6e, 0x65,
-     0x72, 0x67, 0x79, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03,
-     0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69,
-     0x6c, 0x73, 0x2e, 0x45, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74,
-     0x61, 0x52, 0x0a, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74,
-     0x61, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xa5, 0x0e, 0x0a, 0x2d, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73,
-     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x22, 0xde, 0x0d, 0x0a, 0x14, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x12, 0x47, 0x0a, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70,
-     0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72,
-     0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x74,
-     0x61, 0x72, 0x74, 0x75, 0x70, 0x52, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74,
-     0x75, 0x70, 0x1a, 0xe0, 0x01, 0x0a, 0x12, 0x54, 0x61, 0x73, 0x6b, 0x53,
-     0x74, 0x61, 0x74, 0x65, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77,
-     0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67,
-     0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
-     0x03, 0x52, 0x0c, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x44, 0x75,
-     0x72, 0x4e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x72, 0x75, 0x6e, 0x6e, 0x61,
-     0x62, 0x6c, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x02,
-     0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x72, 0x75, 0x6e, 0x6e, 0x61, 0x62,
-     0x6c, 0x65, 0x44, 0x75, 0x72, 0x4e, 0x73, 0x12, 0x3f, 0x0a, 0x1c, 0x75,
-     0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74, 0x69, 0x62,
-     0x6c, 0x65, 0x5f, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5f, 0x64, 0x75, 0x72,
-     0x5f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x19, 0x75,
-     0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74, 0x69, 0x62,
-     0x6c, 0x65, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x44, 0x75, 0x72, 0x4e, 0x73,
-     0x12, 0x3b, 0x0a, 0x1a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70,
+     0x74, 0x6f, 0x73, 0x22, 0xde, 0x0d, 0x0a, 0x14, 0x41, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65,
+     0x74, 0x72, 0x69, 0x63, 0x12, 0x47, 0x0a, 0x07, 0x73, 0x74, 0x61, 0x72,
+     0x74, 0x75, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
+     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x52, 0x07, 0x73, 0x74,
+     0x61, 0x72, 0x74, 0x75, 0x70, 0x1a, 0xe0, 0x01, 0x0a, 0x12, 0x54, 0x61,
+     0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x72, 0x65, 0x61, 0x6b,
+     0x64, 0x6f, 0x77, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x75, 0x6e, 0x6e,
+     0x69, 0x6e, 0x67, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x01,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e,
+     0x67, 0x44, 0x75, 0x72, 0x4e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x72, 0x75,
+     0x6e, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e,
+     0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x72, 0x75, 0x6e,
+     0x6e, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x4e, 0x73, 0x12, 0x3f,
+     0x0a, 0x1c, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70,
      0x74, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5f,
-     0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
-     0x52, 0x17, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74, 0x69,
-     0x62, 0x6c, 0x65, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x44, 0x75, 0x72, 0x4e,
-     0x73, 0x1a, 0x1e, 0x0a, 0x05, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x12, 0x15,
-     0x0a, 0x06, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x05, 0x64, 0x75, 0x72, 0x4e, 0x73, 0x1a, 0xbb, 0x08,
-     0x0a, 0x0c, 0x54, 0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61,
-     0x6d, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x75, 0x72, 0x4e,
-     0x73, 0x12, 0x72, 0x0a, 0x19, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x74, 0x68,
-     0x72, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x74, 0x61, 0x73, 0x6b,
-     0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
-     0x32, 0x38, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74,
-     0x65, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x15,
-     0x6d, 0x61, 0x69, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x42, 0x79,
-     0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x41, 0x0a,
-     0x1d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x65, 0x73, 0x5f, 0x73, 0x70, 0x61, 0x77, 0x6e, 0x65, 0x64,
-     0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d,
-     0x52, 0x1a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x65, 0x73, 0x53, 0x70, 0x61, 0x77, 0x6e, 0x65, 0x64, 0x43,
-     0x6f, 0x75, 0x6e, 0x74, 0x12, 0x5f, 0x0a, 0x15, 0x74, 0x69, 0x6d, 0x65,
-     0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x6d, 0x61,
-     0x6e, 0x61, 0x67, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
-     0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x13, 0x74, 0x69,
-     0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x4d, 0x61,
-     0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x66, 0x0a, 0x19, 0x74, 0x69, 0x6d,
-     0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x74,
-     0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x05,
-     0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75,
-     0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63,
-     0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76,
-     0x69, 0x74, 0x79, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x4d, 0x61, 0x69,
-     0x6e, 0x12, 0x5f, 0x0a, 0x15, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x62, 0x69,
-     0x6e, 0x64, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69,
-     0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74,
-     0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
-     0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x13, 0x74, 0x69, 0x6d, 0x65, 0x42,
-     0x69, 0x6e, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69,
-     0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x13, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61,
-     0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x72,
-     0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61,
-     0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53,
-     0x6c, 0x69, 0x63, 0x65, 0x52, 0x11, 0x74, 0x69, 0x6d, 0x65, 0x41, 0x63,
-     0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12,
-     0x5d, 0x0a, 0x14, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69,
-     0x76, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x18,
-     0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74,
-     0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69,
-     0x63, 0x65, 0x52, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69,
-     0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x12, 0x5a,
-     0x0a, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x63, 0x68, 0x6f, 0x72, 0x65,
-     0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01,
+     0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x19, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70,
+     0x74, 0x69, 0x62, 0x6c, 0x65, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x44, 0x75,
+     0x72, 0x4e, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x69, 0x6e, 0x74, 0x65, 0x72,
+     0x72, 0x75, 0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x6c, 0x65,
+     0x65, 0x70, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x04, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x17, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75,
+     0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x44,
+     0x75, 0x72, 0x4e, 0x73, 0x1a, 0x1e, 0x0a, 0x05, 0x53, 0x6c, 0x69, 0x63,
+     0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18,
+     0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x75, 0x72, 0x4e, 0x73,
+     0x1a, 0xbb, 0x08, 0x0a, 0x0c, 0x54, 0x6f, 0x46, 0x69, 0x72, 0x73, 0x74,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x75, 0x72,
+     0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64,
+     0x75, 0x72, 0x4e, 0x73, 0x12, 0x72, 0x0a, 0x19, 0x6d, 0x61, 0x69, 0x6e,
+     0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x74,
+     0x61, 0x73, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
+     0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70,
+     0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53,
+     0x74, 0x61, 0x74, 0x65, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77,
+     0x6e, 0x52, 0x15, 0x6d, 0x61, 0x69, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61,
+     0x64, 0x42, 0x79, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65,
+     0x12, 0x41, 0x0a, 0x1d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x70, 0x72,
+     0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x73, 0x70, 0x61, 0x77,
+     0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20,
+     0x01, 0x28, 0x0d, 0x52, 0x1a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x50, 0x72,
+     0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x53, 0x70, 0x61, 0x77, 0x6e,
+     0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x5f, 0x0a, 0x15, 0x74,
+     0x69, 0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79,
+     0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01,
      0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
      0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
      0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d,
      0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52,
-     0x11, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x68, 0x6f, 0x72, 0x65, 0x6f, 0x67,
-     0x72, 0x61, 0x70, 0x68, 0x65, 0x72, 0x12, 0x66, 0x0a, 0x19, 0x74, 0x69,
-     0x6d, 0x65, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x74,
-     0x61, 0x72, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18,
-     0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x13, 0x74, 0x69, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74,
+     0x79, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x66, 0x0a, 0x19,
+     0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74,
+     0x79, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6d, 0x61, 0x69,
+     0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65,
+     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61,
+     0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53,
+     0x6c, 0x69, 0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x41, 0x63,
+     0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64,
+     0x4d, 0x61, 0x69, 0x6e, 0x12, 0x5f, 0x0a, 0x15, 0x74, 0x69, 0x6d, 0x65,
+     0x5f, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63,
+     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32,
+     0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x13, 0x74, 0x69,
+     0x6d, 0x65, 0x42, 0x69, 0x6e, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63,
+     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x13, 0x74, 0x69, 0x6d,
+     0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x73,
+     0x74, 0x61, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b,
+     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69,
+     0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x11, 0x74, 0x69, 0x6d,
+     0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61,
+     0x72, 0x74, 0x12, 0x5d, 0x0a, 0x14, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61,
+     0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x73, 0x75,
+     0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74,
+     0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+     0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x41,
+     0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6d,
+     0x65, 0x12, 0x5a, 0x0a, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x63, 0x68,
+     0x6f, 0x72, 0x65, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72, 0x18,
+     0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66,
      0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
      0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74,
      0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69,
-     0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x42, 0x65, 0x66, 0x6f,
-     0x72, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x12, 0x66, 0x0a, 0x19, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64,
-     0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f,
-     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x16,
-     0x74, 0x69, 0x6d, 0x65, 0x44, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74,
-     0x61, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x4b,
-     0x0a, 0x23, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x63,
-     0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76,
-     0x69, 0x74, 0x79, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x72, 0x61, 0x74, 0x69,
-     0x6f, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x1e, 0x6f, 0x74, 0x68,
-     0x65, 0x72, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x41,
-     0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x43, 0x70, 0x75, 0x52, 0x61,
-     0x74, 0x69, 0x6f, 0x1a, 0xbb, 0x02, 0x0a, 0x07, 0x53, 0x74, 0x61, 0x72,
-     0x74, 0x75, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74,
-     0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52,
-     0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x49, 0x64, 0x12, 0x21,
-     0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61,
-     0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61,
-     0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a,
-     0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d,
-     0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f,
-     0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2c, 0x0a, 0x12,
-     0x7a, 0x79, 0x67, 0x6f, 0x74, 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x70,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
-     0x52, 0x10, 0x7a, 0x79, 0x67, 0x6f, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x50,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x43, 0x0a, 0x1e, 0x61, 0x63,
-     0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x69,
-     0x6e, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63,
-     0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x1b,
-     0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x48, 0x6f, 0x73, 0x74,
-     0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f,
-     0x75, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x0e, 0x74, 0x6f, 0x5f, 0x66, 0x69,
-     0x72, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70,
-     0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54, 0x6f, 0x46, 0x69, 0x72,
-     0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x0c, 0x74, 0x6f, 0x46,
-     0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x42, 0x02, 0x48,
-     0x03, 0x0a, 0xcb, 0x05, 0x0a, 0x3a, 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, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xf7, 0x04,
-     0x0a, 0x18, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
-     0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61,
-     0x74, 0x73, 0x12, 0x5e, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e,
-     0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03,
-     0x28, 0x0b, 0x32, 0x37, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61,
-     0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c,
-     0x73, 0x69, 0x74, 0x65, 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, 0x1b, 0x0a, 0x05, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12,
-     0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-     0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x1a, 0x51, 0x0a, 0x08, 0x43,
-     0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x12, 0x45, 0x0a, 0x05, 0x66,
-     0x72, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f,
+     0x63, 0x65, 0x52, 0x11, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x68, 0x6f, 0x72,
+     0x65, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72, 0x12, 0x66, 0x0a,
+     0x19, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
+     0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65,
+     0x73, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74,
+     0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+     0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x42,
+     0x65, 0x66, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72,
+     0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x66, 0x0a, 0x19, 0x74, 0x69, 0x6d,
+     0x65, 0x5f, 0x64, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x61,
+     0x72, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x0b,
+     0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75,
+     0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63,
+     0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x75, 0x72, 0x69, 0x6e,
+     0x67, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
+     0x73, 0x12, 0x4b, 0x0a, 0x23, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x70,
+     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63,
+     0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x72,
+     0x61, 0x74, 0x69, 0x6f, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x1e,
+     0x6f, 0x74, 0x68, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+     0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x43, 0x70,
+     0x75, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x1a, 0xbb, 0x02, 0x0a, 0x07, 0x53,
+     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74,
+     0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x0d, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x49,
+     0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
+     0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+     0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65,
+     0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
+     0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12,
+     0x2c, 0x0a, 0x12, 0x7a, 0x79, 0x67, 0x6f, 0x74, 0x65, 0x5f, 0x6e, 0x65,
+     0x77, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20,
+     0x01, 0x28, 0x08, 0x52, 0x10, 0x7a, 0x79, 0x67, 0x6f, 0x74, 0x65, 0x4e,
+     0x65, 0x77, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x43, 0x0a,
+     0x1e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x68, 0x6f,
+     0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
+     0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28,
+     0x0d, 0x52, 0x1b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x48,
+     0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
+     0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x0e, 0x74, 0x6f,
+     0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+     0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72,
+     0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54, 0x6f,
+     0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x0c,
+     0x74, 0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65,
+     0x42, 0x02, 0x48, 0x03, 0x0a, 0xcb, 0x05, 0x0a, 0x3a, 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, 0x5f, 0x73, 0x74, 0x61, 0x74,
+     0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x22, 0xf7, 0x04, 0x0a, 0x18, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f,
+     0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
+     0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x5e, 0x0a, 0x0e, 0x69, 0x6e, 0x73,
+     0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18,
+     0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43,
+     0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 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, 0x1b, 0x0a, 0x05, 0x46, 0x72, 0x61,
+     0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+     0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x1a, 0x51,
+     0x0a, 0x08, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x12, 0x45,
+     0x0a, 0x05, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28,
+     0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70,
+     0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
+     0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x46, 0x72, 0x61,
+     0x6d, 0x65, 0x52, 0x05, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x1a, 0xe3, 0x01,
+     0x0a, 0x0d, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74,
+     0x61, 0x74, 0x73, 0x12, 0x4e, 0x0a, 0x08, 0x63, 0x61, 0x6c, 0x6c, 0x73,
+     0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66,
+     0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53,
+     0x74, 0x61, 0x74, 0x73, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74,
+     0x65, 0x52, 0x08, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x12,
+     0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75,
+     0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f,
+     0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b,
+     0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18,
+     0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c,
+     0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x6c,
+     0x74, 0x61, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x75,
+     0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f,
+     0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x0a, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x42, 0x79, 0x74, 0x65, 0x73, 0x1a,
+     0xa4, 0x01, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
+     0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64,
+     0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12,
+     0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e,
+     0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70,
+     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5e,
+     0x0a, 0x0e, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x5f, 0x73,
+     0x74, 0x61, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37,
      0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
      0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f,
      0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
-     0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
-     0x05, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x1a, 0xe3, 0x01, 0x0a, 0x0d, 0x43,
-     0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73,
-     0x12, 0x4e, 0x0a, 0x08, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
-     0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74,
-     0x73, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x52, 0x08,
-     0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b,
-     0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18,
-     0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c,
-     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74,
-     0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74,
-     0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f,
-     0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
-     0x0a, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
-     0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x62, 0x79, 0x74,
-     0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65,
-     0x6c, 0x74, 0x61, 0x42, 0x79, 0x74, 0x65, 0x73, 0x1a, 0xa4, 0x01, 0x0a,
-     0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61,
-     0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20,
-     0x01, 0x28, 0x0d, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c,
-     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63,
-     0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5e, 0x0a, 0x0e, 0x63,
-     0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74,
-     0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
-     0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61,
-     0x74, 0x73, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53,
-     0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69,
-     0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a,
-     0x85, 0x02, 0x0a, 0x2b, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69,
+     0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x63, 0x61, 0x6c,
+     0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x42, 0x02,
+     0x48, 0x03, 0x0a, 0x85, 0x02, 0x0a, 0x2b, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
+     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x61, 0x63, 0x6b,
+     0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xc0, 0x01, 0x0a, 0x12,
+     0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61,
+     0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x08, 0x70, 0x61,
+     0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+     0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+     0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73,
+     0x74, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x08, 0x70,
+     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x1a, 0x61, 0x0a, 0x07, 0x50,
+     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61,
+     0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+     0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
+     0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12,
+     0x21, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63,
+     0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x76,
+     0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x02,
+     0x48, 0x03, 0x0a, 0xf6, 0x0d, 0x0a, 0x1e, 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, 0x2a, 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, 0x29, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
      0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
-     0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
-     0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x22, 0xc0, 0x01, 0x0a, 0x12, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c,
-     0x69, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61,
-     0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
-     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x2e, 0x50,
-     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b,
-     0x61, 0x67, 0x65, 0x73, 0x1a, 0x61, 0x0a, 0x07, 0x50, 0x61, 0x63, 0x6b,
-     0x61, 0x67, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61,
-     0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-     0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61,
-     0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20,
-     0x01, 0x28, 0x03, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c,
-     0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65,
-     0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x76, 0x65, 0x72, 0x73,
-     0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a,
-     0xf6, 0x0d, 0x0a, 0x1e, 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, 0x2a, 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,
+     0x72, 0x6f, 0x69, 0x64, 0x2f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x74,
+     0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 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, 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, 0x2d, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
+     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 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,
      0x29, 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, 0x29, 0x70, 0x65, 0x72, 0x66,
+     0x64, 0x2f, 0x6c, 0x6d, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2e, 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, 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, 0x2d, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-     0x5f, 0x67, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x1a, 0x29, 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, 0x29, 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, 0x2e, 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, 0x2d, 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, 0x3a, 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, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x1a, 0x2b, 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, 0x22,
-     0xd2, 0x01, 0x0a, 0x0d, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74,
-     0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x50, 0x0a, 0x11, 0x65, 0x72, 0x72,
-     0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x65, 0x6e, 0x74,
-     0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70,
+     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, 0x2d, 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, 0x3a, 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, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2b, 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, 0x22, 0xd2, 0x01, 0x0a, 0x0d, 0x54, 0x72, 0x61, 0x63, 0x65,
+     0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x50, 0x0a, 0x11,
+     0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f,
+     0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
+     0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d,
+     0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x45, 0x6e, 0x74, 0x72,
+     0x79, 0x52, 0x0f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74,
+     0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x72,
+     0x61, 0x63, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+     0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x74,
+     0x72, 0x61, 0x63, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+     0x4e, 0x73, 0x1a, 0x43, 0x0a, 0x05, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
+     0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69,
+     0x64, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x69, 0x64,
+     0x78, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
+     0xe9, 0x07, 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,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
+     0x72, 0x6f, 0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x4d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+     0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e,
+     0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x63, 0x70, 0x75, 0x18, 0x06, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
+     0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43,
+     0x70, 0x75, 0x12, 0x45, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+     0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69,
+     0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65,
+     0x6d, 0x12, 0x5c, 0x0a, 0x11, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x75, 0x6e, 0x61, 0x67, 0x67, 0x18, 0x0b,
+     0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
+     0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64,
+     0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x12,
+     0x55, 0x0a, 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70,
+     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18,
+     0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 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, 0x52, 0x12, 0x61, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69,
+     0x73, 0x74, 0x12, 0x5b, 0x0a, 0x16, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72,
+     0x6f, 0x77, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25,
+     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74,
+     0x68, 0x52, 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72,
+     0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x12,
+     0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x69,
+     0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70,
      0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61,
-     0x64, 0x61, 0x74, 0x61, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f,
-     0x65, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x45, 0x6e,
-     0x74, 0x72, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x63, 0x65,
-     0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x73,
-     0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x74, 0x72, 0x61, 0x63,
-     0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x73, 0x1a,
-     0x43, 0x0a, 0x05, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04,
-     0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
-     0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x78, 0x18,
-     0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x69, 0x64, 0x78, 0x12, 0x14,
-     0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xe9, 0x07, 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,
+     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f,
+     0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64,
+     0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0b, 0x61,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6d, 0x6b, 0x18, 0x08,
+     0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74,
+     0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x4c, 0x6d, 0x6b, 0x12, 0x4d, 0x0a, 0x10, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+     0x69, 0x64, 0x5f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18,
+     0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72,
+     0x52, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+     0x69, 0x64, 0x50, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4e,
+     0x0a, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x73, 0x74,
+     0x61, 0x72, 0x74, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
      0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
      0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x52, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x42,
-     0x61, 0x74, 0x74, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x5f, 0x63, 0x70, 0x75, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
-     0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52,
-     0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x12,
-     0x45, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6d,
-     0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65,
-     0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a,
-     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x12, 0x5c,
-     0x0a, 0x11, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6d, 0x65,
-     0x6d, 0x5f, 0x75, 0x6e, 0x61, 0x67, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61,
-     0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x4d, 0x65, 0x6d, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x12, 0x55, 0x0a, 0x14,
-     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70, 0x61, 0x63, 0x6b,
-     0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0c, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x23, 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, 0x52, 0x12, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12,
-     0x5b, 0x0a, 0x16, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x77, 0x74,
-     0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65,
+     0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x52, 0x0e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
+     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x68, 0x0a, 0x1b, 0x68, 0x65,
+     0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63,
+     0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74,
+     0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x65,
      0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f,
-     0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x52, 0x14,
-     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x12, 0x42, 0x0a, 0x0b,
-     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x69, 0x6f, 0x6e, 0x18,
-     0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x49, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6d, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b,
-     0x12, 0x4d, 0x0a, 0x10, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f,
-     0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x07, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69,
-     0x6c, 0x73, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
-     0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0f, 0x61,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74,
-     0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74,
-     0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52,
-     0x0e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72,
-     0x74, 0x75, 0x70, 0x12, 0x68, 0x0a, 0x1b, 0x68, 0x65, 0x61, 0x70, 0x5f,
-     0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c,
-     0x73, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x0e,
-     0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48,
-     0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61,
-     0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52,
-     0x18, 0x68, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
-     0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74,
-     0x73, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x6d,
-     0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63,
-     0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x74,
+     0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
+     0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61,
+     0x74, 0x73, 0x52, 0x18, 0x68, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66,
+     0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53,
+     0x74, 0x61, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x63,
+     0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03,
+     0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54,
      0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
-     0x2a, 0x06, 0x08, 0xc2, 0x03, 0x10, 0xf4, 0x03, 0x2a, 0x06, 0x08, 0xf4,
-     0x03, 0x10, 0xe9, 0x07, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04,
-     0x08, 0x0d, 0x10, 0x0e, 0x42, 0x02, 0x48, 0x03}};
+     0x52, 0x0d, 0x74, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64,
+     0x61, 0x74, 0x61, 0x2a, 0x06, 0x08, 0xc2, 0x03, 0x10, 0xf4, 0x03, 0x2a,
+     0x06, 0x08, 0xf4, 0x03, 0x10, 0xe9, 0x07, 0x4a, 0x04, 0x08, 0x04, 0x10,
+     0x05, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x42, 0x02, 0x48, 0x03}};
 
 }  // namespace perfetto
 
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index 442153a..930fb13 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -48,6 +48,7 @@
 #include "perfetto/trace/android/android_log.pbzero.h"
 #include "perfetto/trace/android/packages_list.pbzero.h"
 #include "perfetto/trace/chrome/chrome_benchmark_metadata.pbzero.h"
+#include "perfetto/trace/chrome/chrome_trace_event.pbzero.h"
 #include "perfetto/trace/clock_snapshot.pbzero.h"
 #include "perfetto/trace/ftrace/ftrace.pbzero.h"
 #include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
@@ -254,6 +255,8 @@
           context->storage->InternString("task.posted_from.file_name")),
       task_function_name_args_key_id_(
           context->storage->InternString("task.posted_from.function_name")),
+      raw_chrome_metadata_event_id_(
+          context->storage->InternString("chrome_event.metadata")),
       raw_legacy_event_id_(
           context->storage->InternString("track_event.legacy_event")),
       legacy_event_category_key_id_(
@@ -430,6 +433,10 @@
     ParseChromeBenchmarkMetadata(packet.chrome_benchmark_metadata());
   }
 
+  if (packet.has_chrome_events()) {
+    ParseChromeEvents(packet.chrome_events());
+  }
+
   if (packet.has_perfetto_metatrace()) {
     ParseMetatraceEvent(ts, packet.perfetto_metatrace());
   }
@@ -1215,11 +1222,13 @@
   int64_t clock_realtime = 0;
   for (auto it = evt.clocks(); it; ++it) {
     protos::pbzero::ClockSnapshot::Clock::Decoder clk(it->data(), it->size());
-    if (clk.type() == protos::pbzero::ClockSnapshot::Clock::BOOTTIME) {
+    if (clk.clock_id() == protos::pbzero::ClockSnapshot::Clock::BOOTTIME) {
       clock_boottime = static_cast<int64_t>(clk.timestamp());
-    } else if (clk.type() == protos::pbzero::ClockSnapshot::Clock::REALTIME) {
+    } else if (clk.clock_id() ==
+               protos::pbzero::ClockSnapshot::Clock::REALTIME) {
       clock_realtime = static_cast<int64_t>(clk.timestamp());
-    } else if (clk.type() == protos::pbzero::ClockSnapshot::Clock::MONOTONIC) {
+    } else if (clk.clock_id() ==
+               protos::pbzero::ClockSnapshot::Clock::MONOTONIC) {
       clock_monotonic = static_cast<int64_t>(clk.timestamp());
     }
   }
@@ -1549,8 +1558,8 @@
 
   // TODO(eseckler): This legacy event field will eventually be replaced by
   // fields in TrackEvent itself.
-  if (PERFETTO_UNLIKELY(!legacy_event.has_phase())) {
-    PERFETTO_ELOG("TrackEvent without phase");
+  if (PERFETTO_UNLIKELY(!event.type() && !legacy_event.has_phase())) {
+    PERFETTO_ELOG("TrackEvent without type or phase");
     return;
   }
 
@@ -1580,6 +1589,7 @@
         sequence_state->GetInternedDataMap<protos::pbzero::EventCategory>();
     auto cat_view_it = map->find(category_iids[0]);
     if (cat_view_it == map->end()) {
+      context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
       PERFETTO_ELOG("Could not find category interning entry for ID %" PRIu64,
                     category_iids[0]);
     } else {
@@ -1605,6 +1615,7 @@
     for (uint64_t iid : category_iids) {
       auto cat_view_it = map->find(iid);
       if (cat_view_it == map->end()) {
+        context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
         PERFETTO_ELOG("Could not find category interning entry for ID %" PRIu64,
                       iid);
         continue;
@@ -1628,6 +1639,7 @@
         sequence_state->GetInternedDataMap<protos::pbzero::LegacyEventName>();
     auto name_view_it = map->find(legacy_event.name_iid());
     if (name_view_it == map->end()) {
+      context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
       PERFETTO_ELOG("Could not find event name interning entry for ID %" PRIu64,
                     legacy_event.name_iid());
     } else {
@@ -1678,7 +1690,23 @@
     id_scope = storage->InternString(legacy_event.id_scope());
   }
 
-  int32_t phase = legacy_event.phase();
+  int32_t phase = 0;
+  if (legacy_event.has_phase()) {
+    phase = legacy_event.phase();
+  } else {
+    switch (event.type()) {
+      case protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN:
+        phase = 'B';
+        break;
+      case protos::pbzero::TrackEvent::TYPE_SLICE_END:
+        phase = 'E';
+        break;
+      default:
+        PERFETTO_FATAL("unexpected event type %d", event.type());
+        return;
+    }
+  }
+
   switch (static_cast<char>(phase)) {
     case 'B': {  // TRACE_EVENT_PHASE_BEGIN.
       auto opt_slice_id = slice_tracker->Begin(
@@ -1998,6 +2026,7 @@
       sequence_state->GetInternedDataMap<protos::pbzero::DebugAnnotationName>();
   auto name_view_it = map->find(iid);
   if (name_view_it == map->end()) {
+    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
     PERFETTO_ELOG(
         "Could not find debug annotation name interning entry for ID %" PRIu64,
         iid);
@@ -2127,6 +2156,7 @@
       sequence_state->GetInternedDataMap<protos::pbzero::SourceLocation>();
   auto location_view_it = map->find(iid);
   if (location_view_it == map->end()) {
+    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
     PERFETTO_ELOG(
         "Could not find source location interning entry for ID %" PRIu64, iid);
     return;
@@ -2204,6 +2234,39 @@
   }
 }
 
+void ProtoTraceParser::ParseChromeEvents(ConstBytes blob) {
+  TraceStorage* storage = context_->storage.get();
+  protos::pbzero::ChromeEventBundle::Decoder bundle(blob.data, blob.size);
+  if (bundle.has_metadata()) {
+    ArgsTracker args(context_);
+    RowId row_id = storage->mutable_raw_events()->AddRawEvent(
+        0, raw_chrome_metadata_event_id_, 0, 0);
+
+    // Metadata is proxied via a special event in the raw table to JSON export.
+    for (auto it = bundle.metadata(); it; ++it) {
+      protos::pbzero::ChromeMetadata::Decoder metadata(it->as_bytes().data,
+                                                       it->as_bytes().size);
+      StringId name_id = storage->InternString(metadata.name());
+      Variadic value;
+      if (metadata.has_string_value()) {
+        value =
+            Variadic::String(storage->InternString(metadata.string_value()));
+      } else if (metadata.has_int_value()) {
+        value = Variadic::Integer(metadata.int_value());
+      } else if (metadata.has_bool_value()) {
+        value = Variadic::Integer(metadata.bool_value());
+      } else if (metadata.has_json_value()) {
+        value = Variadic::Json(storage->InternString(metadata.json_value()));
+      } else {
+        PERFETTO_FATAL("Empty ChromeMetadata message");
+      }
+      args.AddArg(row_id, name_id, name_id, value);
+    }
+  }
+
+  // TODO(khokhlov): parse legacy_ftrace_output and legacy_json_trace.
+}
+
 void ProtoTraceParser::ParseMetatraceEvent(int64_t ts, ConstBytes blob) {
   protos::pbzero::PerfettoMetatrace::Decoder event(blob.data, blob.size);
   auto utid = context_->process_tracker->GetOrCreateThread(event.thread_id());
diff --git a/src/trace_processor/proto_trace_parser.h b/src/trace_processor/proto_trace_parser.h
index d7399a7..43e3d6e 100644
--- a/src/trace_processor/proto_trace_parser.h
+++ b/src/trace_processor/proto_trace_parser.h
@@ -128,6 +128,7 @@
       ArgsTracker* args_tracker,
       RowId row);
   void ParseChromeBenchmarkMetadata(ConstBytes);
+  void ParseChromeEvents(ConstBytes);
   void ParseMetatraceEvent(int64_t ts, ConstBytes);
   void ParseGpuCounterEvent(int64_t ts, ConstBytes);
   void ParseGpuRenderStageEvent(int64_t ts, ConstBytes);
@@ -167,6 +168,7 @@
   const StringId metatrace_id_;
   const StringId task_file_name_args_key_id_;
   const StringId task_function_name_args_key_id_;
+  const StringId raw_chrome_metadata_event_id_;
   const StringId raw_legacy_event_id_;
   const StringId legacy_event_category_key_id_;
   const StringId legacy_event_name_key_id_;
diff --git a/src/trace_processor/proto_trace_parser_unittest.cc b/src/trace_processor/proto_trace_parser_unittest.cc
index c67e98a..5cbc108 100644
--- a/src/trace_processor/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/proto_trace_parser_unittest.cc
@@ -33,6 +33,7 @@
 #include "perfetto/common/sys_stats_counters.pbzero.h"
 #include "perfetto/trace/android/packages_list.pbzero.h"
 #include "perfetto/trace/chrome/chrome_benchmark_metadata.pbzero.h"
+#include "perfetto/trace/chrome/chrome_trace_event.pbzero.h"
 #include "perfetto/trace/ftrace/ftrace.pbzero.h"
 #include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
 #include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
@@ -728,6 +729,71 @@
   EXPECT_EQ(storage_->thread_slices().thread_duration_ns()[1], 5000);
 }
 
+TEST_F(ProtoTraceParserTest, TrackEventWithoutInternedDataWithTypes) {
+  context_.sorter.reset(new TraceSorter(
+      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
+
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    packet->set_incremental_state_cleared(true);
+    auto* thread_desc = packet->set_thread_descriptor();
+    thread_desc->set_pid(15);
+    thread_desc->set_tid(16);
+    thread_desc->set_reference_timestamp_us(1000);
+    thread_desc->set_reference_thread_time_us(2000);
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);   // absolute: 1010.
+    event->set_thread_time_delta_us(5);  // absolute: 2005.
+    event->add_category_iids(1);
+    event->set_type(protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);   // absolute: 1020.
+    event->set_thread_time_delta_us(5);  // absolute: 2010.
+    event->add_category_iids(1);
+    event->set_type(protos::pbzero::TrackEvent::TYPE_SLICE_END);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+  }
+
+  Tokenize();
+
+  EXPECT_CALL(*process_, UpdateThread(16, 15))
+      .Times(2)
+      .WillRepeatedly(Return(1));
+
+  MockArgsTracker args(&context_);
+
+  InSequence in_sequence;  // Below slices should be sorted by timestamp.
+  EXPECT_CALL(*slice_, Begin(1010000, 1, RefType::kRefUtid, 0, 0, _))
+      .WillOnce(DoAll(
+          InvokeArgument<5>(
+              &args, TraceStorage::CreateRowId(TableId::kNestableSlices, 0u)),
+          Return(0u)));
+  EXPECT_CALL(*slice_, End(1020000, 1, RefType::kRefUtid, 0, 0, _))
+      .WillOnce(DoAll(
+          InvokeArgument<5>(
+              &args, TraceStorage::CreateRowId(TableId::kNestableSlices, 0u)),
+          Return(0u)));
+
+  context_.sorter->ExtractEventsForced();
+
+  EXPECT_EQ(storage_->thread_slices().slice_count(), 1u);
+  EXPECT_EQ(storage_->thread_slices().slice_ids()[0], 0u);
+  EXPECT_EQ(storage_->thread_slices().thread_timestamp_ns()[0], 2005000);
+  EXPECT_EQ(storage_->thread_slices().thread_duration_ns()[0], 5000);
+}
+
 TEST_F(ProtoTraceParserTest, TrackEventWithInternedData) {
   context_.sorter.reset(new TraceSorter(
       &context_, std::numeric_limits<int64_t>::max() /*window size*/));
@@ -1671,6 +1737,44 @@
   EXPECT_TRUE(HasArg(1u, 5u, Variadic::UnsignedInteger(10u)));
 }
 
+TEST_F(ProtoTraceParserTest, ParseChromeMetadataEventIntoRawTable) {
+  static const char kStringName[] = "string_name";
+  static const char kStringValue[] = "string_value";
+  static const char kIntName[] = "int_name";
+  static const int kIntValue = 123;
+
+  context_.sorter.reset(new TraceSorter(
+      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
+
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* bundle = packet->set_chrome_events();
+    auto* metadata = bundle->add_metadata();
+    metadata->set_name(kStringName);
+    metadata->set_string_value(kStringValue);
+    metadata = bundle->add_metadata();
+    metadata->set_name(kIntName);
+    metadata->set_int_value(kIntValue);
+  }
+
+  Tokenize();
+  context_.sorter->ExtractEventsForced();
+
+  // Verify raw_events and args contents.
+  const auto& raw_events = storage_->raw_events();
+  EXPECT_EQ(raw_events.raw_event_count(), 1u);
+  EXPECT_EQ(raw_events.name_ids()[0],
+            storage_->InternString("chrome_event.metadata"));
+  EXPECT_EQ(raw_events.arg_set_ids()[0], 1u);
+
+  EXPECT_EQ(storage_->args().args_count(), 2u);
+  EXPECT_TRUE(HasArg(1u, storage_->InternString(kStringName),
+                     Variadic::String(storage_->InternString(kStringValue))));
+  EXPECT_TRUE(HasArg(1u, storage_->InternString(kIntName),
+                     Variadic::Integer(kIntValue)));
+}
+
 TEST_F(ProtoTraceParserTest, LoadChromeBenchmarkMetadata) {
   static const char kName[] = "name";
   static const char kTag1[] = "tag1";
diff --git a/src/trace_processor/proto_trace_tokenizer.cc b/src/trace_processor/proto_trace_tokenizer.cc
index fbbd9b4..1fd4b28 100644
--- a/src/trace_processor/proto_trace_tokenizer.cc
+++ b/src/trace_processor/proto_trace_tokenizer.cc
@@ -18,7 +18,10 @@
 
 #include <string>
 
+#include <zlib.h>
+
 #include "perfetto/base/logging.h"
+#include "perfetto/ext/base/optional.h"
 #include "perfetto/ext/base/utils.h"
 #include "perfetto/protozero/proto_decoder.h"
 #include "perfetto/protozero/proto_utils.h"
@@ -50,6 +53,9 @@
 
 namespace {
 
+constexpr uint8_t kTracePacketTag =
+    MakeTagLengthDelimited(protos::pbzero::Trace::kPacketFieldNumber);
+
 template <typename MessageType>
 void InternMessage(TraceProcessorContext* context,
                    ProtoIncrementalState::PacketSequenceState* state,
@@ -82,6 +88,33 @@
                           message_size) == 0));
 }
 
+TraceBlobView Decompress(TraceBlobView input) {
+  uint8_t out[4096];
+  std::string s;
+
+  z_stream stream{};
+  stream.next_in = const_cast<uint8_t*>(input.data());
+  stream.avail_in = static_cast<unsigned int>(input.length());
+
+  if (inflateInit(&stream) != Z_OK)
+    return TraceBlobView(nullptr, 0, 0);
+
+  int ret;
+  do {
+    stream.next_out = out;
+    stream.avail_out = sizeof(out);
+    ret = inflate(&stream, Z_NO_FLUSH);
+    if (ret != Z_STREAM_END && ret != Z_OK)
+      return TraceBlobView(nullptr, 0, 0);
+    s.append(reinterpret_cast<char*>(out), sizeof(out) - stream.avail_out);
+  } while (ret != Z_STREAM_END);
+  inflateEnd(&stream);
+
+  std::unique_ptr<uint8_t[]> output(new uint8_t[s.size()]);
+  memcpy(output.get(), s.data(), s.size());
+  return TraceBlobView(std::move(output), 0, s.size());
+}
+
 }  // namespace
 
 ProtoTraceTokenizer::ProtoTraceTokenizer(TraceProcessorContext* ctx)
@@ -105,8 +138,6 @@
 
     // At this point we have enough data in |partial_buf_| to read at least the
     // field header and know the size of the next TracePacket.
-    constexpr uint8_t kTracePacketTag =
-        MakeTagLengthDelimited(protos::pbzero::Trace::kPacketFieldNumber);
     const uint8_t* pos = &partial_buf_[0];
     uint8_t proto_field_tag = *pos;
     uint64_t field_size = 0;
@@ -221,6 +252,34 @@
     return util::OkStatus();
   }
 
+  if (decoder.has_compressed_packets()) {
+    protozero::ConstBytes field = decoder.compressed_packets();
+    const size_t field_off = packet.offset_of(field.data);
+    TraceBlobView compressed_packets = packet.slice(field_off, field.size);
+    TraceBlobView packets = Decompress(std::move(compressed_packets));
+
+    const uint8_t* start = packets.data();
+    const uint8_t* end = packets.data() + packets.length();
+    const uint8_t* ptr = start;
+    while ((end - ptr) > 2) {
+      const uint8_t* packet_start = ptr;
+      if (PERFETTO_UNLIKELY(*ptr != kTracePacketTag))
+        return util::ErrStatus("Expected TracePacket tag");
+      uint64_t packet_size = 0;
+      ptr = ParseVarInt(++ptr, end, &packet_size);
+      size_t packet_offset = static_cast<size_t>(ptr - start);
+      ptr += packet_size;
+      if (PERFETTO_UNLIKELY((ptr - packet_start) < 2 || ptr > end))
+        return util::ErrStatus("Invalid packet size");
+      util::Status status = ParsePacket(
+          packets.slice(packet_offset, static_cast<size_t>(packet_size)));
+      if (PERFETTO_UNLIKELY(!status.ok()))
+        return status;
+    }
+
+    return util::OkStatus();
+  }
+
   if (decoder.has_trace_config()) {
     auto config = decoder.trace_config();
     protos::pbzero::TraceConfig::Decoder trace_config(config.data, config.size);
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 710c770..70f18d2 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -33,9 +33,7 @@
 #include "src/trace_processor/counter_definitions_table.h"
 #include "src/trace_processor/counter_values_table.h"
 #include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/fuchsia_trace_parser.h"
-#include "src/trace_processor/fuchsia_trace_tokenizer.h"
-#include "src/trace_processor/gzip_trace_parser.h"
+#include "src/trace_processor/forwarding_trace_parser.h"
 #include "src/trace_processor/heap_profile_allocation_table.h"
 #include "src/trace_processor/heap_profile_callsite_table.h"
 #include "src/trace_processor/heap_profile_frame_table.h"
@@ -49,7 +47,6 @@
 #include "src/trace_processor/metrics/sql_metrics.h"
 #include "src/trace_processor/process_table.h"
 #include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/proto_trace_parser.h"
 #include "src/trace_processor/proto_trace_tokenizer.h"
 #include "src/trace_processor/raw_table.h"
 #include "src/trace_processor/sched_slice_table.h"
@@ -77,8 +74,6 @@
 #if PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD) || \
     PERFETTO_BUILD_WITH_CHROMIUM
 #include "src/trace_processor/export_json.h"
-#include "src/trace_processor/json_trace_parser.h"
-#include "src/trace_processor/json_trace_tokenizer.h"
 #endif
 
 // In Android and Chromium tree builds, we don't have the percentile module.
@@ -94,12 +89,6 @@
 namespace trace_processor {
 namespace {
 
-std::string RemoveWhitespace(const std::string& input) {
-  std::string str(input);
-  str.erase(std::remove_if(str.begin(), str.end(), ::isspace), str.end());
-  return str;
-}
-
 void InitializeSqlite(sqlite3* db) {
   char* error = nullptr;
   sqlite3_exec(db, "PRAGMA temp_store=2", 0, 0, &error);
@@ -265,48 +254,8 @@
   }
 }
 
-// Fuchsia traces have a magic number as documented here:
-// https://fuchsia.googlesource.com/fuchsia/+/HEAD/docs/development/tracing/trace-format/README.md#magic-number-record-trace-info-type-0
-constexpr uint64_t kFuchsiaMagicNumber = 0x0016547846040010;
-
 }  // namespace
 
-TraceType GuessTraceType(const uint8_t* data, size_t size) {
-  if (size == 0)
-    return kUnknownTraceType;
-  std::string start(reinterpret_cast<const char*>(data),
-                    std::min<size_t>(size, 20));
-  std::string start_minus_white_space = RemoveWhitespace(start);
-  if (base::StartsWith(start_minus_white_space, "{\"traceEvents\":["))
-    return kJsonTraceType;
-  if (base::StartsWith(start_minus_white_space, "[{"))
-    return kJsonTraceType;
-  if (size >= 8) {
-    uint64_t first_word = *reinterpret_cast<const uint64_t*>(data);
-    if (first_word == kFuchsiaMagicNumber)
-      return kFuchsiaTraceType;
-  }
-
-  // Systrace with header but no leading HTML.
-  if (base::StartsWith(start, "# tracer"))
-    return kSystraceTraceType;
-
-  // Systrace with leading HTML.
-  if (base::StartsWith(start, "<!DOCTYPE html>") ||
-      base::StartsWith(start, "<html>"))
-    return kSystraceTraceType;
-
-  // Systrace with no header or leading HTML.
-  if (base::StartsWith(start, " "))
-    return kSystraceTraceType;
-
-  // Ctrace is GZIPed systrace with no headers.
-  if (base::StartsWith(start, "TRACE:"))
-    return kCtraceTraceType;
-
-  return kProtoTraceType;
-}
-
 TraceProcessorImpl::TraceProcessorImpl(const Config& cfg) {
   sqlite3* db = nullptr;
   PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
@@ -368,58 +317,8 @@
   if (unrecoverable_parse_error_)
     return util::ErrStatus(
         "Failed unrecoverably while parsing in a previous Parse call");
-
-  // If this is the first Parse() call, guess the trace type and create the
-  // appropriate parser.
-  if (!context_.chunk_reader) {
-    TraceType trace_type;
-    {
-      auto scoped_trace = context_.storage->TraceExecutionTimeIntoStats(
-          stats::guess_trace_type_duration_ns);
-      trace_type = GuessTraceType(data.get(), size);
-    }
-    switch (trace_type) {
-      case kJsonTraceType: {
-        PERFETTO_DLOG("Legacy JSON trace detected");
-#if PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD) || \
-    PERFETTO_BUILD_WITH_CHROMIUM
-        context_.chunk_reader.reset(new JsonTraceTokenizer(&context_));
-        // JSON traces have no guarantees about the order of events in them.
-        int64_t window_size_ns = std::numeric_limits<int64_t>::max();
-        context_.sorter.reset(new TraceSorter(&context_, window_size_ns));
-        context_.parser.reset(new JsonTraceParser(&context_));
-#else
-        PERFETTO_FATAL("JSON traces not supported.");
-#endif
-        break;
-      }
-      case kProtoTraceType: {
-        // This will be reduced once we read the trace config and we see flush
-        // period being set.
-        int64_t window_size_ns = std::numeric_limits<int64_t>::max();
-        context_.chunk_reader.reset(new ProtoTraceTokenizer(&context_));
-        context_.sorter.reset(new TraceSorter(&context_, window_size_ns));
-        context_.parser.reset(new ProtoTraceParser(&context_));
-        break;
-      }
-      case kFuchsiaTraceType: {
-        // Fuschia traces can have massively out of order events.
-        int64_t window_size_ns = std::numeric_limits<int64_t>::max();
-        context_.chunk_reader.reset(new FuchsiaTraceTokenizer(&context_));
-        context_.sorter.reset(new TraceSorter(&context_, window_size_ns));
-        context_.parser.reset(new FuchsiaTraceParser(&context_));
-        break;
-      }
-      case kSystraceTraceType:
-        context_.chunk_reader.reset(new SystraceTraceParser(&context_));
-        break;
-      case kCtraceTraceType:
-        context_.chunk_reader.reset(new GzipTraceParser(&context_));
-        break;
-      case kUnknownTraceType:
-        return util::ErrStatus("Unknown trace type provided");
-    }
-  }
+  if (!context_.chunk_reader)
+    context_.chunk_reader.reset(new ForwardingTraceParser(&context_));
 
   auto scoped_trace = context_.storage->TraceExecutionTimeIntoStats(
       stats::parse_trace_duration_ns);
diff --git a/src/trace_processor/trace_processor_impl.h b/src/trace_processor/trace_processor_impl.h
index e9c3435..0ef2d7e 100644
--- a/src/trace_processor/trace_processor_impl.h
+++ b/src/trace_processor/trace_processor_impl.h
@@ -36,17 +36,6 @@
 
 namespace trace_processor {
 
-enum TraceType {
-  kUnknownTraceType,
-  kProtoTraceType,
-  kJsonTraceType,
-  kFuchsiaTraceType,
-  kSystraceTraceType,
-  kCtraceTraceType,
-};
-
-TraceType GuessTraceType(const uint8_t* data, size_t size);
-
 // Coordinates the loading of traces from an arbitrary source and allows
 // execution of SQL queries on the events in these traces.
 class TraceProcessorImpl : public TraceProcessor {
diff --git a/src/tracing/api_integrationtest.cc b/src/tracing/api_integrationtest.cc
index 7e6087f..c696582 100644
--- a/src/tracing/api_integrationtest.cc
+++ b/src/tracing/api_integrationtest.cc
@@ -88,6 +88,8 @@
   MockDataSource* instance;
   perfetto::DataSourceConfig config;
   bool handle_stop_asynchronously = false;
+  std::function<void()> on_start_callback;
+  std::function<void()> on_stop_callback;
   std::function<void()> async_stop_closure;
 };
 
@@ -182,6 +184,8 @@
 
 void MockDataSource::OnStart(const StartArgs&) {
   EXPECT_NE(handle_, nullptr);
+  if (handle_->on_start_callback)
+    handle_->on_start_callback();
   handle_->on_start.Notify();
 }
 
@@ -189,6 +193,8 @@
   EXPECT_NE(handle_, nullptr);
   if (handle_->handle_stop_asynchronously)
     handle_->async_stop_closure = args.HandleStopAsynchronously();
+  if (handle_->on_stop_callback)
+    handle_->on_stop_callback();
   handle_->on_stop.Notify();
 }
 
@@ -441,6 +447,61 @@
   EXPECT_EQ(trace_lambda_calls, 1);
 }
 
+// Regression test for b/139110180. Checks that GetDataSourceLocked() can be
+// called from OnStart() and OnStop() callbacks without deadlocking.
+TEST_F(PerfettoApiTest, GetDataSourceLockedFromCallbacks) {
+  auto* data_source = &data_sources_["my_data_source"];
+
+  // Setup the trace config.
+  perfetto::TraceConfig cfg;
+  cfg.set_duration_ms(1);
+  cfg.add_buffers()->set_size_kb(1024);
+  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+  ds_cfg->set_name("my_data_source");
+
+  // Create a new trace session.
+  auto* tracing_session = NewTrace(cfg);
+
+  data_source->on_start_callback = [] {
+    MockDataSource::Trace([](MockDataSource::TraceContext ctx) {
+      ctx.NewTracePacket()->set_for_testing()->set_str("on-start");
+      auto ds = ctx.GetDataSourceLocked();
+      ASSERT_TRUE(!!ds);
+      ctx.NewTracePacket()->set_for_testing()->set_str("on-start-locked");
+    });
+  };
+
+  data_source->on_stop_callback = [] {
+    MockDataSource::Trace([](MockDataSource::TraceContext ctx) {
+      ctx.NewTracePacket()->set_for_testing()->set_str("on-stop");
+      auto ds = ctx.GetDataSourceLocked();
+      ASSERT_TRUE(!!ds);
+      ctx.NewTracePacket()->set_for_testing()->set_str("on-stop-locked");
+      ctx.Flush();
+    });
+  };
+
+  tracing_session->get()->Start();
+  data_source->on_stop.Wait();
+  tracing_session->on_stop.Wait();
+
+  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+  ASSERT_GE(raw_trace.size(), 0u);
+
+  perfetto::protos::Trace trace;
+  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+  int packets_found = 0;
+  for (const auto& packet : trace.packet()) {
+    if (!packet.has_for_testing())
+      continue;
+    packets_found |= packet.for_testing().str() == "on-start" ? 1 : 0;
+    packets_found |= packet.for_testing().str() == "on-start-locked" ? 2 : 0;
+    packets_found |= packet.for_testing().str() == "on-stop" ? 4 : 0;
+    packets_found |= packet.for_testing().str() == "on-stop-locked" ? 8 : 0;
+  }
+  EXPECT_EQ(packets_found, 1 | 2 | 4 | 8);
+}
+
 }  // namespace
 
 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource);
diff --git a/src/tracing/core/shared_memory_arbiter_impl_unittest.cc b/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
index bffe662..5905ef8 100644
--- a/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
+++ b/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
@@ -44,7 +44,9 @@
   void ActivateTriggers(const std::vector<std::string>&) {}
   SharedMemory* shared_memory() const override { return nullptr; }
   size_t shared_buffer_page_size_kb() const override { return 0; }
-  std::unique_ptr<TraceWriter> CreateTraceWriter(BufferID) override {
+  std::unique_ptr<TraceWriter> CreateTraceWriter(
+      BufferID,
+      BufferExhaustedPolicy) override {
     return nullptr;
   }
   SharedMemoryArbiter* GetInProcessShmemArbiter() override { return nullptr; }
@@ -90,8 +92,7 @@
   static constexpr size_t kTotChunks = kNumPages * 14;
   SharedMemoryABI::Chunk chunks[kTotChunks];
   for (size_t i = 0; i < 14 * 2 + 2; i++) {
-    chunks[i] = arbiter_->GetNewChunk(
-        {}, SharedMemoryArbiter::BufferExhaustedPolicy::kStall);
+    chunks[i] = arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kStall);
     ASSERT_TRUE(chunks[i].is_valid());
   }
 
@@ -175,23 +176,21 @@
   static constexpr size_t kTotChunks = kNumPages;
   SharedMemoryABI::Chunk chunks[kTotChunks];
   for (size_t i = 0; i < kTotChunks; i++) {
-    chunks[i] = arbiter_->GetNewChunk(
-        {}, SharedMemoryArbiter::BufferExhaustedPolicy::kDrop);
+    chunks[i] = arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kDrop);
     ASSERT_TRUE(chunks[i].is_valid());
   }
 
   // SMB is exhausted, thus GetNewChunk() should return an invalid chunk. In
   // kStall mode, this would stall.
-  SharedMemoryABI::Chunk invalid_chunk = arbiter_->GetNewChunk(
-      {}, SharedMemoryArbiter::BufferExhaustedPolicy::kDrop);
+  SharedMemoryABI::Chunk invalid_chunk =
+      arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kDrop);
   ASSERT_FALSE(invalid_chunk.is_valid());
 
   // Returning the chunk is not enough to be able to reacquire it.
   PatchList ignored;
   arbiter_->ReturnCompletedChunk(std::move(chunks[0]), 0, &ignored);
 
-  invalid_chunk = arbiter_->GetNewChunk(
-      {}, SharedMemoryArbiter::BufferExhaustedPolicy::kDrop);
+  invalid_chunk = arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kDrop);
   ASSERT_FALSE(invalid_chunk.is_valid());
 
   // After releasing the chunk as free, we can reacquire it.
@@ -200,8 +199,7 @@
   ASSERT_TRUE(chunks[0].is_valid());
   arbiter_->shmem_abi_for_testing()->ReleaseChunkAsFree(std::move(chunks[0]));
 
-  chunks[0] = arbiter_->GetNewChunk(
-      {}, SharedMemoryArbiter::BufferExhaustedPolicy::kDrop);
+  chunks[0] = arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kDrop);
   ASSERT_TRUE(chunks[0].is_valid());
 }
 
diff --git a/src/tracing/core/startup_trace_writer.cc b/src/tracing/core/startup_trace_writer.cc
index 8f24990..d89b9a1 100644
--- a/src/tracing/core/startup_trace_writer.cc
+++ b/src/tracing/core/startup_trace_writer.cc
@@ -36,12 +36,11 @@
 
 static constexpr ChunkID kFirstChunkId = 0;
 
-SharedMemoryABI::Chunk NewChunk(
-    SharedMemoryArbiterImpl* arbiter,
-    WriterID writer_id,
-    ChunkID chunk_id,
-    bool fragmenting_packet,
-    SharedMemoryArbiter::BufferExhaustedPolicy buffer_exhausted_policy) {
+SharedMemoryABI::Chunk NewChunk(SharedMemoryArbiterImpl* arbiter,
+                                WriterID writer_id,
+                                ChunkID chunk_id,
+                                bool fragmenting_packet,
+                                BufferExhaustedPolicy buffer_exhausted_policy) {
   ChunkHeader::Packets packets = {};
   if (fragmenting_packet) {
     packets.count = 1;
@@ -133,15 +132,14 @@
 // commit before continuing with the remaining data.
 class LocalBufferCommitter {
  public:
-  LocalBufferCommitter(
-      std::unique_ptr<LocalBufferReader> local_buffer_reader,
-      std::unique_ptr<std::vector<uint32_t>> packet_sizes,
-      base::WeakPtr<SharedMemoryArbiterImpl> arbiter,
-      WriterID writer_id,
-      BufferID target_buffer,
-      size_t chunks_per_batch,
-      SharedMemoryArbiter::BufferExhaustedPolicy buffer_exhausted_policy,
-      SharedMemoryABI::Chunk first_chunk)
+  LocalBufferCommitter(std::unique_ptr<LocalBufferReader> local_buffer_reader,
+                       std::unique_ptr<std::vector<uint32_t>> packet_sizes,
+                       base::WeakPtr<SharedMemoryArbiterImpl> arbiter,
+                       WriterID writer_id,
+                       BufferID target_buffer,
+                       size_t chunks_per_batch,
+                       BufferExhaustedPolicy buffer_exhausted_policy,
+                       SharedMemoryABI::Chunk first_chunk)
       : local_buffer_reader_(std::move(local_buffer_reader)),
         packet_sizes_(std::move(packet_sizes)),
         arbiter_(arbiter),
@@ -340,7 +338,7 @@
   const WriterID writer_id_;
   const BufferID target_buffer_;
   const size_t chunks_per_batch_;
-  SharedMemoryArbiter::BufferExhaustedPolicy buffer_exhausted_policy_;
+  BufferExhaustedPolicy buffer_exhausted_policy_;
   SharedMemoryABI::Chunk cur_chunk_;
   // We receive the first chunk in the constructor, thus the next chunk will be
   // the second one.
@@ -354,7 +352,7 @@
 
 StartupTraceWriter::StartupTraceWriter(
     std::shared_ptr<StartupTraceWriterRegistryHandle> registry_handle,
-    SharedMemoryArbiter::BufferExhaustedPolicy buffer_exhausted_policy)
+    BufferExhaustedPolicy buffer_exhausted_policy)
     : registry_handle_(std::move(registry_handle)),
       buffer_exhausted_policy_(buffer_exhausted_policy),
       memory_buffer_(new protozero::ScatteredHeapBuffer()),
diff --git a/src/tracing/core/startup_trace_writer_registry.cc b/src/tracing/core/startup_trace_writer_registry.cc
index f60101f..ddbf31c 100644
--- a/src/tracing/core/startup_trace_writer_registry.cc
+++ b/src/tracing/core/startup_trace_writer_registry.cc
@@ -54,7 +54,7 @@
 
 std::unique_ptr<StartupTraceWriter>
 StartupTraceWriterRegistry::CreateUnboundTraceWriter(
-    SharedMemoryArbiter::BufferExhaustedPolicy buffer_exhausted_policy) {
+    BufferExhaustedPolicy buffer_exhausted_policy) {
   std::lock_guard<std::mutex> lock(lock_);
   PERFETTO_DCHECK(!arbiter_);  // Should only be called while unbound.
   std::unique_ptr<StartupTraceWriter> writer(
diff --git a/src/tracing/core/startup_trace_writer_unittest.cc b/src/tracing/core/startup_trace_writer_unittest.cc
index 2461aff..8383548 100644
--- a/src/tracing/core/startup_trace_writer_unittest.cc
+++ b/src/tracing/core/startup_trace_writer_unittest.cc
@@ -54,8 +54,8 @@
 
   std::unique_ptr<StartupTraceWriter> CreateUnboundWriter() {
     std::shared_ptr<StartupTraceWriterRegistryHandle> registry;
-    return std::unique_ptr<StartupTraceWriter>(new StartupTraceWriter(
-        registry, SharedMemoryArbiter::BufferExhaustedPolicy::kDrop));
+    return std::unique_ptr<StartupTraceWriter>(
+        new StartupTraceWriter(registry, BufferExhaustedPolicy::kDrop));
   }
 
   bool BindWriter(StartupTraceWriter* writer, size_t chunks_per_batch = 0) {
@@ -309,10 +309,10 @@
       new StartupTraceWriterRegistry());
 
   // Create unbound writers.
-  auto writer1 = registry->CreateUnboundTraceWriter(
-      SharedMemoryArbiter::BufferExhaustedPolicy::kDrop);
-  auto writer2 = registry->CreateUnboundTraceWriter(
-      SharedMemoryArbiter::BufferExhaustedPolicy::kDrop);
+  auto writer1 =
+      registry->CreateUnboundTraceWriter(BufferExhaustedPolicy::kDrop);
+  auto writer2 =
+      registry->CreateUnboundTraceWriter(BufferExhaustedPolicy::kDrop);
 
   EXPECT_EQ(2u, GetUnboundWriterCount(*registry));
 
@@ -410,8 +410,7 @@
   static constexpr size_t kTotChunks = kNumPages;
   SharedMemoryABI::Chunk chunks[kTotChunks];
   for (size_t i = 0; i < kTotChunks; i++) {
-    chunks[i] = arbiter_->GetNewChunk(
-        {}, SharedMemoryArbiter::BufferExhaustedPolicy::kDrop);
+    chunks[i] = arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kDrop);
     ASSERT_TRUE(chunks[i].is_valid());
   }
 
diff --git a/src/tracing/core/trace_buffer.cc b/src/tracing/core/trace_buffer.cc
index d78781a..7bb4664 100644
--- a/src/tracing/core/trace_buffer.cc
+++ b/src/tracing/core/trace_buffer.cc
@@ -844,10 +844,10 @@
   const uint8_t* next_packet = packet_data + packet_size;
   if (PERFETTO_UNLIKELY(next_packet <= packet_begin ||
                         next_packet > record_end)) {
-    // In SharedMemoryArbiter::BufferExhaustedPolicy::kDrop mode, TraceWriter
-    // may abort a fragmented packet by writing an invalid size in the last
-    // fragment's header. We should handle this case without recording an ABI
-    // violation (since Android R).
+    // In BufferExhaustedPolicy::kDrop mode, TraceWriter may abort a fragmented
+    // packet by writing an invalid size in the last fragment's header. We
+    // should handle this case without recording an ABI violation (since Android
+    // R).
     if (packet_size != SharedMemoryABI::kPacketSizeDropPacket) {
       stats_.set_abi_violations(stats_.abi_violations() + 1);
       PERFETTO_DCHECK(suppress_sanity_dchecks_for_testing_);
diff --git a/src/tracing/core/trace_config.cc b/src/tracing/core/trace_config.cc
index 88c90db..2cd12b3 100644
--- a/src/tracing/core/trace_config.cc
+++ b/src/tracing/core/trace_config.cc
@@ -67,7 +67,8 @@
          (allow_user_build_tracing_ == other.allow_user_build_tracing_) &&
          (unique_session_name_ == other.unique_session_name_) &&
          (compression_type_ == other.compression_type_) &&
-         (incident_report_config_ == other.incident_report_config_);
+         (incident_report_config_ == other.incident_report_config_) &&
+         (trace_uuid_ == other.trace_uuid_);
 }
 #pragma GCC diagnostic pop
 
@@ -192,6 +193,10 @@
       static_cast<decltype(compression_type_)>(proto.compression_type());
 
   incident_report_config_->FromProto(proto.incident_report_config());
+
+  static_assert(sizeof(trace_uuid_) == sizeof(proto.trace_uuid()),
+                "size mismatch");
+  trace_uuid_ = static_cast<decltype(trace_uuid_)>(proto.trace_uuid());
   unknown_fields_ = proto.unknown_fields();
 }
 
@@ -313,6 +318,11 @@
       static_cast<decltype(proto->compression_type())>(compression_type_));
 
   incident_report_config_->ToProto(proto->mutable_incident_report_config());
+
+  static_assert(sizeof(trace_uuid_) == sizeof(proto->trace_uuid()),
+                "size mismatch");
+  proto->set_trace_uuid(
+      static_cast<decltype(proto->trace_uuid())>(trace_uuid_));
   *(proto->mutable_unknown_fields()) = unknown_fields_;
 }
 
diff --git a/src/tracing/core/trace_writer_impl.cc b/src/tracing/core/trace_writer_impl.cc
index 18e951c..a8926ac 100644
--- a/src/tracing/core/trace_writer_impl.cc
+++ b/src/tracing/core/trace_writer_impl.cc
@@ -40,11 +40,10 @@
 uint8_t g_garbage_chunk[1024];
 }  // namespace
 
-TraceWriterImpl::TraceWriterImpl(
-    SharedMemoryArbiterImpl* shmem_arbiter,
-    WriterID id,
-    BufferID target_buffer,
-    SharedMemoryArbiter::BufferExhaustedPolicy buffer_exhausted_policy)
+TraceWriterImpl::TraceWriterImpl(SharedMemoryArbiterImpl* shmem_arbiter,
+                                 WriterID id,
+                                 BufferID target_buffer,
+                                 BufferExhaustedPolicy buffer_exhausted_policy)
     : shmem_arbiter_(shmem_arbiter),
       id_(id),
       target_buffer_(target_buffer),
diff --git a/src/tracing/core/trace_writer_impl.h b/src/tracing/core/trace_writer_impl.h
index 26afd95..7442b5e 100644
--- a/src/tracing/core/trace_writer_impl.h
+++ b/src/tracing/core/trace_writer_impl.h
@@ -18,6 +18,7 @@
 #define SRC_TRACING_CORE_TRACE_WRITER_IMPL_H_
 
 #include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/ext/tracing/core/buffer_exhausted_policy.h"
 #include "perfetto/ext/tracing/core/shared_memory_abi.h"
 #include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
 #include "perfetto/ext/tracing/core/trace_writer.h"
@@ -38,7 +39,7 @@
   TraceWriterImpl(SharedMemoryArbiterImpl*,
                   WriterID,
                   BufferID,
-                  SharedMemoryArbiter::BufferExhaustedPolicy);
+                  BufferExhaustedPolicy);
   ~TraceWriterImpl() override;
 
   // TraceWriter implementation. See documentation in trace_writer.h.
@@ -73,7 +74,7 @@
 
   // Whether GetNewChunk() should stall or return an invalid chunk if the SMB is
   // exhausted.
-  const SharedMemoryArbiter::BufferExhaustedPolicy buffer_exhausted_policy_;
+  const BufferExhaustedPolicy buffer_exhausted_policy_;
 
   // Monotonic (% wrapping) sequence id of the chunk. Together with the WriterID
   // this allows the Service to reconstruct the linear sequence of packets.
diff --git a/src/tracing/core/trace_writer_impl_unittest.cc b/src/tracing/core/trace_writer_impl_unittest.cc
index 68daa33..32ae83c 100644
--- a/src/tracing/core/trace_writer_impl_unittest.cc
+++ b/src/tracing/core/trace_writer_impl_unittest.cc
@@ -154,8 +154,8 @@
                                              task_runner_.get()));
 
   const BufferID kBufId = 42;
-  std::unique_ptr<TraceWriter> writer = arbiter_->CreateTraceWriter(
-      kBufId, SharedMemoryArbiter::BufferExhaustedPolicy::kDrop);
+  std::unique_ptr<TraceWriter> writer =
+      arbiter_->CreateTraceWriter(kBufId, BufferExhaustedPolicy::kDrop);
 
   // Write a small first packet, so that |writer| owns a chunk.
   auto packet = writer->NewTracePacket();
@@ -166,8 +166,8 @@
   // Grab all the remaining chunks in the SMB in new writers.
   std::array<std::unique_ptr<TraceWriter>, kNumPages * 4 - 1> other_writers;
   for (size_t i = 0; i < other_writers.size(); i++) {
-    other_writers[i] = arbiter_->CreateTraceWriter(
-        kBufId, SharedMemoryArbiter::BufferExhaustedPolicy::kDrop);
+    other_writers[i] =
+        arbiter_->CreateTraceWriter(kBufId, BufferExhaustedPolicy::kDrop);
     auto other_writer_packet = other_writers[i]->NewTracePacket();
     EXPECT_FALSE(reinterpret_cast<TraceWriterImpl*>(other_writers[i].get())
                      ->drop_packets_for_testing());
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index 994e1da..985bfa1 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -2182,7 +2182,7 @@
     !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   struct {
     clockid_t id;
-    protos::ClockSnapshot::Clock::Type type;
+    protos::ClockSnapshot::Clock::BuiltinClocks type;
     struct timespec ts;
   } clocks[] = {
       {CLOCK_BOOTTIME, protos::ClockSnapshot::Clock::BOOTTIME, {0, 0}},
@@ -2216,7 +2216,7 @@
           static_cast<uint64_t>(base::FromPosixTimespec(clock.ts).count()));
     }
     protos::ClockSnapshot::Clock* c = clock_snapshot->add_clocks();
-    c->set_type(clock.type);
+    c->set_clock_id(clock.type);
     c->set_timestamp(
         static_cast<uint64_t>(base::FromPosixTimespec(clock.ts).count()));
   }
@@ -2225,7 +2225,7 @@
   if (set_root_timestamp)
     packet.set_timestamp(wall_time_ns);
   protos::ClockSnapshot::Clock* c = clock_snapshot->add_clocks();
-  c->set_type(protos::ClockSnapshot::Clock::MONOTONIC);
+  c->set_clock_id(protos::ClockSnapshot::Clock::MONOTONIC);
   c->set_timestamp(wall_time_ns);
 #endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 
@@ -2771,8 +2771,11 @@
 
 // Can be called on any thread.
 std::unique_ptr<TraceWriter>
-TracingServiceImpl::ProducerEndpointImpl::CreateTraceWriter(BufferID buf_id) {
-  return GetInProcessShmemArbiter()->CreateTraceWriter(buf_id);
+TracingServiceImpl::ProducerEndpointImpl::CreateTraceWriter(
+    BufferID buf_id,
+    BufferExhaustedPolicy buffer_exhausted_policy) {
+  return GetInProcessShmemArbiter()->CreateTraceWriter(buf_id,
+                                                       buffer_exhausted_policy);
 }
 
 void TracingServiceImpl::ProducerEndpointImpl::NotifyFlushComplete(
diff --git a/src/tracing/core/tracing_service_impl.h b/src/tracing/core/tracing_service_impl.h
index 57f504e..0fd2c3a 100644
--- a/src/tracing/core/tracing_service_impl.h
+++ b/src/tracing/core/tracing_service_impl.h
@@ -89,7 +89,9 @@
     void UnregisterTraceWriter(uint32_t writer_id) override;
     void CommitData(const CommitDataRequest&, CommitDataCallback) override;
     void SetSharedMemory(std::unique_ptr<SharedMemory>);
-    std::unique_ptr<TraceWriter> CreateTraceWriter(BufferID) override;
+    std::unique_ptr<TraceWriter> CreateTraceWriter(
+        BufferID,
+        BufferExhaustedPolicy) override;
     SharedMemoryArbiter* GetInProcessShmemArbiter() override;
     void NotifyFlushComplete(FlushRequestID) override;
     void NotifyDataSourceStarted(DataSourceInstanceID) override;
diff --git a/src/tracing/internal/tracing_muxer_impl.cc b/src/tracing/internal/tracing_muxer_impl.cc
index 5f8035a..38a2d7b 100644
--- a/src/tracing/internal/tracing_muxer_impl.cc
+++ b/src/tracing/internal/tracing_muxer_impl.cc
@@ -26,6 +26,7 @@
 #include "perfetto/base/task_runner.h"
 #include "perfetto/ext/base/thread_checker.h"
 #include "perfetto/ext/base/waitable_event.h"
+#include "perfetto/ext/tracing/core/buffer_exhausted_policy.h"
 #include "perfetto/ext/tracing/core/trace_packet.h"
 #include "perfetto/ext/tracing/core/trace_writer.h"
 #include "perfetto/ext/tracing/core/tracing_service.h"
@@ -488,7 +489,7 @@
 
       auto* internal_state =
           reinterpret_cast<DataSourceState*>(&static_state.instances[i]);
-      std::lock_guard<std::mutex> guard(internal_state->lock);
+      std::lock_guard<std::recursive_mutex> guard(internal_state->lock);
       static_assert(
           std::is_same<decltype(internal_state->data_source_instance_id),
                        DataSourceInstanceID>::value,
@@ -527,7 +528,7 @@
     return;
   }
 
-  std::lock_guard<std::mutex> guard(ds.internal_state->lock);
+  std::lock_guard<std::recursive_mutex> guard(ds.internal_state->lock);
   ds.internal_state->trace_lambda_enabled = true;
   ds.internal_state->data_source->OnStart(DataSourceBase::StartArgs{});
 }
@@ -558,7 +559,7 @@
   };
 
   {
-    std::lock_guard<std::mutex> guard(ds.internal_state->lock);
+    std::lock_guard<std::recursive_mutex> guard(ds.internal_state->lock);
     ds.internal_state->data_source->OnStop(stop_args);
   }
 
@@ -592,7 +593,7 @@
   // a Trace() execution where it called GetDataSourceLocked() while we
   // destroy it.
   {
-    std::lock_guard<std::mutex> guard(ds.internal_state->lock);
+    std::lock_guard<std::recursive_mutex> guard(ds.internal_state->lock);
     ds.internal_state->trace_lambda_enabled = false;
     ds.internal_state->data_source.reset();
   }
@@ -804,7 +805,13 @@
 std::unique_ptr<TraceWriterBase> TracingMuxerImpl::CreateTraceWriter(
     DataSourceState* data_source) {
   ProducerImpl* producer = backends_[data_source->backend_id].producer.get();
-  return producer->service_->CreateTraceWriter(data_source->buffer_id);
+  // We choose BufferExhaustedPolicy::kDrop to avoid stalls when all SMB chunks
+  // are allocated, ensuring that the app keeps working even when tracing hits
+  // its SMB limit. Note that this means we will lose data in such a case
+  // (tracked in BufferStats::trace_writer_packet_loss). To reduce this data
+  // loss, apps should choose a large enough SMB size.
+  return producer->service_->CreateTraceWriter(data_source->buffer_id,
+                                               BufferExhaustedPolicy::kDrop);
 }
 
 // This is called via the public API Tracing::NewTrace().
diff --git a/src/tracing/ipc/producer/producer_ipc_client_impl.cc b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
index 28f1085..bee2026 100644
--- a/src/tracing/ipc/producer/producer_ipc_client_impl.cc
+++ b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
@@ -19,6 +19,7 @@
 #include <inttypes.h>
 #include <string.h>
 
+#include "perfetto/base/logging.h"
 #include "perfetto/base/task_runner.h"
 #include "perfetto/ext/ipc/client.h"
 #include "perfetto/ext/tracing/core/commit_data_request.h"
@@ -107,6 +108,14 @@
           protos::InitializeConnectionRequest::SMB_SCRAPING_DISABLED);
       break;
   }
+
+#if PERFETTO_DCHECK_IS_ON()
+  req.set_build_flags(
+      protos::InitializeConnectionRequest::BUILD_FLAGS_DCHECKS_ON);
+#else
+  req.set_build_flags(
+      protos::InitializeConnectionRequest::BUILD_FLAGS_DCHECKS_OFF);
+#endif
   producer_port_.InitializeConnection(req, std::move(on_init));
 
   // Create the back channel to receive commands from the Service.
@@ -347,10 +356,12 @@
 }
 
 std::unique_ptr<TraceWriter> ProducerIPCClientImpl::CreateTraceWriter(
-    BufferID target_buffer) {
+    BufferID target_buffer,
+    BufferExhaustedPolicy buffer_exhausted_policy) {
   // This method can be called by different threads. |shared_memory_arbiter_| is
   // thread-safe but be aware of accessing any other state in this function.
-  return shared_memory_arbiter_->CreateTraceWriter(target_buffer);
+  return shared_memory_arbiter_->CreateTraceWriter(target_buffer,
+                                                   buffer_exhausted_policy);
 }
 
 SharedMemoryArbiter* ProducerIPCClientImpl::GetInProcessShmemArbiter() {
diff --git a/src/tracing/ipc/producer/producer_ipc_client_impl.h b/src/tracing/ipc/producer/producer_ipc_client_impl.h
index 0028330..2034994 100644
--- a/src/tracing/ipc/producer/producer_ipc_client_impl.h
+++ b/src/tracing/ipc/producer/producer_ipc_client_impl.h
@@ -74,7 +74,8 @@
   void ActivateTriggers(const std::vector<std::string>&) override;
 
   std::unique_ptr<TraceWriter> CreateTraceWriter(
-      BufferID target_buffer) override;
+      BufferID target_buffer,
+      BufferExhaustedPolicy) override;
   SharedMemoryArbiter* GetInProcessShmemArbiter() override;
   void NotifyFlushComplete(FlushRequestID) override;
   SharedMemory* shared_memory() const override;
diff --git a/src/tracing/ipc/service/producer_ipc_service.cc b/src/tracing/ipc/service/producer_ipc_service.cc
index 99b51dd..96acf71 100644
--- a/src/tracing/ipc/service/producer_ipc_service.cc
+++ b/src/tracing/ipc/service/producer_ipc_service.cc
@@ -78,6 +78,21 @@
       break;
   }
 
+  bool dcheck_mismatch = false;
+#if PERFETTO_DCHECK_IS_ON()
+  dcheck_mismatch =
+      req.build_flags() ==
+      protos::InitializeConnectionRequest::BUILD_FLAGS_DCHECKS_OFF;
+#else
+  dcheck_mismatch = req.build_flags() ==
+                    protos::InitializeConnectionRequest::BUILD_FLAGS_DCHECKS_ON;
+#endif
+  if (dcheck_mismatch) {
+    PERFETTO_LOG(
+        "The producer and the service binaries are built using different "
+        "DEBUG/NDEBUG flags. This will likely cause crashes.");
+  }
+
   // ConnectProducer will call OnConnect() on the next task.
   producer->service_endpoint = core_service_->ConnectProducer(
       producer.get(), client_info.uid(), req.producer_name(),
@@ -86,8 +101,10 @@
       req.shared_memory_page_size_hint_bytes());
 
   // Could happen if the service has too many producers connected.
-  if (!producer->service_endpoint)
+  if (!producer->service_endpoint) {
     response.Reject();
+    return;
+  }
 
   producers_.emplace(ipc_client_id, std::move(producer));
   // Because of the std::move() |producer| is invalid after this point.
diff --git a/src/tracing/test/fake_producer_endpoint.h b/src/tracing/test/fake_producer_endpoint.h
index f6fb5b9..fc364cf 100644
--- a/src/tracing/test/fake_producer_endpoint.h
+++ b/src/tracing/test/fake_producer_endpoint.h
@@ -39,7 +39,9 @@
   void ActivateTriggers(const std::vector<std::string>&) override {}
   SharedMemory* shared_memory() const override { return nullptr; }
   size_t shared_buffer_page_size_kb() const override { return 0; }
-  std::unique_ptr<TraceWriter> CreateTraceWriter(BufferID) override {
+  std::unique_ptr<TraceWriter> CreateTraceWriter(
+      BufferID,
+      BufferExhaustedPolicy) override {
     return nullptr;
   }
   SharedMemoryArbiter* GetInProcessShmemArbiter() override { return nullptr; }
diff --git a/test/ci/fuzzer_tests.sh b/test/ci/fuzzer_tests.sh
index b569ee9..6736857 100755
--- a/test/ci/fuzzer_tests.sh
+++ b/test/ci/fuzzer_tests.sh
@@ -29,6 +29,9 @@
 tools/gn gen ${OUT_PATH} --args="${PERFETTO_TEST_GN_ARGS}" --check
 tools/ninja -C ${OUT_PATH} ${PERFETTO_TEST_NINJA_ARGS} fuzzers
 
+# Check the amalgamated build here to avoid slowing down all the Linux bots.
+tools/test_gen_amalgamated.py
+
 # Run a single iteration each to make sure they are not crashing.
 for fuzzer in $(find ${OUT_PATH} -name '*_fuzzer' -executable); do
   $fuzzer -runs=1
diff --git a/test/ci/linux_tests.sh b/test/ci/linux_tests.sh
index 4c293f9..c610844 100755
--- a/test/ci/linux_tests.sh
+++ b/test/ci/linux_tests.sh
@@ -35,8 +35,13 @@
 ${OUT_PATH}/perfetto_integrationtests
 BENCHMARK_FUNCTIONAL_TEST_ONLY=true ${OUT_PATH}/perfetto_benchmarks
 
+mkdir -p /ci/artifacts/perf-test-metrics.tmp
 tools/diff_test_trace_processor.py \
-  --test-type=queries ${OUT_PATH}/trace_processor_shell
-
+  --test-type=queries \
+  --perf-file=/ci/artifacts/perf-test-metrics.tmp/tp-perf-queries.json \
+  ${OUT_PATH}/trace_processor_shell
 tools/diff_test_trace_processor.py \
-  --test-type=metrics ${OUT_PATH}/trace_processor_shell
+  --test-type=metrics \
+  --perf-file=/ci/artifacts/perf-test-metrics.tmp/tp-perf-metrics.json \
+  ${OUT_PATH}/trace_processor_shell
+mv /ci/artifacts/perf-test-metrics.tmp /ci/artifacts/perf-test-metrics
\ No newline at end of file
diff --git a/test/metrics/android_mem_counters.out b/test/metrics/android_mem_counters.out
index 7469f1f..c729120 100644
--- a/test/metrics/android_mem_counters.out
+++ b/test/metrics/android_mem_counters.out
@@ -2347,6 +2347,11 @@
         max: 32796672
         avg: 32765771.09452733
       }
+      java_heap {
+        min: 1374208
+        max: 1427456
+        avg: 1419596.8920014114
+      }
     }
   }
   process_metrics {
@@ -2372,6 +2377,11 @@
         max: 31100928
         avg: 30828073.014492534
       }
+      java_heap {
+        min: 1193984
+        max: 1193984
+        avg: 1193984
+      }
     }
   }
   process_metrics {
@@ -2397,6 +2407,11 @@
         max: 38170624
         avg: 37379428.70679906
       }
+      java_heap {
+        min: 1499136
+        max: 4316160
+        avg: 2972808.7655181894
+      }
     }
   }
   process_metrics {
@@ -2447,6 +2462,11 @@
         max: 43556864
         avg: 37778954.5579197
       }
+      java_heap {
+        min: 3152896
+        max: 7367680
+        avg: 5624331.5376309063
+      }
     }
   }
   process_metrics {
@@ -2522,6 +2542,11 @@
         max: 32333824
         avg: 32312115.023602
       }
+      java_heap {
+        min: 1345536
+        max: 1395712
+        avg: 1378703.0378377116
+      }
     }
   }
   process_metrics {
@@ -2572,6 +2597,11 @@
         max: 51023872
         avg: 50602448.04672049
       }
+      java_heap {
+        min: 2658304
+        max: 3159040
+        avg: 2933014.4999347096
+      }
     }
   }
   process_metrics {
@@ -2597,6 +2627,11 @@
         max: 39768064
         avg: 38817213.791344121
       }
+      java_heap {
+        min: 1519616
+        max: 4826112
+        avg: 2558538.0852529262
+      }
     }
   }
   process_metrics {
@@ -2647,6 +2682,11 @@
         max: 36679680
         avg: 36364002.255620666
       }
+      java_heap {
+        min: 3202048
+        max: 4088832
+        avg: 4043650.9270121339
+      }
     }
   }
   process_metrics {
@@ -2672,6 +2712,11 @@
         max: 35635200
         avg: 35418527.859008193
       }
+      java_heap {
+        min: 3026944
+        max: 3207168
+        avg: 3204534.0849129637
+      }
     }
   }
   process_metrics {
@@ -2822,6 +2867,11 @@
         max: 71012352
         avg: 68351542.715876162
       }
+      java_heap {
+        min: 6224896
+        max: 10747904
+        avg: 6949136.10971856
+      }
     }
   }
   process_metrics {
@@ -2997,6 +3047,11 @@
         max: 82853888
         avg: 68519057.186817423
       }
+      java_heap {
+        min: 8163328
+        max: 14021632
+        avg: 11450919.918936323
+      }
     }
   }
   process_metrics {
diff --git a/test/trace_processor/compressed_smoke.out b/test/trace_processor/compressed_smoke.out
new file mode 100644
index 0000000..422aaec
--- /dev/null
+++ b/test/trace_processor/compressed_smoke.out
@@ -0,0 +1,11 @@
+"ts","cpu","dur","end_state","priority","tid"
+170601497673450,2,53646,"DK",120,6790
+170601497691210,7,22917,"R",120,0
+170601497714127,7,29167,"D",120,6732
+170601497727096,2,55156,"S",120,62
+170601497743294,7,862656,"R",120,0
+170601497766106,3,13594,"S",120,8
+170601497779700,3,31094,"D",120,6790
+170601497782252,2,875313,"R",120,0
+170601497810794,3,824635,"R",120,0
+170601498605950,7,158333,"D",120,6732
diff --git a/test/trace_processor/index b/test/trace_processor/index
index f4a1805..5b0e49d 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -2,6 +2,7 @@
 ../data/sfgate.json smoke.sql sfgate_smoke.out
 ../data/sfgate.json smoke_slices.sql sfgate_smoke_slices.out
 ../data/android_sched_and_ps.pb smoke.sql android_sched_and_ps_smoke.out
+../data/compressed.pb smoke.sql compressed_smoke.out
 synth_1.py smoke.sql synth_1_smoke.out
 ../data/fuchsia_trace.fxt smoke.sql fuchsia_smoke.out
 ../data/fuchsia_trace.fxt smoke_slices.sql fuchsia_smoke_slices.out
diff --git a/tools/diff_test_trace_processor.py b/tools/diff_test_trace_processor.py
index 251de30..627bc7d 100755
--- a/tools/diff_test_trace_processor.py
+++ b/tools/diff_test_trace_processor.py
@@ -23,11 +23,19 @@
 import sys
 import tempfile
 
+from itertools import chain
 from google.protobuf import descriptor, descriptor_pb2, message_factory
 from google.protobuf import reflection, text_format
 
 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
+class PerfResult(object):
+  def __init__(self, trace_name, query_or_metric, ingest_time, real_time):
+    self.trace_name = trace_name
+    self.query_or_metric = query_or_metric
+    self.ingest_time = ingest_time
+    self.real_time = real_time
+
 def create_metrics_message_factory(metrics_descriptor_path):
   with open(metrics_descriptor_path, 'r') as metrics_descriptor_file:
     metrics_descriptor_content = metrics_descriptor_file.read()
@@ -218,8 +226,9 @@
       trace_shortpath = os.path.relpath(trace_path, test_dir)
 
       assert len(perf_numbers) == 2
-      perf_data.append((trace_shortpath, query_fname_or_metric,
-                        perf_numbers[0], perf_numbers[1]))
+      perf_result = PerfResult(trace_shortpath, query_fname_or_metric,
+                               perf_numbers[0], perf_numbers[1])
+      perf_data.append(perf_result)
     else:
       sys.stderr.write(
         'Expected did not match actual for trace {} and {} {}\n'
@@ -235,19 +244,35 @@
     print('All tests passed successfully')
 
     if args.perf_file:
-      output_data = {
-        'benchmarks': [
+      metrics = [
+        [
           {
-            'name': '{}|{}'.format(perf_args[0], perf_args[1]),
-            'trace_name': perf_args[0],
-            'query_name': perf_args[1],
-            'ingest_time': perf_args[2],
-            'real_time': perf_args[3],
-            'time_unit': 'ns',
-            'test_type': args.test_type,
+            'metric': 'tp_perf_test_ingest_time',
+            'value': float(perf_args.ingest_time) / 1.0e9,
+            'unit': 's',
+            'tags': {
+              'test_name': '{}-{}'.format(perf_args.trace_name,
+                                          perf_args.query_or_metric),
+              'test_type': args.test_type,
+            },
+            'labels': {},
+          },
+          {
+            'metric': 'perf_test_real_time',
+            'value': float(perf_args.real_time) / 1.0e9,
+            'unit': 's',
+            'tags': {
+              'test_name': '{}-{}'.format(perf_args.trace_name,
+                                          perf_args.query_or_metric),
+              'test_type': args.test_type,
+            },
+            'labels': {},
           }
-          for perf_args in sorted(perf_data)
         ]
+        for perf_args in sorted(perf_data)
+      ]
+      output_data = {
+        'metrics': list(chain.from_iterable(metrics))
       }
       with open(args.perf_file, 'w+') as perf_file:
         perf_file.write(json.dumps(output_data, indent=2))
diff --git a/tools/gen_all b/tools/gen_all
index dc5021c..3b50478 100755
--- a/tools/gen_all
+++ b/tools/gen_all
@@ -29,7 +29,7 @@
 def call(cmd, *args):
   path = os.path.join('tools', cmd)
   command = [path] + list(args)
-  print 'Running ', ' '.join(command)
+  print 'Running', ' '.join(command)
   try:
     subprocess.check_call(command, cwd=ROOT_DIR)
   except subprocess.CalledProcessError as e:
@@ -51,7 +51,6 @@
     call('gen_merged_protos')
     call('gen_binary_descriptors', '--protoc', protoc_path(out))
     call('gen_tracing_cpp_headers_from_protos', out)
-    call('gen_amalgamated', '--check', '--quiet')  # Keep last
 
   except AssertionError as e:
     if not str(e):
diff --git a/tools/gen_amalgamated b/tools/gen_amalgamated
index ce9ce82..57eed7c 100755
--- a/tools/gen_amalgamated
+++ b/tools/gen_amalgamated
@@ -181,13 +181,16 @@
 class AmalgamatedProject(object):
     """In-memory representation of an amalgamated source/header pair."""
 
-    def __init__(self, desc, source_deps):
+    def __init__(self, desc, source_deps, compute_deps_only=False):
         """Constructor.
 
         Args:
             desc: JSON build description.
             source_deps: A map of (source file, [dependency header]) which is
                 to detect which header files are included by each source file.
+            compute_deps_only: If True, the project will only be used to compute
+                dependency information. Use |get_source_files()| to retrieve
+                the result.
         """
         self.desc = desc
         self.source_deps = source_deps
@@ -204,6 +207,7 @@
         self._processed_headers = set()
         self._processed_source_headers = set()  # Header files included from .cc
         self._include_re = re.compile(r'#include "(.*)"')
+        self._compute_deps_only = compute_deps_only
 
     def add_target(self, target_name):
         """Include |target_name| in the amalgamated result."""
@@ -309,6 +313,8 @@
                         self._process_source_includes(
                             include_dirs, allowed_files, f))
                 return
+        if self._compute_deps_only:
+            return
         msg = 'Looked in %s' % ', '.join('"%s"' % d for d in include_dirs)
         raise Error('Header file %s not found. %s' % (header_name, msg))
 
@@ -343,6 +349,8 @@
                     self.header.extend(
                         self._process_header_includes(include_dirs, f))
                 return
+        if self._compute_deps_only:
+            return
         msg = 'Looked in %s' % ', '.join('"%s"' % d for d in include_dirs)
         raise Error('Header file %s not found. %s' % (header_name, msg))
 
@@ -352,6 +360,8 @@
         self._processed_headers.add(header_name)
         include_dirs = self._get_include_dirs(target_name)
         if not os.path.exists(header_name):
+            if self._compute_deps_only:
+                return
             raise Error('Header file %s not found' % source_name)
         with open(header_name) as f:
             self.header.append(
@@ -411,6 +421,7 @@
 
         Call save() to persist the result.
         """
+        assert not self._compute_deps_only
         self.source_defines.append('// %s: predefined macros' % tool_name)
         def add_define(name):
             # Valued macros aren't supported for now.
@@ -420,7 +431,13 @@
             self.source_defines.append('#endif')
         for name in self.defines:
             add_define(name)
+        for target_name, source_name in self.get_source_files():
+            self._add_source(target_name, source_name)
 
+    def get_source_files(self):
+        """Return a list of (target, [source file]) that describes the source
+           files pulled in by each target which is a dependency of this project.
+        """
         source_files = []
         for node in self._dependency_tree.iterate_depth_first():
             target = self.desc[node.target_name]
@@ -429,8 +446,7 @@
             sources = [(node.target_name, gn_utils.label_to_path(s))
                         for s in target['sources'] if s.endswith('.cc')]
             source_files.extend(sources)
-        for target_name, source_name in source_files:
-            self._add_source(target_name, source_name)
+        return source_files
 
     def _get_nice_path(self, prefix, format):
         basename = os.path.basename(prefix)
@@ -477,16 +493,6 @@
         return build_cmd
 
 
-
-def create_amalgamated_project_for_targets(desc, targets, source_deps):
-    """Generate an amalgamated project for a list of GN targets."""
-    project = AmalgamatedProject(desc, source_deps)
-    for target in targets:
-        project.add_target(target)
-    project.generate()
-    return project
-
-
 def main():
     parser = argparse.ArgumentParser(
         description='Generate an amalgamated header/source pair from a GN '
@@ -510,6 +516,10 @@
     parser.add_argument('--quiet', help='Only report errors',
         action='store_true')
     parser.add_argument(
+        '--dump-deps',
+        help='List all source files that the amalgamated output depends on',
+        action='store_true')
+    parser.add_argument(
         'targets',
         nargs=argparse.REMAINDER,
         help='Targets to include in the output (e.g., "//:libperfetto")')
@@ -526,12 +536,26 @@
         out = gn_utils.prepare_out_directory(
             args.gn_args, 'tmp.gen_amalgamated')
         desc = gn_utils.load_build_description(out)
+
         # We need to build everything first so that the necessary header
-        # dependencies get generated.
-        gn_utils.build_targets(out, targets)
+        # dependencies get generated. However if we are just dumping dependency
+        # information this can be skipped, allowing cross-platform operation.
+        if not args.dump_deps:
+            gn_utils.build_targets(out, targets)
         source_deps = gn_utils.compute_source_dependencies(out)
-        project = create_amalgamated_project_for_targets(
-            desc, targets, source_deps)
+        project = AmalgamatedProject(
+            desc, source_deps, compute_deps_only=args.dump_deps)
+
+        for target in targets:
+            project.add_target(target)
+
+        if args.dump_deps:
+            source_files = [
+                source_file for _, source_file in project.get_source_files()]
+            print('\n'.join(sorted(set(source_files))))
+            return
+
+        project.generate()
         result = project.save(output)
         if not args.quiet:
             print(result)
diff --git a/tools/gen_merged_protos b/tools/gen_merged_protos
index d187e13..74f6d53 100755
--- a/tools/gen_merged_protos
+++ b/tools/gen_merged_protos
@@ -46,6 +46,7 @@
 TRACE_PROTOS = (
   'protos/perfetto/common/trace_stats.proto', # only referenced by trace protos
   'protos/perfetto/trace/android/android_log.proto',
+  'protos/perfetto/trace/android/graphics_frame_event.proto',
   'protos/perfetto/trace/android/packages_list.proto',
   'protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto',
   "protos/perfetto/trace/chrome/chrome_metadata.proto",
@@ -85,6 +86,7 @@
   'protos/perfetto/trace/system_info.proto',
   'protos/perfetto/trace/trace.proto',
   'protos/perfetto/trace/trace_packet.proto',
+  'protos/perfetto/trace/trace_packet_defaults.proto',
   'protos/perfetto/trace/track_event/debug_annotation.proto',
   'protos/perfetto/trace/track_event/log_message.proto',
   'protos/perfetto/trace/track_event/process_descriptor.proto',
diff --git a/tools/heap_profile b/tools/heap_profile
index 5fc693e..3938b64 100755
--- a/tools/heap_profile
+++ b/tools/heap_profile
@@ -30,8 +30,8 @@
 import urllib
 
 TRACE_TO_TEXT_SHAS = {
-  'linux': 'b91fd044422c5276f314728dca52a1d1cf43df69',
-  'mac': 'd00c9ba443c93c18ed9e712d3e699ddda72a8bd8',
+  'linux': '74cb40d9413d7ad756e327e09e46a8adde90db92',
+  'mac': '47045bc6abd4f9113969211f37fdd2259b0c1cc3',
 }
 TRACE_TO_TEXT_PATH = tempfile.gettempdir()
 TRACE_TO_TEXT_BASE_URL = (
diff --git a/tools/install-build-deps b/tools/install-build-deps
index 9ad78b3..e66cdff 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -195,8 +195,8 @@
 
   # Example traces for regression tests.
   ('buildtools/test_data.zip',
-   'https://storage.googleapis.com/perfetto/test-data-20190710-183108.zip',
-   'a37e5e7153ae5f0ade0a413add1404b184c57fcc',
+   'https://storage.googleapis.com/perfetto/test-data-20190807-125643.zip',
+   'abd9bc3e9f9e74ec6810b5c9bd1f15713a9a58ec',
    'all',
   ),
 
diff --git a/tools/test_gen_amalgamated.py b/tools/test_gen_amalgamated.py
new file mode 100755
index 0000000..1a43d67
--- /dev/null
+++ b/tools/test_gen_amalgamated.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env 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.
+
+import os
+import subprocess
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+
+
+def call(cmd, *args):
+  path = os.path.join('tools', cmd)
+  command = [path] + list(args)
+  print 'Running', ' '.join(command)
+  try:
+    return subprocess.check_output(command, cwd=ROOT_DIR)
+  except subprocess.CalledProcessError as e:
+    assert False, 'Command: {} failed'.format(' '.join(command))
+
+
+def check_amalgamated_output():
+  call('gen_amalgamated', '--check', '--quiet')
+
+
+def check_amalgamated_dependencies():
+  os_deps = {}
+  for os_name in ['android', 'linux', 'mac']:
+    os_deps[os_name] = call(
+        'gen_amalgamated', '--gn_args', 'target_os="%s"' % os_name,
+        '--dump-deps', '--quiet').split('\n')
+  for os_name, deps in os_deps.items():
+    for dep in deps:
+      for other_os, other_deps in os_deps.items():
+        if not dep in other_deps:
+          raise AssertionError('Discrepancy in amalgamated build dependencies: '
+                               '%s is missing on %s.' % (dep, other_os))
+
+
+def main():
+  check_amalgamated_output()
+  check_amalgamated_dependencies()
+
+
+if __name__ == '__main__':
+  exit(main())
diff --git a/tools/trace_to_text/main.cc b/tools/trace_to_text/main.cc
index b26fc97..d098e45 100644
--- a/tools/trace_to_text/main.cc
+++ b/tools/trace_to_text/main.cc
@@ -35,7 +35,7 @@
 
 int Usage(const char* argv0) {
   printf(
-      "Usage: %s systrace|json|text|profile [--truncate] [trace.pb] "
+      "Usage: %s systrace|json|text|profile [--truncate start|end] [trace.pb] "
       "[trace.txt]\n",
       argv0);
   return 1;
@@ -44,17 +44,26 @@
 }  // namespace
 
 int main(int argc, char** argv) {
-  uint64_t file_size_limit = std::numeric_limits<uint64_t>::max();
   std::vector<const char*> positional_args;
-  bool should_truncate_trace = false;
+  perfetto::trace_to_text::Keep truncate_keep =
+      perfetto::trace_to_text::Keep::kAll;
   for (int i = 1; i < argc; i++) {
     if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
       printf("%s\n", PERFETTO_GET_GIT_REVISION());
       return 0;
     } else if (strcmp(argv[i], "-t") == 0 ||
                strcmp(argv[i], "--truncate") == 0) {
-      should_truncate_trace = true;
-      file_size_limit = 1024u * 1024u * 50u;
+      i++;
+      if (i <= argc && strcmp(argv[i], "start") == 0) {
+        truncate_keep = perfetto::trace_to_text::Keep::kStart;
+      } else if (i <= argc && strcmp(argv[i], "end") == 0) {
+        truncate_keep = perfetto::trace_to_text::Keep::kEnd;
+      } else {
+        PERFETTO_ELOG(
+            "--truncate must specify whether to keep the end or the "
+            "start of the trace.");
+        return Usage(argv[0]);
+      }
     } else {
       positional_args.push_back(argv[i]);
     }
@@ -97,13 +106,13 @@
 
   if (format == "json")
     return perfetto::trace_to_text::TraceToSystrace(input_stream, output_stream,
-                                                    file_size_limit,
+                                                    truncate_keep,
                                                     /*wrap_in_json=*/true);
   if (format == "systrace")
     return perfetto::trace_to_text::TraceToSystrace(input_stream, output_stream,
-                                                    file_size_limit,
+                                                    truncate_keep,
                                                     /*wrap_in_json=*/false);
-  if (should_truncate_trace) {
+  if (truncate_keep != perfetto::trace_to_text::Keep::kAll) {
     PERFETTO_ELOG(
         "--truncate is unsupported for text|profile|symbolize format.");
     return 1;
diff --git a/tools/trace_to_text/trace_symbol_table.cc b/tools/trace_to_text/trace_symbol_table.cc
index e1ea600..1767cad 100644
--- a/tools/trace_to_text/trace_symbol_table.cc
+++ b/tools/trace_to_text/trace_symbol_table.cc
@@ -22,7 +22,6 @@
 #include <string>
 #include <vector>
 
-#include <elf.h>
 #include <inttypes.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
diff --git a/tools/trace_to_text/trace_to_profile.cc b/tools/trace_to_text/trace_to_profile.cc
index a4c5b14..cb34eca 100644
--- a/tools/trace_to_text/trace_to_profile.cc
+++ b/tools/trace_to_text/trace_to_profile.cc
@@ -23,6 +23,7 @@
 #include "tools/trace_to_text/local_symbolizer.h"  // nogncheck
 #endif
 #include "tools/trace_to_text/pprof_builder.h"
+#include "tools/trace_to_text/symbolizer.h"
 #include "tools/trace_to_text/utils.h"
 
 #include "perfetto/base/logging.h"
diff --git a/tools/trace_to_text/trace_to_systrace.cc b/tools/trace_to_text/trace_to_systrace.cc
index 820ce69..e67ef09 100644
--- a/tools/trace_to_text/trace_to_systrace.cc
+++ b/tools/trace_to_text/trace_to_systrace.cc
@@ -174,7 +174,7 @@
 
 int TraceToSystrace(std::istream* input,
                     std::ostream* output,
-                    uint64_t file_size_limit,
+                    Keep truncate_keep,
                     bool wrap_in_json) {
   trace_processor::Config config;
   std::unique_ptr<trace_processor::TraceProcessor> tp =
@@ -192,7 +192,7 @@
 #endif
   uint64_t file_size = 0;
 
-  for (int i = 0; file_size < file_size_limit; i++) {
+  for (int i = 0;; i++) {
     if (i % kStderrRate == 0) {
       fprintf(stderr, "Loading trace %.2f MB" PROGRESS_CHAR, file_size / 1.0e6);
       fflush(stderr);
@@ -269,7 +269,14 @@
   fprintf(stderr, "Converting trace events" PROGRESS_CHAR);
   fflush(stderr);
 
-  static const char kRawSql[] = "select to_ftrace(id) from raw";
+  static const char kEstimatSql[] = "select count(1) from raw";
+  uint32_t raw_events = 0;
+  auto e_callback = [&raw_events](Iterator* it, base::StringWriter*) {
+    raw_events = static_cast<uint32_t>(it->Get(0).long_value);
+  };
+  if (!q_writer.RunQuery(kEstimatSql, e_callback))
+    return 1;
+
   auto raw_callback = [wrap_in_json](Iterator* it, base::StringWriter* writer) {
     const char* line = it->Get(0 /* col */).string_value;
     if (wrap_in_json) {
@@ -309,8 +316,30 @@
       writer->AppendChar('\n');
     }
   };
-  if (!q_writer.RunQuery(kRawSql, raw_callback))
-    return 1;
+
+  // An estimate of 130b per ftrace event, allowing some space for the processes
+  // and threads.
+  const uint32_t max_ftrace_events = (140 * 1024 * 1024) / 130;
+
+  char kEndTrunc[100];
+  sprintf(kEndTrunc,
+          "select to_ftrace(id) from raw limit %d "
+          "offset %d",
+          max_ftrace_events, raw_events - max_ftrace_events);
+  char kStartTruncate[100];
+  sprintf(kStartTruncate, "select to_ftrace(id) from raw limit %d",
+          max_ftrace_events);
+
+  if (truncate_keep == Keep::kEnd && raw_events > max_ftrace_events) {
+    if (!q_writer.RunQuery(kEndTrunc, raw_callback))
+      return 1;
+  } else if (truncate_keep == Keep::kStart) {
+    if (!q_writer.RunQuery(kStartTruncate, raw_callback))
+      return 1;
+  } else {
+    if (!q_writer.RunQuery("select to_ftrace(id) from raw", raw_callback))
+      return 1;
+  }
 
   if (wrap_in_json)
     *output << kTraceFooter;
diff --git a/tools/trace_to_text/trace_to_systrace.h b/tools/trace_to_text/trace_to_systrace.h
index 366d10c..c1c4659 100644
--- a/tools/trace_to_text/trace_to_systrace.h
+++ b/tools/trace_to_text/trace_to_systrace.h
@@ -22,9 +22,11 @@
 namespace perfetto {
 namespace trace_to_text {
 
+enum class Keep { kStart = 0, kEnd, kAll };
+
 int TraceToSystrace(std::istream* input,
                     std::ostream* output,
-                    uint64_t file_size_limit,
+                    Keep truncate_keep,
                     bool wrap_in_json);
 
 }  // namespace trace_to_text
diff --git a/ui/BUILD.gn b/ui/BUILD.gn
index f4ba00b..2641265 100644
--- a/ui/BUILD.gn
+++ b/ui/BUILD.gn
@@ -291,6 +291,7 @@
   "src/assets/topbar.scss",
   "src/assets/record.scss",
   "src/assets/common.scss",
+  "src/assets/modal.scss",
 ]
 
 # Build css.
diff --git a/ui/index.html b/ui/index.html
index ad3d369..c375f93 100644
--- a/ui/index.html
+++ b/ui/index.html
@@ -10,7 +10,10 @@
   <link rel="preload" href="trace_processor.wasm" as="fetch">
 </head>
 <body>
-  <div class="full-page-loading-screen"></div>
+  <main>
+    <div class="full-page-loading-screen"></div>
+  </main>
+  <div id="main-modal" aria-hidden="true" class="modal micromodal-slide"></div>
 </body>
 </html>
 <script src="frontend_bundle.js"></script>
diff --git a/ui/package-lock.json b/ui/package-lock.json
index c92b6a2..1d3b02d 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -2288,6 +2288,11 @@
       "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=",
       "dev": true
     },
+    "events": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz",
+      "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA=="
+    },
     "exec-sh": {
       "version": "0.2.2",
       "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz",
@@ -2603,7 +2608,8 @@
         "ansi-regex": {
           "version": "2.1.1",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "aproba": {
           "version": "1.2.0",
@@ -2624,12 +2630,14 @@
         "balanced-match": {
           "version": "1.0.0",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "brace-expansion": {
           "version": "1.1.11",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "balanced-match": "^1.0.0",
             "concat-map": "0.0.1"
@@ -2644,17 +2652,20 @@
         "code-point-at": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "concat-map": {
           "version": "0.0.1",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "console-control-strings": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "core-util-is": {
           "version": "1.0.2",
@@ -2771,7 +2782,8 @@
         "inherits": {
           "version": "2.0.3",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "ini": {
           "version": "1.3.5",
@@ -2783,6 +2795,7 @@
           "version": "1.0.0",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "number-is-nan": "^1.0.0"
           }
@@ -2797,6 +2810,7 @@
           "version": "3.0.4",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "brace-expansion": "^1.1.7"
           }
@@ -2804,12 +2818,14 @@
         "minimist": {
           "version": "0.0.8",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "minipass": {
           "version": "2.3.5",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "safe-buffer": "^5.1.2",
             "yallist": "^3.0.0"
@@ -2828,6 +2844,7 @@
           "version": "0.5.1",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "minimist": "0.0.8"
           }
@@ -2908,7 +2925,8 @@
         "number-is-nan": {
           "version": "1.0.1",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "object-assign": {
           "version": "4.1.1",
@@ -2920,6 +2938,7 @@
           "version": "1.4.0",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "wrappy": "1"
           }
@@ -3005,7 +3024,8 @@
         "safe-buffer": {
           "version": "5.1.2",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "safer-buffer": {
           "version": "2.1.2",
@@ -3041,6 +3061,7 @@
           "version": "1.0.2",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "code-point-at": "^1.0.0",
             "is-fullwidth-code-point": "^1.0.0",
@@ -3060,6 +3081,7 @@
           "version": "3.0.1",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "ansi-regex": "^2.0.0"
           }
@@ -3103,12 +3125,14 @@
         "wrappy": {
           "version": "1.0.2",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "yallist": {
           "version": "3.0.3",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         }
       }
     },
@@ -4875,6 +4899,11 @@
         "regex-cache": "^0.4.2"
       }
     },
+    "micromodal": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/micromodal/-/micromodal-0.4.0.tgz",
+      "integrity": "sha512-YDku9Fi57S4Sm6oitSy3sr786qSp5L6NbatuH2kEeXf0jStvZgZk4bLBKaoSONBaq3BEvFz3hAaoUa7/pV1Kgg=="
+    },
     "mime": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
@@ -5160,6 +5189,11 @@
         }
       }
     },
+    "noice-json-rpc": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/noice-json-rpc/-/noice-json-rpc-1.2.0.tgz",
+      "integrity": "sha512-Wm+otW+drKzdqlSPoSwj34tUEq/Xj1gX6Cr2avrykvTW4IY7d3ngLmP+PErALzS0s9nYRokXvYDM54sbFvLlDA=="
+    },
     "nopt": {
       "version": "3.0.6",
       "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
@@ -6437,26 +6471,26 @@
       }
     },
     "rollup": {
-      "version": "1.12.2",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.12.2.tgz",
-      "integrity": "sha512-ePehZfVMIE4eO0/LV6VaMY8kp0D9sbziUabpBeJbHAHa2WJPxuS0lYLmiLamb02e098RIRyq1F2yjM4O08dQVA==",
+      "version": "1.17.0",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.17.0.tgz",
+      "integrity": "sha512-k/j1m0NIsI4SYgCJR4MWPstGJOWfJyd6gycKoMhyoKPVXxm+L49XtbUwZyFsrSU2YXsOkM4u1ll9CS/ZgJBUpw==",
       "dev": true,
       "requires": {
         "@types/estree": "0.0.39",
-        "@types/node": "^12.0.2",
-        "acorn": "^6.1.1"
+        "@types/node": "^12.6.2",
+        "acorn": "^6.2.0"
       },
       "dependencies": {
         "@types/node": {
-          "version": "12.0.2",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.2.tgz",
-          "integrity": "sha512-5tabW/i+9mhrfEOUcLDu2xBPsHJ+X5Orqy9FKpale3SjDA17j5AEpYq5vfy3oAeAHGcvANRCO3NV3d2D6q3NiA==",
+          "version": "12.6.8",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.8.tgz",
+          "integrity": "sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg==",
           "dev": true
         },
         "acorn": {
-          "version": "6.1.1",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz",
-          "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==",
+          "version": "6.2.1",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz",
+          "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==",
           "dev": true
         }
       }
diff --git a/ui/package.json b/ui/package.json
index 30b66cf..c1f09a8 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -18,8 +18,11 @@
     "@types/uuid": "^3.4.4",
     "color-convert": "^2.0.0",
     "devtools-protocol": "0.0.681549",
+    "events": "^3.0.0",
     "immer": "^1.12.1",
+    "micromodal": "^0.4.0",
     "mithril": "^1.1.6",
+    "noice-json-rpc": "^1.2.0",
     "pako": "^1.0.10",
     "protobufjs": "^6.8.8",
     "uuid": "^3.3.2"
@@ -32,7 +35,7 @@
     "lite-server": "^2.4.0",
     "node-sass": "^4.12.0",
     "puppeteer": "^1.16.0",
-    "rollup": "^1.12.2",
+    "rollup": "^1.17.0",
     "rollup-plugin-commonjs": "^9.3.4",
     "rollup-plugin-node-resolve": "^4.2.4",
     "sorcery": "^0.10.0",
diff --git a/ui/rollup.config.js b/ui/rollup.config.js
index 3cd838c..e4795c4 100644
--- a/ui/rollup.config.js
+++ b/ui/rollup.config.js
@@ -8,6 +8,7 @@
         nodeResolve({
           mainFields: ['browser'],
           browser: true,
+          preferBuiltins: false,
         }),
 
         // emscripten conditionally executes require('fs') (likewise for
@@ -21,5 +22,5 @@
             'crypto',
           ]
         }),
-      ]
+      ],
 }
diff --git a/ui/src/assets/common.scss b/ui/src/assets/common.scss
index 061d3dd..fb9f3ba 100644
--- a/ui/src/assets/common.scss
+++ b/ui/src/assets/common.scss
@@ -65,7 +65,8 @@
 }
 
 html,
-body {
+body,
+body>main {
     height: 100%;
     width: 100%;
     padding: 0;
@@ -86,13 +87,13 @@
     user-select: text;
 }
 
-body {
+body>main {
     display: grid;
     grid-template-areas:
       "sidebar topbar"
       "sidebar alerts"
       "sidebar page";
-    grid-template-rows: var(--topbar-height) auto 1fr;
+    grid-template-rows: auto auto 1fr;
     grid-template-columns: auto 1fr;
     color: #121212;
 }
diff --git a/ui/src/assets/modal.scss b/ui/src/assets/modal.scss
new file mode 100644
index 0000000..8879e18
--- /dev/null
+++ b/ui/src/assets/modal.scss
@@ -0,0 +1,169 @@
+// 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.
+
+/**************************\
+  Basic Modal Styles
+\**************************/
+.modal {
+  font-family: 'Raleway';
+}
+
+.modal-overlay {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: rgba(0,0,0,0.6);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 4;
+}
+
+.modal-container {
+  background-color: #fff;
+  padding: 30px;
+  max-width: 550px;
+  max-height: 100vh;
+  border-radius: 4px;
+  overflow-y: auto;
+  box-sizing: border-box;
+}
+
+.modal-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.modal-title {
+  margin-top: 0;
+  margin-bottom: 0;
+  font-family: 'Raleway';
+  font-weight: 600;
+  font-size: 1.25rem;
+  line-height: 1.25;
+  color: #262f3c;
+  box-sizing: border-box;
+}
+
+.modal-close {
+  background: transparent;
+  border: 0;
+}
+
+.modal-header .modal-close:before { content: "\2715"; }
+
+.modal-content {
+  margin-top: 2rem;
+  margin-bottom: 2rem;
+  line-height: 1.5;
+  color: rgba(0,0,0,.8);
+}
+
+.modal-btn {
+  font-size: .875rem;
+  padding-left: 1rem;
+  padding-right: 1rem;
+  padding-top: .5rem;
+  padding-bottom: .5rem;
+  background-color: #e6e6e6;
+  color: rgba(0,0,0,.8);
+  border-radius: .25rem;
+  border-style: none;
+  border-width: 0;
+  cursor: pointer;
+  -webkit-appearance: button;
+  text-transform: none;
+  overflow: visible;
+  line-height: 1.15;
+  margin: 5px;
+  will-change: transform;
+  -moz-osx-font-smoothing: grayscale;
+  -webkit-backface-visibility: hidden;
+  backface-visibility: hidden;
+  -webkit-transform: translateZ(0);
+  transform: translateZ(0);
+  transition: -webkit-transform .25s ease-out;
+  transition: transform .25s ease-out;
+  transition: transform .25s ease-out,-webkit-transform .25s ease-out;
+}
+
+.modal-btn:focus, .modal-btn:hover {
+  -webkit-transform: scale(1.05);
+  transform: scale(1.05);
+}
+
+.modal-btn-primary {
+  background-color: #262f3c;
+  color: #fff;
+}
+
+.modal-footer {
+  display: flex;
+  justify-content: space-around;
+}
+
+/**************************\
+  Demo Animation Style
+\**************************/
+@keyframes mmfadeIn {
+    from { opacity: 0; }
+      to { opacity: 1; }
+}
+
+@keyframes mmfadeOut {
+    from { opacity: 1; }
+      to { opacity: 0; }
+}
+
+@keyframes mmslideIn {
+  from { transform: translateY(15%); }
+    to { transform: translateY(0); }
+}
+
+@keyframes mmslideOut {
+    from { transform: translateY(0); }
+    to { transform: translateY(-10%); }
+}
+
+.micromodal-slide {
+  display: none;
+}
+
+.micromodal-slide.is-open {
+  display: block;
+}
+
+.micromodal-slide[aria-hidden="false"] .modal-overlay {
+  animation: mmfadeIn .3s cubic-bezier(0.0, 0.0, 0.2, 1);
+}
+
+.micromodal-slide[aria-hidden="false"] .modal-container {
+  animation: mmslideIn .3s cubic-bezier(0, 0, .2, 1);
+}
+
+.micromodal-slide[aria-hidden="true"] .modal-overlay {
+  animation: mmfadeOut .3s cubic-bezier(0.0, 0.0, 0.2, 1);
+}
+
+.micromodal-slide[aria-hidden="true"] .modal-container {
+  animation: mmslideOut .3s cubic-bezier(0, 0, .2, 1);
+}
+
+.micromodal-slide .modal-container,
+.micromodal-slide .modal-overlay {
+  will-change: transform;
+}
\ No newline at end of file
diff --git a/ui/src/assets/perfetto.scss b/ui/src/assets/perfetto.scss
index 059a98a..ca03a81 100644
--- a/ui/src/assets/perfetto.scss
+++ b/ui/src/assets/perfetto.scss
@@ -17,3 +17,4 @@
 @import 'sidebar';
 @import 'topbar';
 @import 'record';
+@import 'modal';
diff --git a/ui/src/assets/topbar.scss b/ui/src/assets/topbar.scss
index 6c4bf3a..c346488 100644
--- a/ui/src/assets/topbar.scss
+++ b/ui/src/assets/topbar.scss
@@ -23,7 +23,10 @@
     overflow: visible;
     background-color: hsl(215, 1%, 95%);
     box-shadow: 0px -3px 14px 2px #bbb;
-    line-height: var(--topbar-height);
+    min-height: var(--topbar-height);
+    display: flex;
+    justify-content: center;
+    align-items: center;
     .omnibox {
         @include omnibox-width();
         @include transition(0.25s);
@@ -33,13 +36,10 @@
         border-radius: 20px;
         background-color: #fcfcfc;
         border: 0;
-        margin: 6px auto 0 auto;
-        height: 36px;
         line-height: 36px;
         &:before {
             @include material-icon('search');
             vertical-align: middle;
-            font-size: 32px;
             margin: 5px;
             color: #aaa;
             grid-area: icon;
@@ -130,10 +130,8 @@
         bottom: 0;
         height: 1px;
         width: 100%;
-        background-color: #f2f2f2;
-    }
-
-    .progress-anim {
+      }
+      .progress-anim {
         &:before {
             content: '';
             position: absolute;
diff --git a/ui/src/chrome_extension/chrome_tracing_controller.ts b/ui/src/chrome_extension/chrome_tracing_controller.ts
index d4ea29e..0ba2314 100644
--- a/ui/src/chrome_extension/chrome_tracing_controller.ts
+++ b/ui/src/chrome_extension/chrome_tracing_controller.ts
@@ -1,167 +1,173 @@
-import Protocol from 'devtools-protocol';
-// TODO(nicomazz): Use noice-json-rpc.
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import {Protocol} from 'devtools-protocol';
+import {ProtocolProxyApi} from 'devtools-protocol/types/protocol-proxy-api';
+import * as rpc from 'noice-json-rpc';
 import {TraceConfig} from '../common/protos';
+import {
+  GetTraceStatsResponse,
+  ReadBuffersResponse
+} from '../controller/consumer_port_types';
+import {perfetto} from '../gen/protos';
+
+import {DevToolsSocket} from './devtools_socket';
 
 const CHUNK_SIZE: number = 1024 * 1024 * 64;
 
-export class ChromeTraceController {
-  recordingTarget: chrome.debugger.Debuggee|null = null;
-  streamHandle: string|undefined = undefined;
-  startTracingSendResponse: Function|null = null;
-  dataBuffer = '';
+export class ChromeTracingController {
+  private streamHandle: string|undefined = undefined;
+  private uiPort: chrome.runtime.Port;
+  private api: ProtocolProxyApi.ProtocolApi;
+  private devtoolsSocket: DevToolsSocket;
+  private lastBufferUsageEvent: Protocol.Tracing.BufferUsageEvent|undefined;
 
-  constructor() {
-    chrome.debugger.onEvent.addListener(this.onEvent.bind(this));
-    chrome.debugger.onDetach.addListener(this.onDetach.bind(this));
+  constructor(port: chrome.runtime.Port) {
+    this.uiPort = port;
+    this.devtoolsSocket = new DevToolsSocket();
+    this.devtoolsSocket.on('close', () => this.resetState());
+    const rpcClient = new rpc.Client(this.devtoolsSocket);
+    this.api = rpcClient.api();
+    this.api.Tracing.on('tracingComplete', this.onTracingComplete.bind(this));
+    this.api.Tracing.on('bufferUsage', this.onBufferUsage.bind(this));
   }
 
-  onMessage(
-      request: {method: string, traceConfig: Uint8Array},
-      _sender: chrome.runtime.MessageSender, sendResponse: Function) {
-    console.log('OnMessage: ', request);
+  sendMessage(message: object) {
+    this.uiPort.postMessage(message);
+  }
+
+  sendErrorMessage(error: string) {
+    this.uiPort.postMessage({type: 'ErrorResponse', result: {error}});
+  }
+
+  onMessage(request: {method: string, traceConfig: Uint8Array}) {
     switch (request.method) {
       case 'EnableTracing':
-        this.cleanState();
-        this.startTracingSendResponse = sendResponse;
-        const traceConfig =
-            TraceConfig.decode(new Uint8Array(request.traceConfig));
-        this.handleStartTracing(traceConfig);
-        break;
-      case 'StartTracing':
-        sendResponse({
-          answer: 'no-op, start tracing happens when enable tracing is called.'
-        });
+        this.enableTracing(request);
         break;
       case 'FreeBuffers':
-        sendResponse({answer: 'Freeing buffers'});
-        this.handleFreeBuffers();
+        this.freeBuffers();
         break;
       case 'ReadBuffers':
-        this.handleReadBuffers(sendResponse);
+        this.readBuffers();
         break;
-      case 'StopTracing':
-        this.startTracingSendResponse = sendResponse;
-        this.handleStopTracing();
+      case 'DisableTracing':
+        this.disableTracing();
+        break;
+      case 'GetTraceStats':
+        this.getTraceStats();
         break;
       default:
-        sendResponse({error: 'Action not recognised'});
+        this.sendErrorMessage('Action not recognised');
         console.log('Received not recognized message');
         break;
     }
   }
 
-  cleanState() {
-    this.recordingTarget = null;
-    this.streamHandle = undefined;
-    this.startTracingSendResponse = null;
-    this.dataBuffer = '';
+  enableTracing(request: {method: string, traceConfig: Uint8Array}) {
+    this.resetState();
+    const traceConfig = TraceConfig.decode(new Uint8Array(request.traceConfig));
+    const chromeConfig = this.extractChromeConfig(traceConfig);
+    this.handleStartTracing(chromeConfig);
   }
 
-  onEvent(_source: chrome.debugger.Debuggee, method: string, params?: object) {
-    if (method === 'Tracing.tracingComplete' && params) {
-      this.streamHandle =
-          (params as Protocol.Tracing.TracingCompleteEvent).stream;
-      this.notifyFrontendStreamReady();
+  extractChromeConfig(perfettoConfig: TraceConfig):
+      Protocol.Tracing.TraceConfig {
+    for (const ds of perfettoConfig.dataSources) {
+      if (ds.config && ds.config.name === 'org.chromium.trace_event' &&
+          ds.config.chromeConfig && ds.config.chromeConfig.traceConfig) {
+        const chromeConfigJsonString = ds.config.chromeConfig.traceConfig;
+        return JSON.parse(chromeConfigJsonString) as
+            Protocol.Tracing.TraceConfig;
+      }
     }
+    return {};
   }
 
-  notifyFrontendStreamReady() {
-    // TODO(nicomazz): Send the response in a separate way.
-    if (this.startTracingSendResponse) {
-      this.startTracingSendResponse({recordingReady: 1});
+  freeBuffers() {
+    this.devtoolsSocket.detach();
+    this.sendMessage({type: 'FreeBuffersResponse'});
+  }
+
+  async readBuffers(offset = 0) {
+    // TODO(nicomazz): Add error handling also in the frontend.
+    if (!this.devtoolsSocket.isAttached() || this.streamHandle === undefined) {
+      this.sendErrorMessage('No tracing session to read from');
+      return;
     }
-  }
 
-  handleStartTracing(traceConfig: TraceConfig) {
-    const args: Protocol.Tracing.StartRequest = {
-      traceConfig: {includedCategories: []},
-      streamFormat: 'proto',
-      transferMode: 'ReturnAsStream',
-      streamCompression: 'gzip'
+    const res = await this.api.IO.read(
+        {handle: this.streamHandle, offset, size: CHUNK_SIZE});
+    if (res === undefined) return;
+
+    const chunk = res.base64Encoded ? atob(res.data) : res.data;
+    // TODO(nicomazz): remove the conversion to unknown when we stream each
+    // chunk to the trace processor.
+    const response: ReadBuffersResponse = {
+      type: 'ReadBuffersResponse',
+      slices:
+          [{data: chunk as unknown as Uint8Array, lastSliceForPacket: res.eof}]
     };
-    this.findAndAttachTarget(t => {
-      chrome.debugger.sendCommand(t, 'Tracing.start', args, results => {
-        console.log('tracing started with config:', traceConfig, results);
-        // For initial testing, the recording is stopped after 3 seconds.
-        setTimeout(() => {
-          this.handleStopTracing();
-        }, 3000);
-      });
-    });
+    this.sendMessage(response);
+    if (res.eof) return;
+    this.readBuffers(offset + res.data.length);
   }
 
-  findTarget(then: (target: chrome.debugger.Debuggee) => void) {
-    chrome.debugger.getTargets(targets => {
-      const perfettoTab =
-          targets.find((target) => target.title.includes('Perfetto'));
-      if (perfettoTab === undefined) {
-        console.log('No perfetto tab found');
-        return;
-      }
-      const t: chrome.debugger.Debuggee = {targetId: perfettoTab.id};
-      this.recordingTarget = t;
-      then(t);
-    });
+  async disableTracing() {
+    await this.api.Tracing.end();
+    this.sendMessage({type: 'DisableTracingResponse'});
   }
 
-  findAndAttachTarget(then: (target: chrome.debugger.Debuggee) => void) {
-    this.findTarget(t => {
-      chrome.debugger.attach(t, /*requiredVersion=*/ '1.3', () => {
-        then(t);
-      });
-    });
-  }
-
-  handleStopTracing() {
-    if (this.recordingTarget === null) {
-      console.log('No recordings in progress');
-      return;
+  getTraceStats() {
+    let percentFull = 0;  // If the statistics are not available yet, it is 0.
+    if (this.lastBufferUsageEvent && this.lastBufferUsageEvent.percentFull) {
+      percentFull = this.lastBufferUsageEvent.percentFull;
     }
-    chrome.debugger.sendCommand(
-        this.recordingTarget, 'Tracing.end', undefined, _ => {});
+    const stats: perfetto.protos.ITraceStats = {
+      bufferStats:
+          [{bufferSize: 1000, bytesWritten: Math.round(percentFull * 1000)}]
+    };
+    const response: GetTraceStatsResponse = {
+      type: 'GetTraceStatsResponse',
+      traceStats: stats
+    };
+    this.sendMessage(response);
   }
 
-  handleFreeBuffers() {
-    if (this.recordingTarget !== null) {
-      chrome.debugger.detach(this.recordingTarget, () => {
-        this.recordingTarget = null;
-      });
-    }
-  }
-
-  handleReadBuffers(sendResponse: Function, offset = 0) {
-    // TODO(nicomazz): Send back the response each time a chunk is readed.
-    if (this.recordingTarget === null || this.streamHandle === undefined) {
-      return;
-    }
-    this.readBuffer(this.streamHandle, offset, res => {
-      if (res === undefined) return;
-      const chunk = res.base64Encoded ? atob(res.data) : res.data;
-      this.dataBuffer += chunk;
-      if (res.eof) {
-        sendResponse({traceData: this.dataBuffer});
-        return;
-      }
-      this.handleReadBuffers(sendResponse, offset + res.data.length);
-    });
-  }
-
-  readBuffer(
-      handle: string, offset: number,
-      then: (res: Protocol.IO.ReadResponse) => void) {
-    if (this.recordingTarget === null) return;
-    const readRequest:
-        Protocol.IO.ReadRequest = {handle, offset, size: CHUNK_SIZE};
-    chrome.debugger.sendCommand(
-        this.recordingTarget,
-        'IO.read',
-        readRequest,
-        res => then(res as Protocol.IO.ReadResponse));
-  }
-
-  onDetach(source: chrome.debugger.Debuggee, reason: string) {
-    console.log('source detached: ', source, 'reason: ', reason);
-    this.recordingTarget = null;
+  resetState() {
+    this.devtoolsSocket.detach();
     this.streamHandle = undefined;
   }
-}
\ No newline at end of file
+
+  onTracingComplete(params: Protocol.Tracing.TracingCompleteEvent) {
+    this.streamHandle = params.stream;
+    this.sendMessage({type: 'EnableTracingResponse'});
+  }
+
+  onBufferUsage(params: Protocol.Tracing.BufferUsageEvent) {
+    this.lastBufferUsageEvent = params;
+  }
+
+  handleStartTracing(traceConfig: Protocol.Tracing.TraceConfig) {
+    this.devtoolsSocket.findAndAttachTarget(async _ => {
+      await this.api.Tracing.start({
+        traceConfig,
+        streamFormat: 'proto',
+        transferMode: 'ReturnAsStream',
+        streamCompression: 'gzip',
+        bufferUsageReportingInterval: 200
+      });
+    });
+  }
+}
diff --git a/ui/src/chrome_extension/devtools_socket.ts b/ui/src/chrome_extension/devtools_socket.ts
new file mode 100644
index 0000000..aa23f8f
--- /dev/null
+++ b/ui/src/chrome_extension/devtools_socket.ts
@@ -0,0 +1,107 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as rpc from 'noice-json-rpc';
+
+// To really understand how this works it is useful to see the implementation
+// of noice-json-rpc.
+export class DevToolsSocket implements rpc.LikeSocket {
+  private messageCallback: Function = (_: string) => {};
+  private openCallback: Function = () => {};
+  private closeCallback: Function = () => {};
+  private target: chrome.debugger.Debuggee|undefined;
+
+  constructor() {
+    chrome.debugger.onDetach.addListener(this.onDetach.bind(this));
+    chrome.debugger.onEvent.addListener((_source, method, params) => {
+      if (this.messageCallback) {
+        const msg: rpc.JsonRpc2.Notification = {method, params};
+        this.messageCallback(JSON.stringify(msg));
+      }
+    });
+  }
+
+  send(message: string): void {
+    if (this.target === undefined) return;
+
+    const msg: rpc.JsonRpc2.Request = JSON.parse(message);
+    chrome.debugger.sendCommand(
+        this.target, msg.method, msg.params, (result) => {
+          if (result === undefined) result = {};
+          const response: rpc.JsonRpc2.Response = {id: msg.id, result};
+          this.messageCallback(JSON.stringify(response));
+        });
+  }
+
+  // This method will be called once for each event soon after the creation of
+  // this object. To understand better what happens, checking the implementation
+  // of noice-json-rpc is very useful.
+  // While the events "message" and "open" are for implementing the LikeSocket,
+  // "close" is a callback set from ChromeTracingController, to reset the state
+  // after a detach.
+  on(event: string, cb: Function) {
+    if (event === 'message') {
+      this.messageCallback = cb;
+    } else if (event === 'open') {
+      this.openCallback = cb;
+    } else if (event === 'close') {
+      this.closeCallback = cb;
+    }
+  }
+
+  removeListener(_event: string, _cb: Function) {
+    throw new Error('Call unexpected');
+  }
+
+  findTarget(then: (target: chrome.debugger.Debuggee) => void) {
+    chrome.debugger.getTargets(targets => {
+      const perfettoTab =
+          targets.find(target => target.title.includes('Perfetto'));
+      if (perfettoTab === undefined) {
+        console.log('No perfetto tab found');
+        return;
+      }
+      this.target = {targetId: perfettoTab.id};
+      then(this.target);
+    });
+  }
+
+  findAndAttachTarget(then: (target: chrome.debugger.Debuggee) => void) {
+    this.findTarget(t => {
+      chrome.debugger.attach(t, /*requiredVersion=*/ '1.3', () => {
+        this.openCallback();
+        then(t);
+      });
+    });
+  }
+
+  detach() {
+    if (this.target === undefined) return;
+
+    chrome.debugger.detach(this.target, () => {
+      this.target = undefined;
+    });
+  }
+
+  onDetach(_source: chrome.debugger.Debuggee, _reason: string) {
+    if (_source === this.target) {
+      this.target = undefined;
+      this.closeCallback();
+    }
+  }
+
+  isAttached(): boolean {
+    return this.target !== undefined;
+  }
+}
diff --git a/ui/src/chrome_extension/index.ts b/ui/src/chrome_extension/index.ts
index 95f20c5..468857b 100644
--- a/ui/src/chrome_extension/index.ts
+++ b/ui/src/chrome_extension/index.ts
@@ -1,34 +1,55 @@
-// import {TraceConfig} from '../common/protos';
-import {ChromeTraceController} from './chrome_tracing_controller';
+// 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.
 
-const chromeTraceController = new ChromeTraceController();
+import {ChromeTracingController} from './chrome_tracing_controller';
+
+let chromeTraceController: ChromeTracingController|undefined = undefined;
 
 chrome.runtime.onInstalled.addListener(() => {
   enableOnlyOnPerfettoHost();
   // Listen for messages from the perfetto ui.
-  chrome.runtime.onMessageExternal.addListener(onMessage);
+  chrome.runtime.onConnectExternal.addListener(port => {
+    chromeTraceController = new ChromeTracingController(port);
+    port.onMessage.addListener(onUIMessage);
+  });
 });
 
-function onMessage(
-    request: {method: string, traceConfig: Uint8Array},
-    _sender: chrome.runtime.MessageSender,
-    sendResponse: Function) {
-  if (request.method === 'ExtensionVersion') {
-    sendResponse({version: chrome.runtime.getManifest().version});
+function onUIMessage(
+    message: {method: string, traceConfig: Uint8Array},
+    port: chrome.runtime.Port) {
+  if (message.method === 'ExtensionVersion') {
+    port.postMessage({version: chrome.runtime.getManifest().version});
     return;
   }
-  // In the future more targets will be supported.
-  chromeTraceController.onMessage(request, _sender, sendResponse);
+  // In the future, more targets will be supported.
+  if (chromeTraceController) chromeTraceController.onMessage(message);
 }
 
 function enableOnlyOnPerfettoHost() {
-  chrome.declarativeContent.onPageChanged.removeRules(undefined, () => {
-    chrome.declarativeContent.onPageChanged.addRules([{
+  function enableOnHostWithSuffix(suffix: string) {
+    return {
       conditions: [new chrome.declarativeContent.PageStateMatcher({
-        // TODO(nicomazz): Also enable on ui.perfetto.dev once we're ready.
-        pageUrl: {hostContains: 'perfetto.local'},
+        pageUrl: {hostSuffix: suffix},
       })],
       actions: [new chrome.declarativeContent.ShowPageAction()]
-    }]);
+    };
+  }
+  chrome.declarativeContent.onPageChanged.removeRules(undefined, () => {
+    chrome.declarativeContent.onPageChanged.addRules([
+      enableOnHostWithSuffix('.perfetto.local'),
+      enableOnHostWithSuffix('.perfetto.dev'),
+      enableOnHostWithSuffix('-dot-perfetto-ui.appspot.com'),
+    ]);
   });
 }
diff --git a/ui/src/chrome_extension/manifest.json b/ui/src/chrome_extension/manifest.json
index ce0caa4..3b48556 100644
--- a/ui/src/chrome_extension/manifest.json
+++ b/ui/src/chrome_extension/manifest.json
@@ -19,6 +19,10 @@
     "persistent": false
   },
   "externally_connectable": {
-    "matches": ["*://*.perfetto.local/*"]
+    "matches": [
+      "*://*.perfetto.local/*",
+      "*://*.perfetto.dev/*",
+      "*://*-dot-perfetto-ui.appspot.com/*"
+    ]
   }
 }
\ No newline at end of file
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index 7f561d7..f37ae0a 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -83,10 +83,10 @@
     state.videoEnabled = true;
   },
 
-  convertTraceToJson(_: StateDraft, args: {file: File, truncate: boolean}):
-      void {
-        ConvertTrace(args.file, args.truncate);
-      },
+  convertTraceToJson(
+      _: StateDraft, args: {file: File, truncate?: 'start'|'end'}): void {
+    ConvertTrace(args.file, args.truncate);
+  },
 
   openTraceFromUrl(state: StateDraft, args: {url: string}): void {
     clearTraceState(state);
@@ -325,6 +325,10 @@
     }
   },
 
+  setVideoOffset(state: StateDraft, args: {offset: number}): void {
+    state.videoOffset = args.offset;
+  },
+
   changeNoteColor(state: StateDraft, args: {id: string, newColor: string}):
       void {
         const note = state.notes[args.id];
@@ -403,7 +407,11 @@
 
   setExtensionAvailable(state: StateDraft, args: {available: boolean}): void {
     state.extensionInstalled = args.available;
-  }
+  },
+
+  updateBufferUsage(state: StateDraft, args: {percentage: number}): void {
+    state.bufferUsage = args.percentage;
+  },
 
 };
 
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index bc86c7c..be59fe9 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -160,10 +160,10 @@
 
   video: string | null;
   videoEnabled: boolean;
+  videoOffset: number;
+  videoNoteIds: string[];
   scrubbingEnabled: boolean;
   flagPauseEnabled: boolean;
-  videoNoteIds: string[];
-
   /**
    * Trace recording
    */
@@ -316,10 +316,10 @@
 
     video: null,
     videoEnabled: false,
+    videoOffset: 0,
+    videoNoteIds: [],
     scrubbingEnabled: false,
     flagPauseEnabled: false,
-    videoNoteIds: [],
-
     recordingInProgress: false,
     extensionInstalled: false,
   };
diff --git a/ui/src/common/time.ts b/ui/src/common/time.ts
index 33e13b8..58e2eda 100644
--- a/ui/src/common/time.ts
+++ b/ui/src/common/time.ts
@@ -31,6 +31,17 @@
   return ns / 1e9;
 }
 
+export function toNsFloor(seconds: number) {
+  return Math.floor(seconds * 1e9);
+}
+
+export function toNsCeil(seconds: number) {
+  return Math.ceil(seconds * 1e9);
+}
+
+export function toNs(seconds: number) {
+  return Math.round(seconds * 1e9);
+}
 
 // 1000000023ns -> "1.000 000 023"
 export function formatTimestamp(sec: number) {
diff --git a/ui/src/controller/consumer_port_types.ts b/ui/src/controller/consumer_port_types.ts
new file mode 100644
index 0000000..0e9bc0c
--- /dev/null
+++ b/ui/src/controller/consumer_port_types.ts
@@ -0,0 +1,41 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import {perfetto} from '../gen/protos';
+
+interface Typed {
+  type: string;
+}
+
+export interface ReadBuffersResponse extends
+    Typed, perfetto.protos.IReadBuffersResponse {}
+export interface EnableTracingResponse extends
+    Typed, perfetto.protos.IEnableTracingResponse {}
+export interface GetTraceStatsResponse extends
+    Typed, perfetto.protos.IGetTraceStatsResponse {}
+
+
+export function isReadBuffersResponse(obj: Typed): obj is ReadBuffersResponse {
+  return obj.type === 'ReadBuffersResponse';
+}
+
+export function isEnableTracingResponse(obj: Typed):
+    obj is EnableTracingResponse {
+  return obj.type === 'EnableTracingResponse';
+}
+
+export function isGetTraceStatsResponse(obj: Typed):
+    obj is GetTraceStatsResponse {
+  return obj.type === 'GetTraceStatsResponse';
+}
\ No newline at end of file
diff --git a/ui/src/controller/globals.ts b/ui/src/controller/globals.ts
index 5ff94f5..c5f5c18 100644
--- a/ui/src/controller/globals.ts
+++ b/ui/src/controller/globals.ts
@@ -104,7 +104,7 @@
   // TODO: this needs to be cleaned up.
   publish(
       what: 'OverviewData'|'TrackData'|'Threads'|'QueryResult'|'LegacyTrace'|
-      'SliceDetails'|'Loading',
+      'SliceDetails'|'Loading'|'BufferUsage',
       data: {}, transferList?: Transferable[]) {
     assertExists(this._frontend)
         .send<void>(`publish${what}`, [data], transferList);
diff --git a/ui/src/controller/logs_controller.ts b/ui/src/controller/logs_controller.ts
index 6e7735e..3d6e9ea 100644
--- a/ui/src/controller/logs_controller.ts
+++ b/ui/src/controller/logs_controller.ts
@@ -20,15 +20,15 @@
   LogEntriesKey,
   LogExistsKey
 } from '../common/logs';
-import {fromNs, TimeSpan} from '../common/time';
+import {fromNs, TimeSpan, toNsCeil, toNsFloor} from '../common/time';
 
 import {Controller} from './controller';
 import {App} from './globals';
 
 async function updateLogBounds(
     engine: Engine, span: TimeSpan): Promise<LogBounds> {
-  const vizStartNs = Math.floor(span.start * 1e9);
-  const vizEndNs = Math.ceil(span.end * 1e9);
+  const vizStartNs = toNsFloor(span.start);
+  const vizEndNs = toNsCeil(span.end);
 
   const countResult = await engine.queryOneRow(`
      select min(ts), max(ts), count(ts)
@@ -63,8 +63,8 @@
 async function updateLogEntries(
     engine: Engine, span: TimeSpan, pagination: Pagination):
     Promise<LogEntries> {
-  const vizStartNs = Math.floor(span.start * 1e9);
-  const vizEndNs = Math.ceil(span.end * 1e9);
+  const vizStartNs = toNsFloor(span.start);
+  const vizEndNs = toNsCeil(span.end);
   const vizSqlBounds = `ts >= ${vizStartNs} and ts <= ${vizEndNs}`;
 
   const rowsResult =
diff --git a/ui/src/controller/record_controller.ts b/ui/src/controller/record_controller.ts
index 3a0ec65..c73fa56 100644
--- a/ui/src/controller/record_controller.ts
+++ b/ui/src/controller/record_controller.ts
@@ -32,6 +32,14 @@
 import {MeminfoCounters, VmstatCounters} from '../common/protos';
 import {MAX_TIME, RecordConfig} from '../common/state';
 
+import {
+  EnableTracingResponse,
+  GetTraceStatsResponse,
+  isEnableTracingResponse,
+  isGetTraceStatsResponse,
+  isReadBuffersResponse,
+  ReadBuffersResponse
+} from './consumer_port_types';
 import {Controller} from './controller';
 import {App, globals} from './globals';
 
@@ -298,6 +306,10 @@
     protoCfg.dataSources.push(metadataDs);
   }
 
+  if (uiCfg.screenRecord) {
+    atraceCats.add('gfx');
+  }
+
   // Keep these last. The stages above can enrich them.
 
   if (sysStatsCfg !== undefined) {
@@ -395,8 +407,10 @@
   private app: App;
   private config: RecordConfig|null = null;
   private extensionPort: MessagePort;
-  private recordingInProgress: boolean|null = null;
+  private recordingInProgress = false;
   private consumerPort: ConsumerPort;
+  private traceBuffer = '';
+  private bufferUpdateInterval: ReturnType<typeof setTimeout>|undefined;
 
   constructor(args: {app: App, extensionPort: MessagePort}) {
     super('main');
@@ -406,50 +420,6 @@
     this.extensionPort.onmessage = this.onExtensionMessage.bind(this);
   }
 
-  requestRecording() {
-    console.log('Requesting recording');
-    if (this.extensionPort) {
-      this.extensionPort.postMessage({method: 'ReadBuffers'});
-    }
-  }
-
-  // TODO(nicomazz): Create different data types for each extension response,
-  // like "TraceCompleteEvent", "ReadBufferResponse"
-  onExtensionMessage(message: {
-    data: {recordingReady: number, traceData: string, readProgress: number}
-  }) {
-    const data = message.data;
-    console.log('message received from the extension:', data);
-    if (data === undefined) return;
-
-    if (data.recordingReady === 1) {
-      this.requestRecording();
-      return;
-    }
-    if (data.traceData !== undefined) {
-      // The trace is gzipped.
-      const compressedTraceProto = this.stringToArrayBuffer(data.traceData);
-      const uncompressedTrace = ungzip(compressedTraceProto);
-
-      // Open trace in UI.
-      globals.dispatch(
-          Actions.openTraceFromBuffer({buffer: uncompressedTrace.buffer}));
-      return;
-    }
-    if (data.readProgress) {
-      // TODO(nicomazz): update loading state
-    }
-  }
-
-  stringToArrayBuffer(str: string): Uint8Array {
-    const buf = new ArrayBuffer(str.length);
-    const bufView = new Uint8Array(buf);
-    for (let i = 0, strLen = str.length; i < strLen; i++) {
-      bufView[i] = str.charCodeAt(i);
-    }
-    return bufView;
-  }
-
   run() {
     if (this.app.state.recordConfig === this.config &&
         this.app.state.recordingInProgress === this.recordingInProgress) {
@@ -485,11 +455,74 @@
   }
 
   startRecordTrace(traceConfig: TraceConfig) {
+    this.scheduleBufferUpdateRequests();
     this.consumerPort.enableTracing({traceConfig});
   }
 
   stopRecordTrace() {
-    // TODO(nicomazz): Implement stopping trace & retrieving trace data.
+    if (this.bufferUpdateInterval) clearInterval(this.bufferUpdateInterval);
+    this.consumerPort.disableTracing({});
+  }
+
+  scheduleBufferUpdateRequests() {
+    if (this.bufferUpdateInterval) clearInterval(this.bufferUpdateInterval);
+    this.bufferUpdateInterval = setInterval(() => {
+      this.consumerPort.getTraceStats({});
+    }, 200);
+  }
+
+  readBuffers() {
+    if (this.extensionPort) this.consumerPort.readBuffers({});
+  }
+
+  onExtensionMessage(message: {
+    data: EnableTracingResponse|ReadBuffersResponse|GetTraceStatsResponse
+  }) {
+    const data = message.data;
+    if (data === undefined) return;
+
+    // TODO(nicomazz): Add error handling.
+    if (isReadBuffersResponse(data)) {
+      if (!data.slices) return;
+      this.traceBuffer += data.slices[0].data;
+      // TODO(nicomazz): Stream the chunks directly in the trace processor.
+      if (data.slices[0].lastSliceForPacket) this.openTraceInUI();
+    } else if (isEnableTracingResponse(data)) {
+      this.readBuffers();
+    } else if (isGetTraceStatsResponse(data)) {
+      const percentage = this.getBufferUsagePercentage(data);
+      if (percentage) {
+        globals.publish('BufferUsage', {percentage});
+      }
+    }
+  }
+
+  openTraceInUI() {
+    this.consumerPort.freeBuffers({});
+    const trace = ungzip(this.stringToArrayBuffer(this.traceBuffer));
+    globals.dispatch(Actions.openTraceFromBuffer({buffer: trace.buffer}));
+    this.traceBuffer = '';
+  }
+
+  stringToArrayBuffer(str: string): Uint8Array {
+    const buf = new ArrayBuffer(str.length);
+    const bufView = new Uint8Array(buf);
+    for (let i = 0, strLen = str.length; i < strLen; i++) {
+      bufView[i] = str.charCodeAt(i);
+    }
+    return bufView;
+  }
+
+
+  getBufferUsagePercentage(data: GetTraceStatsResponse): number {
+    if (!data.traceStats || !data.traceStats.bufferStats) return 0.0;
+    let used = 0.0, total = 0.0;
+    for (const buffer of data.traceStats.bufferStats) {
+      used += buffer.bytesWritten as number;
+      total += buffer.bufferSize as number;
+    }
+    if (total === 0.0) return 0;
+    return used / total;
   }
 
   // This forwards the messages that have to be sent to the extension to the
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 9ac9d78..eedb6a5 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -25,6 +25,7 @@
 import {Engine} from '../common/engine';
 import {NUM, NUM_NULL, rawQueryToRows, STR_NULL} from '../common/protos';
 import {SCROLLING_TRACK_GROUP} from '../common/state';
+import {toNs, toNsCeil, toNsFloor} from '../common/time';
 import {TimeSpan} from '../common/time';
 import {QuantizedLoad, ThreadDesc} from '../frontend/globals';
 import {ANDROID_LOGS_TRACK_KIND} from '../tracks/android_log/common';
@@ -571,9 +572,9 @@
           'Loading overview ' +
           `${Math.round((step + 1) / numSteps * 1000) / 10}%`);
       const startSec = traceTime.start + step * stepSec;
-      const startNs = Math.floor(startSec * 1e9);
+      const startNs = toNsFloor(startSec);
       const endSec = startSec + stepSec;
-      const endNs = Math.ceil(endSec * 1e9);
+      const endNs = toNsCeil(endSec);
 
       // Sched overview.
       const schedRows = await engine.query(
@@ -595,8 +596,8 @@
     }
 
     // Slices overview.
-    const traceStartNs = traceTime.start * 1e9;
-    const stepSecNs = stepSec * 1e9;
+    const traceStartNs = toNs(traceTime.start);
+    const stepSecNs = toNs(stepSec);
     const sliceSummaryQuery = await engine.query(
         `select bucket, upid, sum(utid_sum) / cast(${stepSecNs} as float) ` +
         `as upid_sum from thread inner join ` +
diff --git a/ui/src/controller/trace_converter.ts b/ui/src/controller/trace_converter.ts
index d45970b..5941cb4 100644
--- a/ui/src/controller/trace_converter.ts
+++ b/ui/src/controller/trace_converter.ts
@@ -17,7 +17,7 @@
 
 import {globals} from './globals';
 
-export function ConvertTrace(trace: Blob, truncate: boolean) {
+export function ConvertTrace(trace: Blob, truncate?: 'start'|'end') {
   const mod = trace_to_text({
     noInitialRun: true,
     locateFile: (s: string) => s,
@@ -26,10 +26,11 @@
     onRuntimeInitialized: () => {
       updateStatus('Converting trace');
       const outPath = '/trace.json';
-      if (truncate) {
-        mod.callMain(['json', '--truncate', '/fs/trace.proto', outPath]);
-      } else {
+      if (truncate === undefined) {
         mod.callMain(['json', '/fs/trace.proto', outPath]);
+      } else {
+        mod.callMain(
+            ['json', '--truncate', truncate, '/fs/trace.proto', outPath]);
       }
       updateStatus('Trace conversion completed');
       const fsNode = mod.FS.lookupPath(outPath).node;
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index 0e979c0..e6c2a9b 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -67,6 +67,7 @@
   private _threadMap?: ThreadMap = undefined;
   private _sliceDetails?: SliceDetails = undefined;
   private _isLoading = false;
+  private _bufferUsage?: number = undefined;
 
   initialize(dispatch: Dispatch, controllerWorker: Worker) {
     this._dispatch = dispatch;
@@ -136,6 +137,14 @@
     return this._isLoading;
   }
 
+  get bufferUsage() {
+    return this._bufferUsage;
+  }
+
+  setBufferUsage(bufferUsage: number) {
+    this._bufferUsage = bufferUsage;
+  }
+
   setTrackData(id: string, data: {}) {
     this.trackDataStore.set(id, data);
   }
diff --git a/ui/src/frontend/index.ts b/ui/src/frontend/index.ts
index 1106113..c68aefe 100644
--- a/ui/src/frontend/index.ts
+++ b/ui/src/frontend/index.ts
@@ -15,8 +15,10 @@
 import '../tracks/all_frontend';
 
 import {applyPatches, Patch} from 'immer';
+import * as MicroModal from 'micromodal';
 import * as m from 'mithril';
 
+import {assertExists} from '../base/logging';
 import {forwardRemoteCalls} from '../base/remote';
 import {Actions} from '../common/actions';
 import {
@@ -119,6 +121,11 @@
     openBufferWithLegacyTraceViewer('trace.json', str, 0);
   }
 
+  publishBufferUsage(args: {percentage: number}) {
+    globals.setBufferUsage(args.percentage);
+    this.redraw();
+  }
+
   private redraw(): void {
     if (globals.state.route &&
         globals.state.route !== this.router.getRouteFromHash()) {
@@ -129,26 +136,15 @@
   }
 }
 
-function checkExtensionAvailability() {
-  function setAvailable(available: boolean) {
-    globals.dispatch(Actions.setExtensionAvailable({
-      available,
-    }));
-  }
-  // Check if the extension is installed.
-  if (chrome.runtime === undefined) {
-    setAvailable(false);
-    return;
-  }
-
-  chrome.runtime.sendMessage(
-      EXTENSION_ID, {method: 'ExtensionVersion'}, resp => {
-        setAvailable(
-            chrome.runtime.lastError === undefined && resp !== undefined &&
-            resp.version !== null);
-      });
+function setExtensionAvailability(available: boolean) {
+  if (available) console.log('Extension available!');
+  globals.dispatch(Actions.setExtensionAvailable({
+    available,
+  }));
 }
 
+
+
 function main() {
   const controller = new Worker('controller_bundle.js');
   controller.onerror = e => {
@@ -156,14 +152,20 @@
   };
   const frontendChannel = new MessageChannel();
   const controllerChannel = new MessageChannel();
-  const extensionChannel = new MessageChannel();
+  const extensionLocalChannel = new MessageChannel();
+
+
   controller.postMessage(
       {
         frontendPort: frontendChannel.port1,
         controllerPort: controllerChannel.port1,
-        extensionPort: extensionChannel.port1
+        extensionPort: extensionLocalChannel.port1
       },
-      [frontendChannel.port1, controllerChannel.port1, extensionChannel.port1]);
+      [
+        frontendChannel.port1,
+        controllerChannel.port1,
+        extensionLocalChannel.port1
+      ]);
 
   const dispatch =
       controllerChannel.port2.postMessage.bind(controllerChannel.port2);
@@ -180,15 +182,28 @@
 
   // We proxy messages between the extension and the controller because the
   // controller's worker can't access chrome.runtime.
-  extensionChannel.port2.onmessage = ({data}) => {
-    chrome.runtime.sendMessage(EXTENSION_ID, data, (response) => {
-      extensionChannel.port2.postMessage(response);
-    });
+  const extensionPort = chrome.runtime !== undefined ?
+      chrome.runtime.connect(EXTENSION_ID) :
+      undefined;  // Will be null if the extension is not installed.
+  setExtensionAvailability(extensionPort !== undefined);
+  if (extensionPort) {
+    // This forwards the messages from the extension to the controller.
+    extensionPort.onMessage.addListener(
+        (message: object, _port: chrome.runtime.Port) => {
+          extensionLocalChannel.port2.postMessage(message);
+        });
+  }
+
+  // This forwards the messages from the controller to the extension
+  extensionLocalChannel.port2.onmessage = ({data}) => {
+    if (extensionPort) extensionPort.postMessage(data);
   };
-  checkExtensionAvailability();
+
+
+  const main = assertExists(document.body.querySelector('main'));
 
   globals.rafScheduler.domRedraw = () =>
-      m.render(document.body, m(router.resolve(globals.state.route)));
+      m.render(main, m(router.resolve(globals.state.route)));
 
   // Add support for opening traces from postMessage().
   window.addEventListener('message', postMessageHandler, {passive: true});
@@ -211,6 +226,8 @@
   }, {passive: false});
 
   router.navigateToCurrentHash();
+
+  MicroModal.init();
 }
 
 main();
diff --git a/ui/src/frontend/modal.ts b/ui/src/frontend/modal.ts
new file mode 100644
index 0000000..8791e58
--- /dev/null
+++ b/ui/src/frontend/modal.ts
@@ -0,0 +1,67 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as MicroModal from 'micromodal';
+import * as m from 'mithril';
+
+// We need any here so we can accept vnodes with arbitrary attrs.
+// tslint:disable-next-line:no-any
+export type AnyAttrsVnode = m.Vnode<any, {}>;
+
+interface ModalDefinition {
+  title: string;
+  content: AnyAttrsVnode;
+  buttons: Button[];
+}
+
+export interface Button {
+  text: string;
+  primary: boolean;
+  id: string;
+  action: () => void;
+}
+
+export async function showModal(attrs: ModalDefinition): Promise<void> {
+  const modal = document.querySelector('#main-modal') as HTMLElement;
+  m.render(
+      modal,
+      m('.modal-overlay[data-micromodal-close]',
+        {tabindex: -1},
+        m('.modal-container[aria-labelledby=mm-title][aria-model][role=dialog]',
+          m('header.modal-header',
+            m('h2.modal-title', {id: 'mm-title'}, attrs.title),
+            m('button.modal-close[aria-label=Close Modal]' +
+              '[data-micromodal-close]')),
+          m('main.modal-content', attrs.content),
+          m('footer.modal-footer', ...makeButtons(attrs.buttons)))));
+  return new Promise(resolve => {
+    MicroModal.show(
+        'main-modal', {onClose: () => resolve, awaitCloseAnimation: true});
+  });
+}
+
+function makeButtons(buttonDefinition: Button[]): Array<m.Vnode<Button>> {
+  const buttons: Array<m.Vnode<Button>> = [];
+  buttonDefinition.forEach(button => {
+    buttons.push(
+        m('button[data-micromodal-close].modal-btn',
+          {
+            class: button.primary ? 'modal-btn-primary' : '',
+            id: button.id,
+            onclick: button.action
+          },
+          button.text));
+  });
+  return buttons;
+}
diff --git a/ui/src/frontend/record_page.ts b/ui/src/frontend/record_page.ts
index 829d420..4480127 100644
--- a/ui/src/frontend/record_page.ts
+++ b/ui/src/frontend/record_page.ts
@@ -520,19 +520,18 @@
               img: null,
               descr: `Records the screen along with running a trace. Max
                   time of recording is 3 minutes (180 seconds).`,
-              setEnabled: (cfg, val) => cfg.screenRecord = val,
-              isEnabled: (cfg) => cfg.screenRecord,
-            } as ProbeAttrs,
-            m(Slider, {
-              title: 'Max duration',
-              icon: 'timer',
-              values: [S(10), S(15), S(30), S(60), M(2), M(3)],
-              isTime: true,
-              unit: 'm:s',
-              set: (cfg, val) => cfg.durationMs = val,
-              get: (cfg) => cfg.durationMs,
-            } as SliderAttrs)) :
-          null);
+          setEnabled: (cfg, val) => cfg.screenRecord = val,
+          isEnabled: (cfg) => cfg.screenRecord,
+        } as ProbeAttrs,
+        m(Slider, {
+          title: 'Max duration',
+          icon: 'timer',
+          values: [S(10), S(15), S(30), S(60), M(2), M(3)],
+          isTime: true,
+          unit: 'm:s',
+          set: (cfg, val) => cfg.durationMs = val,
+          get: (cfg) => cfg.durationMs,
+        } as SliderAttrs),) : null);
 }
 
 function Instructions(cssClass: string) {
@@ -550,8 +549,10 @@
   const pbtx = data ? data.pbtxt : '';
   let cmd = '';
   if (cfg.screenRecord) {
-    cmd += `adb shell screenrecord --time-limit ${time}`;
-    cmd += ' "/sdcard/tracescr.mp4" &\\\n';
+    // Half-second delay to ensure Perfetto starts tracing before screenrecord
+    // starts recording
+    cmd += `(sleep 0.5 && adb shell screenrecord --time-limit ${time}`;
+    cmd += ' "/sdcard/tracescr.mp4") &\\\n';
   }
   cmd += 'adb shell perfetto \\\n';
   cmd += '  -c - --txt \\\n';
@@ -607,6 +608,9 @@
     globals.dispatch(Actions.setRecordConfig({config: traceCfg}));
   };
 
+  const bufferUsagePercentage =
+      ((globals.bufferUsage ? globals.bufferUsage : 0.0) * 100).toFixed(1);
+
   return m(
       `.record-section.instructions${cssClass}`,
       m('header', 'Instructions'),
@@ -623,11 +627,21 @@
       globals.state.extensionInstalled ?
           [
             m('button',
-              {onclick: () => globals.dispatch(Actions.startRecording({}))},
+              {
+                onclick: () => globals.dispatch(Actions.startRecording({})),
+                disabled: globals.state.recordingInProgress
+              },
               'Start Recording'),
             m('button',
-              {onclick: () => globals.dispatch(Actions.stopRecording({}))},
-              'Stop Recording')
+              {
+                onclick: () => globals.dispatch(Actions.stopRecording({})),
+                disabled: !globals.state.recordingInProgress
+              },
+              'Stop Recording'),
+            m('label',
+              globals.state.recordingInProgress ?
+                  'Buffer usage: ' + bufferUsagePercentage + '%' :
+                  '')
           ] :
           []);
 }
diff --git a/ui/src/frontend/sidebar.ts b/ui/src/frontend/sidebar.ts
index d0d0fc6..0d1dbcd 100644
--- a/ui/src/frontend/sidebar.ts
+++ b/ui/src/frontend/sidebar.ts
@@ -15,12 +15,14 @@
 import * as m from 'mithril';
 
 import {Actions} from '../common/actions';
+import {QueryResponse} from '../common/queries';
 
 import {globals} from './globals';
 import {
   isLegacyTrace,
   openFileWithLegacyTraceViewer,
 } from './legacy_trace_viewer';
+import {showModal} from './modal';
 
 const ALL_PROCESSES_QUERY = 'select name, pid from process order by name;';
 
@@ -90,7 +92,7 @@
 }
 
 const EXAMPLE_ANDROID_TRACE_URL =
-    'https://storage.googleapis.com/perfetto-misc/example_android_trace_30s_1';
+    'https://storage.googleapis.com/perfetto-misc/example_android_trace_15s';
 
 const EXAMPLE_CHROME_TRACE_URL =
     'https://storage.googleapis.com/perfetto-misc/example_chrome_trace_4s_1.json';
@@ -102,6 +104,11 @@
     expanded: true,
     items: [
       {t: 'Open trace file', a: popupFileSelectionDialog, i: 'folder_open'},
+      {
+        t: 'Open with legacy UI',
+        a: popupFileSelectionDialogOldUI,
+        i: 'filter_none'
+      },
       {t: 'Record new trace', a: navigateRecord, i: 'fiber_smart_record'},
       {t: 'Show timeline', a: navigateViewer, i: 'line_style'},
       {
@@ -119,23 +126,6 @@
     ],
   },
   {
-    title: 'Legacy UI',
-    expanded: true,
-    summary: 'Open trace with legacy UI',
-    items: [
-      {
-        t: 'Open with legacy UI',
-        a: popupFileSelectionDialogOldUI,
-        i: 'folder_open'
-      },
-      {
-        t: 'Truncate and open',
-        a: popupFileSelectionDialogOldUITruncate,
-        i: 'flip'
-      },
-    ],
-  },
-  {
     title: 'Example Traces',
     expanded: true,
     summary: 'Open an example trace',
@@ -224,26 +214,16 @@
   e.preventDefault();
   delete getFileElement().dataset['useCatapultLegacyUi'];
   delete getFileElement().dataset['video'];
-  delete getFileElement().dataset['truncate'];
   getFileElement().click();
 }
 
 function popupFileSelectionDialogOldUI(e: Event) {
   e.preventDefault();
   delete getFileElement().dataset['video'];
-  delete getFileElement().dataset['truncate'];
   getFileElement().dataset['useCatapultLegacyUi'] = '1';
   getFileElement().click();
 }
 
-function popupFileSelectionDialogOldUITruncate(e: Event) {
-  e.preventDefault();
-  delete getFileElement().dataset['video'];
-  getFileElement().dataset['useCatapultLegacyUi'] = '1';
-  getFileElement().dataset['truncate'] = '1';
-  getFileElement().click();
-}
-
 function popupVideoSelectionDialog(e: Event) {
   e.preventDefault();
   delete getFileElement().dataset['useCatapultLegacyUi'];
@@ -274,30 +254,89 @@
     // Switch back to the old catapult UI.
     if (isLegacyTrace(file.name)) {
       openFileWithLegacyTraceViewer(file);
-    } else {
-      if (e.target.dataset['truncate'] === '1') {
-        globals.dispatch(Actions.convertTraceToJson({file, truncate: true}));
-        return;
-      } else if (file.size > 1024 * 1024 * 50) {
-        const size = Math.round(file.size / (1024 * 1024));
-        const result = confirm(
-            `This trace is ${size}mb, opening it in ` +
-            `the legacy UI may fail.\nPress 'OK' to attempt to open this ` +
-            `trace or press 'Cancel' and use the 'Truncate' button ` +
-            `to load just the first 50mb.\nMore options can be found at ` +
-            `go/opening-large-traces.`);
-        if (!result) return;
-      }
-      globals.dispatch(Actions.convertTraceToJson({file, truncate: false}));
+      return;
     }
+
+    // Perfetto traces smaller than 50mb can be safely opened in the legacy UI.
+    if (file.size < 1024 * 1024 * 50) {
+      globals.dispatch(Actions.convertTraceToJson({file}));
+      return;
+    }
+
+    // Give the user the option to truncate larger perfetto traces.
+    const size = Math.round(file.size / (1024 * 1024));
+    showModal({
+      title: 'Legacy UI may fail to open this trace',
+      content:
+          m('div',
+            m('p',
+              `This trace is ${size}mb, opening it in the legacy UI ` +
+                  `may fail.`),
+            m('p',
+              'More options can be found at ',
+              m('a',
+                {
+                  href: 'https://goto.google.com/opening-large-traces',
+                  target: '_blank'
+                },
+                'go/opening-large-traces'),
+              '.')),
+      buttons: [
+        {
+          text: 'Open full trace (not recommended)',
+          primary: false,
+          id: 'open',
+          action: () => {
+            globals.dispatch(Actions.convertTraceToJson({file}));
+          }
+        },
+        {
+          text: 'Open beginning of trace',
+          primary: true,
+          id: 'truncate-start',
+          action: () => {
+            globals.dispatch(
+                Actions.convertTraceToJson({file, truncate: 'start'}));
+          }
+        },
+        {
+          text: 'Open end of trace',
+          primary: true,
+          id: 'truncate-end',
+          action: () => {
+            globals.dispatch(
+                Actions.convertTraceToJson({file, truncate: 'end'}));
+          }
+        }
+
+      ]
+    });
     return;
   }
 
   if (e.target.dataset['video'] === '1') {
+    // TODO(hjd): Update this to use a controller and publish.
+    globals.dispatch(Actions.executeQuery({
+      engineId: '0', queryId: 'command',
+      query: `select ts from slices where name = 'first_frame' union ` +
+             `select start_ts from trace_bounds`}));
+    setTimeout(() => {
+      const resp = globals.queryResults.get('command') as QueryResponse;
+      // First value is screenrecord trace event timestamp
+      // and second value is trace boundary's start timestamp
+      const offset = (parseInt(resp.rows[1]['ts'].toString()) -
+                      parseInt(resp.rows[0]['ts'].toString())) / 1e9;
+      globals.queryResults.delete('command');
+      globals.rafScheduler.scheduleFullRedraw();
+      globals.dispatch(Actions.deleteQuery({queryId: 'command'}));
+      globals.dispatch(Actions.setVideoOffset({offset}));
+    }, 1000);
     globals.dispatch(Actions.openVideoFromFile({file}));
-  } else {
-    globals.dispatch(Actions.openTraceFromFile({file}));
+    return;
   }
+
+  globals.dispatch(Actions.openTraceFromFile({file}));
+
 }
 
 function navigateRecord(e: Event) {
@@ -420,22 +459,23 @@
           class: globals.frontendLocalState.sidebarVisible ? 'show-sidebar' :
                                                              'hide-sidebar'
         },
-        m('header',
-          'Perfetto',
-          m(
-              '.sidebar-button',
-              m('button',
-                m('i.material-icons',
-                  {
-                    title: globals.frontendLocalState.sidebarVisible ?
-                        'Hide menu' :
-                        'Show menu',
-                    onclick: () => {
-                      globals.frontendLocalState.toggleSidebar();
-                    },
-                  },
-                  'menu')),
-              )),
+        m(
+            'header',
+            'Perfetto',
+            m('button.sidebar-button',
+              {
+                onclick: () => {
+                  globals.frontendLocalState.toggleSidebar();
+                },
+              },
+              m('i.material-icons',
+                {
+                  title: globals.frontendLocalState.sidebarVisible ?
+                      'Hide menu' :
+                      'Show menu',
+                },
+                'menu')),
+            ),
         m('input[type=file]', {onchange: onInputElementFileSelectionChanged}),
         m('.sidebar-content', ...vdomSections));
   }
diff --git a/ui/src/frontend/topbar.ts b/ui/src/frontend/topbar.ts
index 36319b4..d6f7db8 100644
--- a/ui/src/frontend/topbar.ts
+++ b/ui/src/frontend/topbar.ts
@@ -22,24 +22,26 @@
 
 const QUERY_ID = 'quicksearch';
 
+const SEARCH = Symbol('search');
+const COMMAND = Symbol('command');
+type Mode = typeof SEARCH|typeof COMMAND;
+
+const PLACEHOLDER = {
+  [SEARCH]: 'Search',
+  [COMMAND]: 'e.g. select * from sched left join thread using(utid) limit 10'
+};
+
 let selResult = 0;
 let numResults = 0;
-let mode: 'search'|'command' = 'search';
+let mode: Mode = SEARCH;
 let omniboxValue = '';
 
-function enterCommandMode() {
-  if (mode === 'search') {
-    mode = 'command';
-    globals.rafScheduler.scheduleFullRedraw();
-  }
-}
-
 function clearOmniboxResults(e: Event) {
   globals.queryResults.delete(QUERY_ID);
   globals.dispatch(Actions.deleteQuery({queryId: QUERY_ID}));
   const txt = (e.target as HTMLInputElement);
   if (txt.value.length <= 0) {
-    mode = 'search';
+    mode = SEARCH;
     globals.rafScheduler.scheduleFullRedraw();
   }
 }
@@ -47,6 +49,7 @@
 function onKeyDown(e: Event) {
   e.stopPropagation();
   const key = (e as KeyboardEvent).key;
+  const txt = (e.target as HTMLInputElement);
 
   // Avoid that the global 'a', 'd', 'w', 's' handler sees these keystrokes.
   // TODO: this seems a bug in the pan_and_zoom_handler.ts.
@@ -54,7 +57,20 @@
     e.preventDefault();
     return;
   }
-  const txt = (e.target as HTMLInputElement);
+
+  if (mode === SEARCH && txt.value === '' && key === ':') {
+    e.preventDefault();
+    mode = COMMAND;
+    globals.rafScheduler.scheduleFullRedraw();
+    return;
+  }
+
+  if (mode === COMMAND && txt.value === '' && key === 'Backspace') {
+    mode = SEARCH;
+    globals.rafScheduler.scheduleFullRedraw();
+    return;
+  }
+
   omniboxValue = txt.value;
 }
 
@@ -71,17 +87,17 @@
     globals.rafScheduler.scheduleFullRedraw();
     return;
   }
-  if (txt.value.length <= 0 || key === 'Escape') {
+
+  if (key === 'Escape') {
     globals.queryResults.delete(QUERY_ID);
-    globals.dispatch(Actions.deleteQuery({queryId: QUERY_ID}));
-    mode = 'search';
+    globals.dispatch(Actions.deleteQuery({queryId: 'command'}));
+    mode = SEARCH;
     txt.value = '';
-    omniboxValue = txt.value;
     txt.blur();
     globals.rafScheduler.scheduleFullRedraw();
     return;
   }
-  if (mode === 'command' && key === 'Enter') {
+  if (mode === COMMAND && key === 'Enter') {
     globals.dispatch(Actions.executeQuery(
         {engineId: '0', queryId: 'command', query: txt.value}));
   }
@@ -90,8 +106,6 @@
 class Omnibox implements m.ClassComponent {
   oncreate(vnode: m.VnodeDOM) {
     const txt = vnode.dom.querySelector('input') as HTMLInputElement;
-    txt.addEventListener('focus', enterCommandMode);
-    txt.addEventListener('click', enterCommandMode);
     txt.addEventListener('blur', clearOmniboxResults);
     txt.addEventListener('keydown', onKeyDown);
     txt.addEventListener('keyup', onKeyUp);
@@ -124,15 +138,11 @@
         results.push(m(`div${clazz}`, resp.rows[i][resp.columns[0]]));
       }
     }
-    const placeholder = {
-      search: 'Click to enter command mode',
-      command: 'e.g. select * from sched left join thread using(utid) limit 10'
-    };
-
-    const commandMode = mode === 'command';
+    const commandMode = mode === COMMAND;
     return m(
         `.omnibox${commandMode ? '.command-mode' : ''}`,
-        m(`input[placeholder=${placeholder[mode]}]`, {
+        m('input', {
+          placeholder: PLACEHOLDER[mode],
           onchange: m.withAttr('value', v => omniboxValue = v),
           value: omniboxValue,
         }),
@@ -166,9 +176,9 @@
     const engine: EngineConfig = globals.state.engines['0'];
     if (globals.state.queries[QUERY_ID] !== undefined ||
         (engine !== undefined && !engine.ready) || globals.isLoading) {
-      this.progressBar.setAttribute('class', 'progress progress-anim');
+      this.progressBar.classList.add('progress-anim');
     } else {
-      this.progressBar.setAttribute('class', 'progress');
+      this.progressBar.classList.remove('progress-anim');
     }
   }
 }
diff --git a/ui/src/frontend/video_panel.ts b/ui/src/frontend/video_panel.ts
index d3f3bbd..9957e37 100644
--- a/ui/src/frontend/video_panel.ts
+++ b/ui/src/frontend/video_panel.ts
@@ -21,7 +21,7 @@
 export class VideoPanel implements m.ClassComponent {
   view() {
     const vidSections = [];
-    const offset = globals.state.traceTime.startSec;
+    const offset = globals.state.traceTime.startSec + globals.state.videoOffset;
     vidSections.push(
       m('video', {
         class: 'video-panel',
@@ -67,7 +67,7 @@
       makeMsg(globals.state.flagPauseEnabled, 'message', pEnabled, pDisabled),
       makeMsg(globals.state.scrubbingEnabled, 'setting',
               tSetting.concat('Enabled'), tSetting.concat('Disabled')),
-      makeMsg(globals.state.scrubbingEnabled, 'message', tEnabled, tDisabled))
+      makeMsg(globals.state.scrubbingEnabled, 'message', tEnabled, tDisabled));
     vidSections.push(vidMessages);
     return m('.video-panel', vidSections);
   }
diff --git a/ui/src/tracks/android_log/controller.ts b/ui/src/tracks/android_log/controller.ts
index 170875c..fba13d7 100644
--- a/ui/src/tracks/android_log/controller.ts
+++ b/ui/src/tracks/android_log/controller.ts
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs} from '../../common/time';
+import {fromNs, toNsCeil, toNsFloor} from '../../common/time';
 import {LIMIT} from '../../common/track_data';
 import {
   TrackController,
@@ -26,11 +26,11 @@
 
   async onBoundsChange(start: number, end: number, resolution: number):
       Promise<Data> {
-    const startNs = Math.floor(start * 1e9);
-    const endNs = Math.ceil(end * 1e9);
+    const startNs = toNsFloor(start);
+    const endNs = toNsCeil(end);
 
     // |resolution| is in s/px the frontend wants.
-    const quantNs = Math.ceil(resolution * 1e9);
+    const quantNs = toNsCeil(resolution);
 
     const rawResult = await this.query(`
       select
diff --git a/ui/src/tracks/chrome_slices/controller.ts b/ui/src/tracks/chrome_slices/controller.ts
index 6b55d64..8e7ac98 100644
--- a/ui/src/tracks/chrome_slices/controller.ts
+++ b/ui/src/tracks/chrome_slices/controller.ts
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs} from '../../common/time';
+import {fromNs, toNs} from '../../common/time';
 import {LIMIT} from '../../common/track_data';
 import {
   TrackController,
@@ -27,10 +27,10 @@
 
   async onBoundsChange(start: number, end: number, resolution: number):
       Promise<Data> {
-    const startNs = Math.round(start * 1e9);
-    const endNs = Math.round(end * 1e9);
+    const startNs = toNs(start);
+    const endNs = toNs(end);
     // Ns in 1px width. We want all slices smaller than 1px to be grouped.
-    const minNs = Math.round(resolution * 1e9);
+    const minNs = toNs(resolution);
 
     if (!this.setup) {
       await this.query(
diff --git a/ui/src/tracks/counter/controller.ts b/ui/src/tracks/counter/controller.ts
index 13146bb..2ef24af 100644
--- a/ui/src/tracks/counter/controller.ts
+++ b/ui/src/tracks/counter/controller.ts
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs} from '../../common/time';
+import {fromNs, toNs} from '../../common/time';
 import {LIMIT} from '../../common/track_data';
 
 import {
@@ -34,8 +34,8 @@
 
   async onBoundsChange(start: number, end: number, resolution: number):
       Promise<Data> {
-    const startNs = Math.round(start * 1e9);
-    const endNs = Math.round(end * 1e9);
+    const startNs = toNs(start);
+    const endNs = toNs(end);
 
     if (!this.setup) {
       const result = await this.query(`
diff --git a/ui/src/tracks/cpu_freq/controller.ts b/ui/src/tracks/cpu_freq/controller.ts
index a1c2149..190a3d9 100644
--- a/ui/src/tracks/cpu_freq/controller.ts
+++ b/ui/src/tracks/cpu_freq/controller.ts
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs} from '../../common/time';
+import {fromNs, toNs} from '../../common/time';
 import {LIMIT} from '../../common/track_data';
 
 import {
@@ -33,8 +33,8 @@
 
   async onBoundsChange(start: number, end: number, resolution: number):
       Promise<Data> {
-    const startNs = Math.round(start * 1e9);
-    const endNs = Math.round(end * 1e9);
+    const startNs = toNs(start);
+    const endNs = toNs(end);
 
     if (!this.setup) {
       const result = await this.query(`
diff --git a/ui/src/tracks/cpu_slices/controller.ts b/ui/src/tracks/cpu_slices/controller.ts
index 2e858c4..278450e 100644
--- a/ui/src/tracks/cpu_slices/controller.ts
+++ b/ui/src/tracks/cpu_slices/controller.ts
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs} from '../../common/time';
+import {fromNs, toNs} from '../../common/time';
 import {LIMIT} from '../../common/track_data';
 
 import {
@@ -34,8 +34,8 @@
 
   async onBoundsChange(start: number, end: number, resolution: number):
       Promise<Data> {
-    const startNs = Math.round(start * 1e9);
-    const endNs = Math.round(end * 1e9);
+    const startNs = toNs(start);
+    const endNs = toNs(end);
 
     if (this.setup === false) {
       await this.query(
@@ -72,8 +72,8 @@
   private async computeSummary(
       start: number, end: number, resolution: number,
       bucketSizeNs: number): Promise<SummaryData> {
-    const startNs = Math.round(start * 1e9);
-    const endNs = Math.round(end * 1e9);
+    const startNs = toNs(start);
+    const endNs = toNs(end);
     const numBuckets = Math.ceil((endNs - startNs) / bucketSizeNs);
 
     const query = `select
diff --git a/ui/src/tracks/gpu_freq/controller.ts b/ui/src/tracks/gpu_freq/controller.ts
index 57c503f..6fa2e39 100644
--- a/ui/src/tracks/gpu_freq/controller.ts
+++ b/ui/src/tracks/gpu_freq/controller.ts
@@ -12,9 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs} from '../../common/time';
+import {fromNs, toNs} from '../../common/time';
 import {LIMIT} from '../../common/track_data';
-
 import {
   TrackController,
   trackControllerRegistry
@@ -22,8 +21,8 @@
 
 import {
   Config,
-  GPU_FREQ_TRACK_KIND,
   Data,
+  GPU_FREQ_TRACK_KIND,
 } from './common';
 
 class GpuFreqTrackController extends TrackController<Config, Data> {
@@ -33,8 +32,8 @@
 
   async onBoundsChange(start: number, end: number, resolution: number):
       Promise<Data> {
-    const startNs = Math.round(start * 1e9);
-    const endNs = Math.round(end * 1e9);
+    const startNs = toNs(start);
+    const endNs = toNs(end);
 
     if (!this.setup) {
       const result = await this.query(`
diff --git a/ui/src/tracks/process_scheduling/controller.ts b/ui/src/tracks/process_scheduling/controller.ts
index ea9cf00..e0816a5 100644
--- a/ui/src/tracks/process_scheduling/controller.ts
+++ b/ui/src/tracks/process_scheduling/controller.ts
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs} from '../../common/time';
+import {fromNs, toNs} from '../../common/time';
 import {LIMIT} from '../../common/track_data';
 
 import {
@@ -42,8 +42,8 @@
       throw new Error('Upid not set.');
     }
 
-    const startNs = Math.round(start * 1e9);
-    const endNs = Math.round(end * 1e9);
+    const startNs = toNs(start);
+    const endNs = toNs(end);
 
     if (this.setup === false) {
       await this.query(
@@ -85,8 +85,8 @@
   private async computeSummary(
       start: number, end: number, resolution: number,
       bucketSizeNs: number): Promise<SummaryData> {
-    const startNs = Math.round(start * 1e9);
-    const endNs = Math.round(end * 1e9);
+    const startNs = toNs(start);
+    const endNs = toNs(end);
     const numBuckets = Math.ceil((endNs - startNs) / bucketSizeNs);
 
     // cpu < numCpus improves perfomance a lot since the window table can
diff --git a/ui/src/tracks/process_summary/controller.ts b/ui/src/tracks/process_summary/controller.ts
index 2600dc2..d18cb6b 100644
--- a/ui/src/tracks/process_summary/controller.ts
+++ b/ui/src/tracks/process_summary/controller.ts
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs} from '../../common/time';
+import {fromNs, toNs} from '../../common/time';
 import {LIMIT} from '../../common/track_data';
 
 import {
@@ -35,8 +35,8 @@
 
   async onBoundsChange(start: number, end: number, resolution: number):
       Promise<Data> {
-    const startNs = Math.round(start * 1e9);
-    const endNs = Math.round(end * 1e9);
+    const startNs = toNs(start);
+    const endNs = toNs(end);
 
     if (this.setup === false) {
       await this.query(
@@ -81,8 +81,8 @@
   private async computeSummary(
       start: number, end: number, resolution: number,
       bucketSizeNs: number): Promise<Data> {
-    const startNs = Math.round(start * 1e9);
-    const endNs = Math.round(end * 1e9);
+    const startNs = toNs(start);
+    const endNs = toNs(end);
     const numBuckets = Math.ceil((endNs - startNs) / bucketSizeNs);
 
     const query = `select
diff --git a/ui/src/tracks/thread_state/controller.ts b/ui/src/tracks/thread_state/controller.ts
index a6ebd2c..043d134 100644
--- a/ui/src/tracks/thread_state/controller.ts
+++ b/ui/src/tracks/thread_state/controller.ts
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs} from '../../common/time';
+import {fromNs, toNs} from '../../common/time';
 import {LIMIT} from '../../common/track_data';
 
 import {
@@ -33,12 +33,12 @@
 
   async onBoundsChange(start: number, end: number, resolution: number):
       Promise<Data> {
-    const startNs = Math.round(start * 1e9);
-    const endNs = Math.round(end * 1e9);
+    const startNs = toNs(start);
+    const endNs = toNs(end);
     let minNs = 0;
     if (groupBusyStates(resolution)) {
       // Ns for 1px (the smallest state to display)
-      minNs = Math.round(resolution * 1 * 1e9);
+      minNs = Math.round(resolution * 1e9);
     }
 
     if (this.setup === false) {
diff --git a/ui/tsconfig.json b/ui/tsconfig.json
index 314b2d4..7f4d790 100644
--- a/ui/tsconfig.json
+++ b/ui/tsconfig.json
@@ -9,6 +9,10 @@
       "dom",                               // Need to be explicitly mentioned now since we're overriding default included libs.
       "es2018",                            // Need this to use Object.values.
     ],
+    "baseUrl": ".",
+    "paths": {
+      "*" : ["*", "./types/*"]
+    },
     "target": "es6",
     "module": "commonjs",
     "moduleResolution": "node",
diff --git a/ui/types/micromodal/index.d.ts b/ui/types/micromodal/index.d.ts
new file mode 100644
index 0000000..d16ff3e
--- /dev/null
+++ b/ui/types/micromodal/index.d.ts
@@ -0,0 +1,73 @@
+// Type definitions for micromodal 0.3
+// Project: https://github.com/ghosh/micromodal#readme
+// Definitions by: Wayne Carson <https://github.com/wcarson>
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+
+
+/**
+ * MicroModal controller
+ */
+declare namespace MicroModal {
+  /**
+   * MicroModal configuration options
+   */
+  export interface MicroModalConfig {
+    /** This is fired when the modal is opening. */
+    onShow?: (modal?: HTMLElement) => void;
+
+    /** This is fired when the modal is closing. */
+    onClose?: (modal?: HTMLElement) => void;
+
+    /**
+     * Custom data attribute to open modal. Default is data-micromodal-trigger.
+     */
+    openTrigger?: string;
+
+    /**
+     * Custom data attribute to close modal. Default is data-micromodal-close.
+     */
+    closeTrigger?: string;
+
+    /**
+     * This disables scrolling on the page while the modal is open. The default
+     * value is false.
+     */
+    disableScroll?: boolean;
+
+    /** Disable auto focus on first focusable element. Default is false */
+    disableFocus?: boolean;
+
+    /**
+     * Set this to true if using css animations to hide the modal. This allows
+     * it to wait for the animation to finish before removing it from the DOM.
+     * Default is false
+     */
+    awaitCloseAnimation?: boolean;
+
+    /**
+     * This option suppresses the console warnings if passed as true. The
+     * default value is false.
+     */
+    debugMode?: boolean;
+  }
+
+  /**
+   * Binds click handlers to all modal triggers
+   * @param config configuration options
+   */
+  function init(config?: MicroModalConfig): void;
+
+  /**
+   * Shows a particular modal
+   * @param targetModal The id of the modal to display
+   * @param config configuration options
+   */
+  function show(targetModal: string, config?: MicroModalConfig): void;
+
+  /**
+   * Closes the active modal
+   */
+  function close(): void;
+}
+
+export = MicroModal;