diff options
author | Primiano Tucci <primiano@google.com> | 2019-05-23 14:41:31 +0100 |
---|---|---|
committer | Primiano Tucci <primiano@google.com> | 2019-05-23 16:52:44 +0000 |
commit | 20e879f967d6981814eb935fd081c454a5e34a33 (patch) | |
tree | 7262282ab59134a0331936cb6ccab854fc0fdbc0 | |
parent | b60b1e905f213926c2f923041027a92d9905bc26 (diff) | |
parent | 1ef91c971fde3aa0ee292c425e8e8324a9f29228 (diff) | |
download | perfetto-20e879f967d6981814eb935fd081c454a5e34a33.tar.gz |
DO NOT MERGE: Merge 1ef91c971fde into qt-dev for Camera
This is to pick-up changes relevant for b/130543265 (see list below).
List of changes intended to be merged:
fb4d0732 traced: support unique trace session names
a48a9dde probes: invalidate seen pids on task_rename event
0b4008a9 process stats: clear more incremental state
e004a574 traced: Add initial timestamp
c4ecf3eb traced_probes: process tree - handle ClearIncrementalState()
71bce87b Make test trace writer keep its buffer as proper trace packet protos
33868d52 tracing service: add support for issuing periodic ClearIncrementalState ipcs.
bdaa962f Producer: add ClearIncrementalState() call/ipc
3f2024e0 ftrace_controller debug print: support >64 cpus (bitset is 128 wide)
248241ee Reduce field id for test trace packet
ac6e0d46 incremental state invalidation: trace config & data source descriptor protos
a868a078 perfetto_cmd: Avoid indefinite length Dropbox traces
b63f61e8 Add config to disable perfetto's default data sources
f1d1cd83 Rename Android kill switch
Bug: 130543265
Test: unittest, integrationtests + manual
Change-Id: Ibdc87afdb22a40a08be3de7b327956cfc3c555af
Merged-In: I4b965c9d49f98516dab47dc457458967cb0f6966
70 files changed, 2108 insertions, 872 deletions
diff --git a/.travis.yml b/.travis.yml index 256881cb4..2d53e2208 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,36 +45,33 @@ matrix: # compiler: clang # env: CFG=mac-clang-x86_64-ubsan GN_ARGS="is_debug=false is_ubsan=true" - os: linux - dist: trusty + dist: xenial sudo: false - # When setting compiler: clang Travis pull a newer version of clang than - # the version that is shipped with Trusty. This is good for all the other - # configs, but we want to keep at least one target in the matrix to match - # the default version of clang that we have on our workstations. + # Test the system-version of clang, not our own at least in this config. addons: apt: packages: - clang env: CFG=linux_trusty-clang-x86_64-debug GN_ARGS="is_debug=true is_hermetic_clang=false" - os: linux - dist: trusty + dist: xenial sudo: false compiler: clang env: CFG=linux_trusty-clang-x86_64-tsan GN_ARGS="is_debug=false is_tsan=true" - os: linux - dist: trusty + dist: xenial sudo: false compiler: clang env: CFG=linux_trusty-clang-x86_64-msan GN_ARGS="is_debug=false is_msan=true" # TODO(b/117093687): ubsan always times out in Travis. # Re-enable once that is fixed. - os: linux - dist: trusty + dist: xenial sudo: true compiler: clang env: CFG=linux_trusty-clang-x86_64-asan_lsan GN_ARGS="is_debug=false is_asan=true is_lsan=true" - os: linux - dist: trusty + dist: xenial sudo: false addons: apt: @@ -84,27 +81,27 @@ matrix: - g++-7 env: CFG=linux_trusty-gcc7-x86_64-release GN_ARGS="is_debug=false is_clang=false use_custom_libcxx=false cc=\"gcc-7\" cxx=\"g++-7\"" - os: linux - dist: trusty + dist: xenial sudo: false compiler: clang env: CFG=android-clang-arm-release GN_ARGS="is_debug=false target_os=\"android\" target_cpu=\"arm\"" - os: linux - dist: trusty + dist: xenial sudo: true compiler: clang env: CFG=android-clang-arm-asan GN_ARGS="is_debug=false target_os=\"android\" target_cpu=\"arm\" is_asan=true" - os: linux - dist: trusty + dist: xenial sudo: true compiler: clang env: CFG=linux_trusty-clang-x86_64-libfuzzer GN_ARGS="is_clang=true is_debug=false is_fuzzer=true is_asan=true" - os: linux - dist: trusty + dist: xenial sudo: false compiler: clang env: CFG=ui-clang-x86_64-release GN_ARGS="is_debug=false is_clang=true" - os: linux - dist: trusty + dist: xenial sudo: false compiler: clang env: CFG=ui-clang-x86_64-debug GN_ARGS="is_debug=true is_clang=true" @@ -185,7 +182,9 @@ script: "out/dist/$TEST_TARGET" done BENCHMARK_FUNCTIONAL_TEST_ONLY=true out/dist/perfetto_benchmarks - tools/diff_test_trace_processor.py out/dist/trace_processor_shell + + tools/diff_test_trace_processor.py --test-type=queries out/dist/trace_processor_shell + tools/diff_test_trace_processor.py --test-type=metrics out/dist/trace_processor_shell fi after_script: diff --git a/Android.bp b/Android.bp index cbbed4615..14284b767 100644 --- a/Android.bp +++ b/Android.bp @@ -756,6 +756,7 @@ genrule { srcs: [ "protos/perfetto/common/android_log_constants.proto", "protos/perfetto/common/commit_data_request.proto", + "protos/perfetto/common/descriptor.proto", "protos/perfetto/common/observable_events.proto", "protos/perfetto/common/sys_stats_counters.proto", "protos/perfetto/common/trace_stats.proto", @@ -767,6 +768,7 @@ genrule { out: [ "external/perfetto/protos/perfetto/common/android_log_constants.pb.cc", "external/perfetto/protos/perfetto/common/commit_data_request.pb.cc", + "external/perfetto/protos/perfetto/common/descriptor.pb.cc", "external/perfetto/protos/perfetto/common/observable_events.pb.cc", "external/perfetto/protos/perfetto/common/sys_stats_counters.pb.cc", "external/perfetto/protos/perfetto/common/trace_stats.pb.cc", @@ -779,6 +781,7 @@ genrule { srcs: [ "protos/perfetto/common/android_log_constants.proto", "protos/perfetto/common/commit_data_request.proto", + "protos/perfetto/common/descriptor.proto", "protos/perfetto/common/observable_events.proto", "protos/perfetto/common/sys_stats_counters.proto", "protos/perfetto/common/trace_stats.proto", @@ -790,6 +793,7 @@ genrule { out: [ "external/perfetto/protos/perfetto/common/android_log_constants.pb.h", "external/perfetto/protos/perfetto/common/commit_data_request.pb.h", + "external/perfetto/protos/perfetto/common/descriptor.pb.h", "external/perfetto/protos/perfetto/common/observable_events.pb.h", "external/perfetto/protos/perfetto/common/sys_stats_counters.pb.h", "external/perfetto/protos/perfetto/common/trace_stats.pb.h", @@ -805,6 +809,7 @@ genrule { srcs: [ "protos/perfetto/common/android_log_constants.proto", "protos/perfetto/common/commit_data_request.proto", + "protos/perfetto/common/descriptor.proto", "protos/perfetto/common/observable_events.proto", "protos/perfetto/common/sys_stats_counters.proto", "protos/perfetto/common/trace_stats.proto", @@ -817,6 +822,7 @@ genrule { out: [ "external/perfetto/protos/perfetto/common/android_log_constants.pbzero.cc", "external/perfetto/protos/perfetto/common/commit_data_request.pbzero.cc", + "external/perfetto/protos/perfetto/common/descriptor.pbzero.cc", "external/perfetto/protos/perfetto/common/observable_events.pbzero.cc", "external/perfetto/protos/perfetto/common/sys_stats_counters.pbzero.cc", "external/perfetto/protos/perfetto/common/trace_stats.pbzero.cc", @@ -829,6 +835,7 @@ genrule { srcs: [ "protos/perfetto/common/android_log_constants.proto", "protos/perfetto/common/commit_data_request.proto", + "protos/perfetto/common/descriptor.proto", "protos/perfetto/common/observable_events.proto", "protos/perfetto/common/sys_stats_counters.proto", "protos/perfetto/common/trace_stats.proto", @@ -841,6 +848,7 @@ genrule { out: [ "external/perfetto/protos/perfetto/common/android_log_constants.pbzero.h", "external/perfetto/protos/perfetto/common/commit_data_request.pbzero.h", + "external/perfetto/protos/perfetto/common/descriptor.pbzero.h", "external/perfetto/protos/perfetto/common/observable_events.pbzero.h", "external/perfetto/protos/perfetto/common/sys_stats_counters.pbzero.h", "external/perfetto/protos/perfetto/common/trace_stats.pbzero.h", @@ -2412,7 +2420,6 @@ genrule { genrule { name: "perfetto_src_perfetto_cmd_protos_gen", srcs: [ - "src/perfetto_cmd/descriptor.proto", "src/perfetto_cmd/perfetto_cmd_state.proto", ], tools: [ @@ -2420,7 +2427,6 @@ genrule { ], cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ $(in)", out: [ - "external/perfetto/src/perfetto_cmd/descriptor.pb.cc", "external/perfetto/src/perfetto_cmd/perfetto_cmd_state.pb.cc", ], } @@ -2429,7 +2435,6 @@ genrule { genrule { name: "perfetto_src_perfetto_cmd_protos_gen_headers", srcs: [ - "src/perfetto_cmd/descriptor.proto", "src/perfetto_cmd/perfetto_cmd_state.proto", ], tools: [ @@ -2437,7 +2442,6 @@ genrule { ], cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ $(in)", out: [ - "external/perfetto/src/perfetto_cmd/descriptor.pb.h", "external/perfetto/src/perfetto_cmd/perfetto_cmd_state.pb.h", ], export_include_dirs: [ @@ -85,6 +85,7 @@ cc_library( "include/perfetto/base/string_writer.h", "include/perfetto/base/task_runner.h", "include/perfetto/base/temp_file.h", + "include/perfetto/base/thread_annotations.h", "include/perfetto/base/thread_checker.h", "include/perfetto/base/thread_task_runner.h", "include/perfetto/base/thread_utils.h", @@ -283,6 +284,7 @@ cc_library( "include/perfetto/base/string_writer.h", "include/perfetto/base/task_runner.h", "include/perfetto/base/temp_file.h", + "include/perfetto/base/thread_annotations.h", "include/perfetto/base/thread_checker.h", "include/perfetto/base/thread_task_runner.h", "include/perfetto/base/thread_utils.h", @@ -357,6 +359,7 @@ cc_binary( "include/perfetto/base/string_writer.h", "include/perfetto/base/task_runner.h", "include/perfetto/base/temp_file.h", + "include/perfetto/base/thread_annotations.h", "include/perfetto/base/thread_checker.h", "include/perfetto/base/thread_task_runner.h", "include/perfetto/base/thread_utils.h", @@ -564,6 +567,7 @@ cc_binary( "include/perfetto/base/string_writer.h", "include/perfetto/base/task_runner.h", "include/perfetto/base/temp_file.h", + "include/perfetto/base/thread_annotations.h", "include/perfetto/base/thread_checker.h", "include/perfetto/base/thread_task_runner.h", "include/perfetto/base/thread_utils.h", @@ -790,3 +794,24 @@ py_binary( ], main = "tools/gen_merged_sql_metrics.py", ) + +load("//security/fuzzing/blaze:cc_fuzz_target.bzl", "cc_fuzz_target") + +cc_fuzz_target( + name = "trace_parsing_fuzzer", + srcs = ["src/trace_processor/trace_parsing_fuzzer.cc"], + componentid = 323270, + deps = [ + ":trace_processor", + "//third_party/perfetto/protos:trace_processor_cc_proto", + ], +) + +cc_fuzz_target( + name = "proto_decoder_fuzzer", + srcs = ["src/protozero/proto_decoder_fuzzer.cc"], + componentid = 323270, + deps = [ + ":trace_processor", + ], +) diff --git a/BUILD.extras b/BUILD.extras index cda25fb5c..d18d9a24b 100644 --- a/BUILD.extras +++ b/BUILD.extras @@ -17,3 +17,24 @@ py_binary( ], main = "tools/gen_merged_sql_metrics.py", ) + +load("//security/fuzzing/blaze:cc_fuzz_target.bzl", "cc_fuzz_target") + +cc_fuzz_target( + name = "trace_parsing_fuzzer", + srcs = ["src/trace_processor/trace_parsing_fuzzer.cc"], + componentid = 323270, + deps = [ + ":trace_processor", + "//third_party/perfetto/protos:trace_processor_cc_proto", + ], +) + +cc_fuzz_target( + name = "proto_decoder_fuzzer", + srcs = ["src/protozero/proto_decoder_fuzzer.cc"], + componentid = 323270, + deps = [ + ":trace_processor", + ], +) @@ -138,7 +138,9 @@ test("perfetto_unittests") { deps += [ "src/profiling/memory:unittests" ] } if (perfetto_build_standalone && !is_android) { - deps += [ "src/trace_processor:unittests" ] + deps += [ + "src/trace_processor:unittests", + ] } } diff --git a/gn/protozero_library.gni b/gn/protozero_library.gni index 89e7969fc..d2c01b92d 100644 --- a/gn/protozero_library.gni +++ b/gn/protozero_library.gni @@ -49,6 +49,7 @@ template("protozero_library") { "sources", "testonly", "visibility", + "generate_descriptor", ]) } } diff --git a/include/perfetto/base/BUILD.gn b/include/perfetto/base/BUILD.gn index 65df2f024..0540e0f66 100644 --- a/include/perfetto/base/BUILD.gn +++ b/include/perfetto/base/BUILD.gn @@ -38,6 +38,7 @@ source_set("base") { "string_writer.h", "task_runner.h", "temp_file.h", + "thread_annotations.h", "thread_checker.h", "thread_task_runner.h", "thread_utils.h", diff --git a/include/perfetto/base/logging.h b/include/perfetto/base/logging.h index 35896ce75..131f58908 100644 --- a/include/perfetto/base/logging.h +++ b/include/perfetto/base/logging.h @@ -169,6 +169,8 @@ constexpr const char* kLogFmt[] = {"\x1b[2m", "\x1b[39m", "\x1b[32m\x1b[1m", PERFETTO_IMMEDIATE_CRASH(); \ } while (0) +#define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_DFATAL(__VA_ARGS__) + #else #define PERFETTO_DCHECK(x) \ @@ -176,6 +178,7 @@ constexpr const char* kLogFmt[] = {"\x1b[2m", "\x1b[39m", "\x1b[32m\x1b[1m", } while (false && (x)) #define PERFETTO_DFATAL(...) ::perfetto::base::ignore_result(__VA_ARGS__) +#define PERFETTO_DFATAL_OR_ELOG(...) PERFETTO_ELOG(__VA_ARGS__) #endif // PERFETTO_DCHECK_IS_ON() diff --git a/include/perfetto/base/metatrace.h b/include/perfetto/base/metatrace.h index 9659b9007..116a160a8 100644 --- a/include/perfetto/base/metatrace.h +++ b/include/perfetto/base/metatrace.h @@ -29,6 +29,8 @@ namespace base { class MetaTrace { public: + static constexpr uint32_t kMainThreadCpu = 255; + MetaTrace(const char* evt_name, size_t cpu) : evt_name_(evt_name), cpu_(cpu) { WriteEvent('B', evt_name, cpu); } diff --git a/include/perfetto/base/paged_memory.h b/include/perfetto/base/paged_memory.h index ea2aaae8f..f994ea5ed 100644 --- a/include/perfetto/base/paged_memory.h +++ b/include/perfetto/base/paged_memory.h @@ -78,6 +78,7 @@ class PagedMemory { inline void* Get() const noexcept { return p_; } inline bool IsValid() const noexcept { return !!p_; } + inline size_t size() const noexcept { return size_; } private: PagedMemory(char* p, size_t size); diff --git a/include/perfetto/base/thread_annotations.h b/include/perfetto/base/thread_annotations.h new file mode 100644 index 000000000..b5d367194 --- /dev/null +++ b/include/perfetto/base/thread_annotations.h @@ -0,0 +1,40 @@ +/* + * 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_BASE_THREAD_ANNOTATIONS_H_ +#define INCLUDE_PERFETTO_BASE_THREAD_ANNOTATIONS_H_ + +#include "perfetto/base/build_config.h" + +// Windows TSAN doesn't currently support these annotations. +#if defined(THREAD_SANITIZER) && !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +extern "C" { +void AnnotateBenignRaceSized(const char* file, + int line, + unsigned long address, + unsigned long size, + const char* description); +} + +#define PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(pointer, size, description) \ + AnnotateBenignRaceSized(__FILE__, __LINE__, \ + reinterpret_cast<unsigned long>(pointer), size, \ + description); +#else // defined(ADDRESS_SANITIZER) +#define PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(pointer, size, description) +#endif // defined(ADDRESS_SANITIZER) + +#endif // INCLUDE_PERFETTO_BASE_THREAD_ANNOTATIONS_H_ diff --git a/include/perfetto/base/thread_task_runner.h b/include/perfetto/base/thread_task_runner.h index 7992eeb6b..db49a6103 100644 --- a/include/perfetto/base/thread_task_runner.h +++ b/include/perfetto/base/thread_task_runner.h @@ -50,7 +50,7 @@ class ThreadTaskRunner { // // Warning: do not call Quit() on the returned runner pointer, the termination // should be handled exclusively by this class' destructor. - UnixTaskRunner* get() { return task_runner_; } + UnixTaskRunner* get() const { return task_runner_; } private: ThreadTaskRunner(); diff --git a/include/perfetto/protozero/field.h b/include/perfetto/protozero/field.h index cbb48e6ca..9c6da8d07 100644 --- a/include/perfetto/protozero/field.h +++ b/include/perfetto/protozero/field.h @@ -19,6 +19,8 @@ #include <stdint.h> +#include <string> + #include "perfetto/base/logging.h" #include "perfetto/protozero/contiguous_memory_range.h" #include "perfetto/protozero/proto_utils.h" @@ -34,6 +36,7 @@ struct ConstChars { // Allow implicit conversion to perfetto's base::StringView without depending // on perfetto/base or viceversa. static constexpr bool kConvertibleToStringView = true; + std::string ToStdString() const { return std::string(data, size); } const char* data; size_t size; @@ -112,6 +115,8 @@ class Field { return ConstChars{reinterpret_cast<const char*>(data()), size_}; } + inline std::string as_std_string() const { return as_string().ToStdString(); } + inline ConstBytes as_bytes() const { PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kLengthDelimited); diff --git a/include/perfetto/protozero/scattered_heap_buffer.h b/include/perfetto/protozero/scattered_heap_buffer.h index d88f7e63b..7f3906ed9 100644 --- a/include/perfetto/protozero/scattered_heap_buffer.h +++ b/include/perfetto/protozero/scattered_heap_buffer.h @@ -18,6 +18,7 @@ #define INCLUDE_PERFETTO_PROTOZERO_SCATTERED_HEAP_BUFFER_H_ #include <memory> +#include <string> #include <vector> #include "perfetto/base/export.h" @@ -26,6 +27,8 @@ namespace protozero { +class Message; + class PERFETTO_EXPORT ScatteredHeapBuffer : public protozero::ScatteredStreamWriter::Delegate { public: @@ -86,6 +89,48 @@ class PERFETTO_EXPORT ScatteredHeapBuffer std::vector<Slice> slices_; }; +// Helper function to create heap-based protozero messages in one line. +// This is a convenience wrapper, mostly for tests, to avoid having to do: +// MyMessage msg; +// ScatteredHeapBuffer shb; +// ScatteredStreamWriter writer(&shb); +// shb.set_writer(&writer); +// msg.Reset(&shb); +// Just to get an easily serializable message. Instead this allows simply: +// HeapBuffered<MyMessage> msg; +// msg->set_stuff(...); +// msg->SerializeAsString(); +template <typename T = ::protozero::Message> +class HeapBuffered { + public: + HeapBuffered() : shb_(4096, 4096), writer_(&shb_) { + shb_.set_writer(&writer_); + msg_.Reset(&writer_); + } + + // This can't be neither copied nor moved because Message hands out pointers + // to itself when creating submessages. + HeapBuffered(const HeapBuffered&) = delete; + HeapBuffered& operator=(const HeapBuffered&) = delete; + HeapBuffered(HeapBuffered&&) = delete; + HeapBuffered& operator=(HeapBuffered&&) = delete; + + T* get() { return &msg_; } + T* operator->() { return &msg_; } + + std::vector<uint8_t> SerializeAsArray() { return shb_.StitchSlices(); } + + std::string SerializeAsString() { + auto vec = SerializeAsArray(); + return std::string(reinterpret_cast<const char*>(vec.data()), vec.size()); + } + + private: + ScatteredHeapBuffer shb_; + ScatteredStreamWriter writer_; + T msg_; +}; + } // namespace protozero #endif // INCLUDE_PERFETTO_PROTOZERO_SCATTERED_HEAP_BUFFER_H_ diff --git a/include/perfetto/tracing/core/data_source_descriptor.h b/include/perfetto/tracing/core/data_source_descriptor.h index 8cbab7390..af161ff14 100644 --- a/include/perfetto/tracing/core/data_source_descriptor.h +++ b/include/perfetto/tracing/core/data_source_descriptor.h @@ -70,10 +70,18 @@ class PERFETTO_EXPORT DataSourceDescriptor { bool will_notify_on_start() const { return will_notify_on_start_; } void set_will_notify_on_start(bool value) { will_notify_on_start_ = value; } + bool handles_incremental_state_clear() const { + return handles_incremental_state_clear_; + } + void set_handles_incremental_state_clear(bool value) { + handles_incremental_state_clear_ = value; + } + private: std::string name_ = {}; bool will_notify_on_stop_ = {}; bool will_notify_on_start_ = {}; + bool handles_incremental_state_clear_ = {}; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. diff --git a/include/perfetto/tracing/core/producer.h b/include/perfetto/tracing/core/producer.h index 2c8e6f2f9..f383b7ec0 100644 --- a/include/perfetto/tracing/core/producer.h +++ b/include/perfetto/tracing/core/producer.h @@ -104,6 +104,23 @@ class PERFETTO_EXPORT Producer { virtual void Flush(FlushRequestID, const DataSourceInstanceID* data_source_ids, size_t num_data_sources) = 0; + + // Called by the service to instruct the given data sources to stop referring + // to any trace contents emitted so far. The intent is that after processing + // this call, the rest of the trace should be parsable even if all of the + // packets emitted so far have been lost (for example due to ring buffer + // overwrites). + // + // Called only for Producers with active data sources that have opted in by + // setting |handles_incremental_state_clear| in their DataSourceDescriptor. + // + // The way this call is handled is up to the individual Producer + // implementation. Some might wish to emit invalidation markers in the trace + // (see TracePacket.incremental_state_cleared for an existing field), and + // handle them when parsing the trace. + virtual void ClearIncrementalState( + const DataSourceInstanceID* data_source_ids, + size_t num_data_sources) = 0; }; } // namespace perfetto diff --git a/include/perfetto/tracing/core/trace_config.h b/include/perfetto/tracing/core/trace_config.h index 8d6cbbb6a..a48cd2245 100644 --- a/include/perfetto/tracing/core/trace_config.h +++ b/include/perfetto/tracing/core/trace_config.h @@ -56,11 +56,13 @@ class AndroidPowerConfig; class AndroidLogConfig; class TestConfig; class TestConfig_DummyFields; +class TraceConfig_BuiltinDataSource; class TraceConfig_ProducerConfig; class TraceConfig_StatsdMetadata; class TraceConfig_GuardrailOverrides; class TraceConfig_TriggerConfig; class TraceConfig_TriggerConfig_Trigger; +class TraceConfig_IncrementalStateConfig; } // namespace protos } // namespace perfetto @@ -147,6 +149,46 @@ class PERFETTO_EXPORT TraceConfig { std::string unknown_fields_; }; + class PERFETTO_EXPORT BuiltinDataSource { + public: + BuiltinDataSource(); + ~BuiltinDataSource(); + BuiltinDataSource(BuiltinDataSource&&) noexcept; + BuiltinDataSource& operator=(BuiltinDataSource&&); + BuiltinDataSource(const BuiltinDataSource&); + BuiltinDataSource& operator=(const BuiltinDataSource&); + bool operator==(const BuiltinDataSource&) const; + bool operator!=(const BuiltinDataSource& other) const { + return !(*this == other); + } + + // Conversion methods from/to the corresponding protobuf types. + void FromProto(const perfetto::protos::TraceConfig_BuiltinDataSource&); + void ToProto(perfetto::protos::TraceConfig_BuiltinDataSource*) const; + + bool disable_clock_snapshotting() const { + return disable_clock_snapshotting_; + } + void set_disable_clock_snapshotting(bool value) { + disable_clock_snapshotting_ = value; + } + + bool disable_trace_config() const { return disable_trace_config_; } + void set_disable_trace_config(bool value) { disable_trace_config_ = value; } + + bool disable_system_info() const { return disable_system_info_; } + void set_disable_system_info(bool value) { disable_system_info_ = value; } + + private: + bool disable_clock_snapshotting_ = {}; + bool disable_trace_config_ = {}; + bool disable_system_info_ = {}; + + // Allows to preserve unknown protobuf fields for compatibility + // with future versions of .proto files. + std::string unknown_fields_; + }; + enum LockdownModeOperation { LOCKDOWN_UNCHANGED = 0, LOCKDOWN_CLEAR = 1, @@ -358,6 +400,34 @@ class PERFETTO_EXPORT TraceConfig { std::string unknown_fields_; }; + class PERFETTO_EXPORT IncrementalStateConfig { + public: + IncrementalStateConfig(); + ~IncrementalStateConfig(); + IncrementalStateConfig(IncrementalStateConfig&&) noexcept; + IncrementalStateConfig& operator=(IncrementalStateConfig&&); + IncrementalStateConfig(const IncrementalStateConfig&); + IncrementalStateConfig& operator=(const IncrementalStateConfig&); + bool operator==(const IncrementalStateConfig&) const; + bool operator!=(const IncrementalStateConfig& other) const { + return !(*this == other); + } + + // Conversion methods from/to the corresponding protobuf types. + void FromProto(const perfetto::protos::TraceConfig_IncrementalStateConfig&); + void ToProto(perfetto::protos::TraceConfig_IncrementalStateConfig*) const; + + uint32_t clear_period_ms() const { return clear_period_ms_; } + void set_clear_period_ms(uint32_t value) { clear_period_ms_ = value; } + + private: + uint32_t clear_period_ms_ = {}; + + // Allows to preserve unknown protobuf fields for compatibility + // with future versions of .proto files. + std::string unknown_fields_; + }; + TraceConfig(); ~TraceConfig(); TraceConfig(TraceConfig&&) noexcept; @@ -391,6 +461,13 @@ class PERFETTO_EXPORT TraceConfig { return &data_sources_.back(); } + const BuiltinDataSource& builtin_data_sources() const { + return builtin_data_sources_; + } + BuiltinDataSource* mutable_builtin_data_sources() { + return &builtin_data_sources_; + } + uint32_t duration_ms() const { return duration_ms_; } void set_duration_ms(uint32_t value) { duration_ms_ = value; } @@ -443,13 +520,6 @@ class PERFETTO_EXPORT TraceConfig { uint32_t flush_timeout_ms() const { return flush_timeout_ms_; } void set_flush_timeout_ms(uint32_t value) { flush_timeout_ms_ = value; } - bool disable_clock_snapshotting() const { - return disable_clock_snapshotting_; - } - void set_disable_clock_snapshotting(bool value) { - disable_clock_snapshotting_ = value; - } - bool notify_traceur() const { return notify_traceur_; } void set_notify_traceur(bool value) { notify_traceur_ = value; } @@ -471,14 +541,29 @@ class PERFETTO_EXPORT TraceConfig { return &activate_triggers_.back(); } + const IncrementalStateConfig& incremental_state_config() const { + return incremental_state_config_; + } + IncrementalStateConfig* mutable_incremental_state_config() { + return &incremental_state_config_; + } + bool allow_user_build_tracing() const { return allow_user_build_tracing_; } void set_allow_user_build_tracing(bool value) { allow_user_build_tracing_ = value; } + const std::string& unique_session_name() const { + return unique_session_name_; + } + void set_unique_session_name(const std::string& value) { + unique_session_name_ = value; + } + private: std::vector<BufferConfig> buffers_; std::vector<DataSource> data_sources_; + BuiltinDataSource builtin_data_sources_ = {}; uint32_t duration_ms_ = {}; bool enable_extra_guardrails_ = {}; LockdownModeOperation lockdown_mode_ = {}; @@ -491,11 +576,12 @@ class PERFETTO_EXPORT TraceConfig { bool deferred_start_ = {}; uint32_t flush_period_ms_ = {}; uint32_t flush_timeout_ms_ = {}; - bool disable_clock_snapshotting_ = {}; bool notify_traceur_ = {}; TriggerConfig trigger_config_ = {}; std::vector<std::string> activate_triggers_; + IncrementalStateConfig incremental_state_config_ = {}; bool allow_user_build_tracing_ = {}; + std::string unique_session_name_ = {}; // Allows to preserve unknown protobuf fields for compatibility // with future versions of .proto files. diff --git a/include/perfetto/tracing/core/tracing_service.h b/include/perfetto/tracing/core/tracing_service.h index c2eb971fa..3d276989e 100644 --- a/include/perfetto/tracing/core/tracing_service.h +++ b/include/perfetto/tracing/core/tracing_service.h @@ -45,6 +45,165 @@ class TraceWriter; // TODO: for the moment this assumes that all the calls happen on the same // thread/sequence. Not sure this will be the case long term in Chrome. +// The API for the Producer port of the Service. +// Subclassed by: +// 1. The tracing_service_impl.cc business logic when returning it in response +// to the ConnectProducer() method. +// 2. The transport layer (e.g., src/ipc) when the producer and +// the service don't talk locally but via some IPC mechanism. +class PERFETTO_EXPORT ProducerEndpoint { + public: + virtual ~ProducerEndpoint(); + + // Called by the Producer to (un)register data sources. Data sources are + // identified by their name (i.e. DataSourceDescriptor.name) + virtual void RegisterDataSource(const DataSourceDescriptor&) = 0; + virtual void UnregisterDataSource(const std::string& name) = 0; + + // Associate the trace writer with the given |writer_id| with + // |target_buffer|. The service may use this information to retrieve and + // copy uncommitted chunks written by the trace writer into its associated + // buffer, e.g. when a producer process crashes or when a flush is + // necessary. + virtual void RegisterTraceWriter(uint32_t writer_id, + uint32_t target_buffer) = 0; + + // Remove the association of the trace writer previously created via + // RegisterTraceWriter. + virtual void UnregisterTraceWriter(uint32_t writer_id) = 0; + + // Called by the Producer to signal that some pages in the shared memory + // buffer (shared between Service and Producer) have changed. + // When the Producer and the Service are hosted in the same process and + // hence potentially live on the same task runner, This method must call + // TracingServiceImpl's CommitData synchronously, without any PostTask()s, + // if on the same thread. This is to avoid a deadlock where the Producer + // exhausts its SMB and stalls waiting for the service to catch up with + // reads, but the Service never gets to that because it lives on the same + // thread. + using CommitDataCallback = std::function<void()>; + virtual void CommitData(const CommitDataRequest&, + CommitDataCallback callback = {}) = 0; + + virtual SharedMemory* shared_memory() const = 0; + + // Size of shared memory buffer pages. It's always a multiple of 4K. + // See shared_memory_abi.h + virtual size_t shared_buffer_page_size_kb() const = 0; + + // Creates a trace writer, which allows to create events, handling the + // underying shared memory buffer and signalling to the Service. This method + // is thread-safe but the returned object is not. A TraceWriter should be + // used only from a single thread, or the caller has to handle sequencing + // via a mutex or equivalent. This method can only be called if + // TracingService::ConnectProducer was called with |in_process=true|. + // Args: + // |target_buffer| is the target buffer ID where the data produced by the + // writer should be stored by the tracing service. This value is passed + // upon creation of the data source (StartDataSource()) in the + // DataSourceConfig.target_buffer(). + virtual std::unique_ptr<TraceWriter> CreateTraceWriter( + BufferID target_buffer) = 0; + + // If TracingService::ConnectProducer is called with |in_process=true|, + // this returns the producer's SharedMemoryArbiter which can be used + // to create TraceWriters which is able to directly commit chunks + // without going through an IPC layer. + virtual SharedMemoryArbiter* GetInProcessShmemArbiter() = 0; + + // Called in response to a Producer::Flush(request_id) call after all data + // for the flush request has been committed. + virtual void NotifyFlushComplete(FlushRequestID) = 0; + + // Called in response to one or more Producer::StartDataSource(), + // if the data source registered setting the flag + // DataSourceDescriptor.will_notify_on_start. + virtual void NotifyDataSourceStarted(DataSourceInstanceID) = 0; + + // Called in response to one or more Producer::StopDataSource(), + // if the data source registered setting the flag + // DataSourceDescriptor.will_notify_on_stop. + virtual void NotifyDataSourceStopped(DataSourceInstanceID) = 0; + + // This informs the service to activate any of these triggers if any tracing + // session was waiting for them. + virtual void ActivateTriggers(const std::vector<std::string>&) = 0; +}; // class ProducerEndpoint. + +// The API for the Consumer port of the Service. +// Subclassed by: +// 1. The tracing_service_impl.cc business logic when returning it in response +// to +// the ConnectConsumer() method. +// 2. The transport layer (e.g., src/ipc) when the consumer and +// the service don't talk locally but via some IPC mechanism. +class ConsumerEndpoint { + public: + virtual ~ConsumerEndpoint(); + + // Enables tracing with the given TraceConfig. The ScopedFile argument is + // used only when TraceConfig.write_into_file == true. + // If TraceConfig.deferred_start == true data sources are configured via + // SetupDataSource() but are not started until StartTracing() is called. + // This is to support pre-initialization and fast triggering of traces. + // The ScopedFile argument is used only when TraceConfig.write_into_file + // == true. + virtual void EnableTracing(const TraceConfig&, + base::ScopedFile = base::ScopedFile()) = 0; + + // Update the trace config of an existing tracing session; only a subset + // of options can be changed mid-session. Currently the only + // supported functionality is expanding the list of producer_name_filters() + // (or removing the filter entirely) for existing data sources. + virtual void ChangeTraceConfig(const TraceConfig&) = 0; + + // Starts all data sources configured in the trace config. This is used only + // after calling EnableTracing() with TraceConfig.deferred_start=true. + // It's a no-op if called after a regular EnableTracing(), without setting + // deferred_start. + virtual void StartTracing() = 0; + + virtual void DisableTracing() = 0; + + // Requests all data sources to flush their data immediately and invokes the + // passed callback once all of them have acked the flush (in which case + // the callback argument |success| will be true) or |timeout_ms| are elapsed + // (in which case |success| will be false). + // If |timeout_ms| is 0 the TraceConfig's flush_timeout_ms is used, or, + // if that one is not set (or is set to 0), kDefaultFlushTimeoutMs (5s) is + // used. + using FlushCallback = std::function<void(bool /*success*/)>; + virtual void Flush(uint32_t timeout_ms, FlushCallback) = 0; + + // Tracing data will be delivered invoking Consumer::OnTraceData(). + virtual void ReadBuffers() = 0; + + virtual void FreeBuffers() = 0; + + // Will call OnDetach(). + virtual void Detach(const std::string& key) = 0; + + // Will call OnAttach(). + virtual void Attach(const std::string& key) = 0; + + // Will call OnTraceStats(). + virtual void GetTraceStats() = 0; + + enum ObservableEventType : uint32_t { + kNone = 0, + kDataSourceInstances = 1 << 0 + }; + + // Start or stop observing events of selected types. |enabled_event_types| + // specifies the types of events to observe in a bitmask (see + // ObservableEventType enum). To disable observing, pass + // ObservableEventType::kNone. Will call OnObservableEvents() repeatedly + // whenever an event of an enabled ObservableEventType occurs. + // + // TODO(eseckler): Extend this to support producers & data sources. + virtual void ObserveEvents(uint32_t enabled_event_types) = 0; +}; // class ConsumerEndpoint. + // The public API of the tracing Service business logic. // // Exposed to: @@ -57,164 +216,8 @@ class TraceWriter; // The service business logic in src/core/tracing_service_impl.cc. class PERFETTO_EXPORT TracingService { public: - // The API for the Producer port of the Service. - // Subclassed by: - // 1. The tracing_service_impl.cc business logic when returning it in response - // to the ConnectProducer() method. - // 2. The transport layer (e.g., src/ipc) when the producer and - // the service don't talk locally but via some IPC mechanism. - class PERFETTO_EXPORT ProducerEndpoint { - public: - virtual ~ProducerEndpoint(); - - // Called by the Producer to (un)register data sources. Data sources are - // identified by their name (i.e. DataSourceDescriptor.name) - virtual void RegisterDataSource(const DataSourceDescriptor&) = 0; - virtual void UnregisterDataSource(const std::string& name) = 0; - - // Associate the trace writer with the given |writer_id| with - // |target_buffer|. The service may use this information to retrieve and - // copy uncommitted chunks written by the trace writer into its associated - // buffer, e.g. when a producer process crashes or when a flush is - // necessary. - virtual void RegisterTraceWriter(uint32_t writer_id, - uint32_t target_buffer) = 0; - - // Remove the association of the trace writer previously created via - // RegisterTraceWriter. - virtual void UnregisterTraceWriter(uint32_t writer_id) = 0; - - // Called by the Producer to signal that some pages in the shared memory - // buffer (shared between Service and Producer) have changed. - // When the Producer and the Service are hosted in the same process and - // hence potentially live on the same task runner, This method must call - // TracingServiceImpl's CommitData synchronously, without any PostTask()s, - // if on the same thread. This is to avoid a deadlock where the Producer - // exhausts its SMB and stalls waiting for the service to catch up with - // reads, but the Service never gets to that because it lives on the same - // thread. - using CommitDataCallback = std::function<void()>; - virtual void CommitData(const CommitDataRequest&, - CommitDataCallback callback = {}) = 0; - - virtual SharedMemory* shared_memory() const = 0; - - // Size of shared memory buffer pages. It's always a multiple of 4K. - // See shared_memory_abi.h - virtual size_t shared_buffer_page_size_kb() const = 0; - - // Creates a trace writer, which allows to create events, handling the - // underying shared memory buffer and signalling to the Service. This method - // is thread-safe but the returned object is not. A TraceWriter should be - // used only from a single thread, or the caller has to handle sequencing - // via a mutex or equivalent. This method can only be called if - // TracingService::ConnectProducer was called with |in_process=true|. - // Args: - // |target_buffer| is the target buffer ID where the data produced by the - // writer should be stored by the tracing service. This value is passed - // upon creation of the data source (StartDataSource()) in the - // DataSourceConfig.target_buffer(). - virtual std::unique_ptr<TraceWriter> CreateTraceWriter( - BufferID target_buffer) = 0; - - // If TracingService::ConnectProducer is called with |in_process=true|, - // this returns the producer's SharedMemoryArbiter which can be used - // to create TraceWriters which is able to directly commit chunks - // without going through an IPC layer. - virtual SharedMemoryArbiter* GetInProcessShmemArbiter() = 0; - - // Called in response to a Producer::Flush(request_id) call after all data - // for the flush request has been committed. - virtual void NotifyFlushComplete(FlushRequestID) = 0; - - // Called in response to one or more Producer::StartDataSource(), - // if the data source registered setting the flag - // DataSourceDescriptor.will_notify_on_start. - virtual void NotifyDataSourceStarted(DataSourceInstanceID) = 0; - - // Called in response to one or more Producer::StopDataSource(), - // if the data source registered setting the flag - // DataSourceDescriptor.will_notify_on_stop. - virtual void NotifyDataSourceStopped(DataSourceInstanceID) = 0; - - // This informs the service to activate any of these triggers if any tracing - // session was waiting for them. - virtual void ActivateTriggers(const std::vector<std::string>&) = 0; - }; // class ProducerEndpoint. - - // The API for the Consumer port of the Service. - // Subclassed by: - // 1. The tracing_service_impl.cc business logic when returning it in response - // to - // the ConnectConsumer() method. - // 2. The transport layer (e.g., src/ipc) when the consumer and - // the service don't talk locally but via some IPC mechanism. - class ConsumerEndpoint { - public: - virtual ~ConsumerEndpoint(); - - // Enables tracing with the given TraceConfig. The ScopedFile argument is - // used only when TraceConfig.write_into_file == true. - // If TraceConfig.deferred_start == true data sources are configured via - // SetupDataSource() but are not started until StartTracing() is called. - // This is to support pre-initialization and fast triggering of traces. - // The ScopedFile argument is used only when TraceConfig.write_into_file - // == true. - virtual void EnableTracing(const TraceConfig&, - base::ScopedFile = base::ScopedFile()) = 0; - - // Update the trace config of an existing tracing session; only a subset - // of options can be changed mid-session. Currently the only - // supported functionality is expanding the list of producer_name_filters() - // (or removing the filter entirely) for existing data sources. - virtual void ChangeTraceConfig(const TraceConfig&) = 0; - - // Starts all data sources configured in the trace config. This is used only - // after calling EnableTracing() with TraceConfig.deferred_start=true. - // It's a no-op if called after a regular EnableTracing(), without setting - // deferred_start. - virtual void StartTracing() = 0; - - virtual void DisableTracing() = 0; - - // Requests all data sources to flush their data immediately and invokes the - // passed callback once all of them have acked the flush (in which case - // the callback argument |success| will be true) or |timeout_ms| are elapsed - // (in which case |success| will be false). - // If |timeout_ms| is 0 the TraceConfig's flush_timeout_ms is used, or, - // if that one is not set (or is set to 0), kDefaultFlushTimeoutMs (5s) is - // used. - using FlushCallback = std::function<void(bool /*success*/)>; - virtual void Flush(uint32_t timeout_ms, FlushCallback) = 0; - - // Tracing data will be delivered invoking Consumer::OnTraceData(). - virtual void ReadBuffers() = 0; - - virtual void FreeBuffers() = 0; - - // Will call OnDetach(). - virtual void Detach(const std::string& key) = 0; - - // Will call OnAttach(). - virtual void Attach(const std::string& key) = 0; - - // Will call OnTraceStats(). - virtual void GetTraceStats() = 0; - - enum ObservableEventType : uint32_t { - kNone = 0, - kDataSourceInstances = 1 << 0 - }; - - // Start or stop observing events of selected types. |enabled_event_types| - // specifies the types of events to observe in a bitmask (see - // ObservableEventType enum). To disable observing, pass - // ObservableEventType::kNone. Will call OnObservableEvents() repeatedly - // whenever an event of an enabled ObservableEventType occurs. - // - // TODO(eseckler): Extend this to support producers & data sources. - virtual void ObserveEvents(uint32_t enabled_event_types) = 0; - }; // class ConsumerEndpoint. + using ProducerEndpoint = perfetto::ProducerEndpoint; + using ConsumerEndpoint = perfetto::ConsumerEndpoint; // Implemented in src/core/tracing_service_impl.cc . static std::unique_ptr<TracingService> CreateInstance( diff --git a/perfetto.rc b/perfetto.rc index 40e5f7534..8d077131e 100644 --- a/perfetto.rc +++ b/perfetto.rc @@ -35,10 +35,10 @@ service traced_probes /system/bin/traced_probes file /dev/kmsg w capabilities DAC_READ_SEARCH -on property:sys.traced.enable_override=1 +on property:persist.device_config.global_settings.sys_traced=1 setprop persist.traced.enable 1 -on property:sys.traced.enable_override=0 +on property:persist.device_config.global_settings.sys_traced=0 setprop persist.traced.enable 0 on property:debug.atrace.user_initiated=1 diff --git a/protos/BUILD b/protos/BUILD index ed2ce1fc3..bbcdc0f0c 100644 --- a/protos/BUILD +++ b/protos/BUILD @@ -29,6 +29,7 @@ proto_library( srcs = [ "perfetto/common/android_log_constants.proto", "perfetto/common/commit_data_request.proto", + "perfetto/common/descriptor.proto", "perfetto/common/observable_events.proto", "perfetto/common/sys_stats_counters.proto", "perfetto/common/trace_stats.proto", @@ -58,6 +59,7 @@ proto_library( srcs = [ "perfetto/common/android_log_constants.proto", "perfetto/common/commit_data_request.proto", + "perfetto/common/descriptor.proto", "perfetto/common/observable_events.proto", "perfetto/common/sys_stats_counters.proto", "perfetto/common/trace_stats.proto", diff --git a/protos/perfetto/common/BUILD.gn b/protos/perfetto/common/BUILD.gn index a67b42d56..36a9b20e8 100644 --- a/protos/perfetto/common/BUILD.gn +++ b/protos/perfetto/common/BUILD.gn @@ -17,8 +17,9 @@ import("../../../gn/proto_library.gni") import("../../../gn/protozero_library.gni") common_sources = [ - "commit_data_request.proto", "android_log_constants.proto", + "commit_data_request.proto", + "descriptor.proto", "observable_events.proto", "sys_stats_counters.proto", "trace_stats.proto", diff --git a/src/perfetto_cmd/descriptor.proto b/protos/perfetto/common/descriptor.proto index be0fff5c5..be0fff5c5 100644 --- a/src/perfetto_cmd/descriptor.proto +++ b/protos/perfetto/common/descriptor.proto diff --git a/protos/perfetto/config/data_source_descriptor.proto b/protos/perfetto/config/data_source_descriptor.proto index 6414f5139..28e59d748 100644 --- a/protos/perfetto/config/data_source_descriptor.proto +++ b/protos/perfetto/config/data_source_descriptor.proto @@ -38,6 +38,11 @@ message DataSourceDescriptor { // Android P in March 2019 and is not supported on older versions. optional bool will_notify_on_start = 3; + // If true, opt into receiving the ClearIncrementalState() IPC. This should be + // set if the data source writes packets that refer to previous trace + // contents, and knows how to stop referring to the already-emitted data. + optional bool handles_incremental_state_clear = 4; + // TODO: this should have a structure to enable reflection of the proto // fields emitted (see go/perfetto-logging). } diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto index c64bd112e..daa6b8b93 100644 --- a/protos/perfetto/config/perfetto_config.proto +++ b/protos/perfetto/config/perfetto_config.proto @@ -489,7 +489,7 @@ message TestConfig { // Begin of protos/perfetto/config/trace_config.proto -// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py +// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos // to reflect changes in the corresponding C++ headers. // The overall config that is used when starting a new tracing session through @@ -497,7 +497,7 @@ message TestConfig { // It contains the general config for the logging buffer(s) and the configs for // all the data source being enabled. // -// Next id: 20. +// Next id: 23. message TraceConfig { message BufferConfig { optional uint32 size_kb = 1; @@ -541,6 +541,18 @@ message TraceConfig { } repeated DataSource data_sources = 2; + // Config for builtin trace packets emitted by perfetto like trace stats, + // system info, etc. + message BuiltinDataSource { + // Disable emitting clock timestamps into the trace. + optional bool disable_clock_snapshotting = 1; + + optional bool disable_trace_config = 2; + + optional bool disable_system_info = 3; + } + optional BuiltinDataSource builtin_data_sources = 20; + // If specified, the trace will be stopped |duration_ms| after starting. // However in case of traces with triggers, see // TriggerConfig.trigger_timeout_ms instead. @@ -635,8 +647,7 @@ message TraceConfig { // Default 5s. optional uint32 flush_timeout_ms = 14; - // Disable emitting clock timestamps into the trace. - optional bool disable_clock_snapshotting = 15; + reserved 15; // |disable_clock_snapshotting| moved. // Android-only. If set, sends an intent to the Traceur system app when the // trace ends to notify it about the trace readiness. @@ -704,11 +715,37 @@ message TraceConfig { // that were previous configured to use a TriggerConfig. repeated string activate_triggers = 18; + // Configuration for trace contents that reference earlier trace data. For + // example, a data source might intern strings, and emit packets containing + // {interned id : string} pairs. Future packets from that data source can then + // use the interned ids instead of duplicating the raw string contents. The + // trace parser will then need to use that interning table to fully interpret + // the rest of the trace. + message IncrementalStateConfig { + // If nonzero, notify eligible data sources to clear their incremental state + // periodically, with the given period. The notification is sent only to + // data sources that have |handles_incremental_state_clear| set in their + // DataSourceDescriptor. The notification requests that the data source + // stops referring to past trace contents. This is particularly useful when + // tracing in ring buffer mode, where it is not exceptional to overwrite old + // trace data. + // + // Warning: this time-based global clearing is likely to be removed in the + // future, to be replaced with a smarter way of sending the notifications + // only when necessary. + optional uint32 clear_period_ms = 1; + } + optional IncrementalStateConfig incremental_state_config = 21; + // Additional guardrail used by the Perfetto command line client. // On user builds when --dropbox is set perfetto will refuse to trace unless // this is also set. // Added in Q. optional bool allow_user_build_tracing = 19; + + // If set the tracing service will ensure there is at most one tracing session + // with this key. + optional string unique_session_name = 22; } // 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 a2a6fa699..802836e9e 100644 --- a/protos/perfetto/config/trace_config.proto +++ b/protos/perfetto/config/trace_config.proto @@ -21,7 +21,7 @@ import "perfetto/config/data_source_config.proto"; package perfetto.protos; -// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py +// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos // to reflect changes in the corresponding C++ headers. // The overall config that is used when starting a new tracing session through @@ -29,7 +29,7 @@ package perfetto.protos; // It contains the general config for the logging buffer(s) and the configs for // all the data source being enabled. // -// Next id: 20. +// Next id: 23. message TraceConfig { message BufferConfig { optional uint32 size_kb = 1; @@ -73,6 +73,18 @@ message TraceConfig { } repeated DataSource data_sources = 2; + // Config for builtin trace packets emitted by perfetto like trace stats, + // system info, etc. + message BuiltinDataSource { + // Disable emitting clock timestamps into the trace. + optional bool disable_clock_snapshotting = 1; + + optional bool disable_trace_config = 2; + + optional bool disable_system_info = 3; + } + optional BuiltinDataSource builtin_data_sources = 20; + // If specified, the trace will be stopped |duration_ms| after starting. // However in case of traces with triggers, see // TriggerConfig.trigger_timeout_ms instead. @@ -167,8 +179,7 @@ message TraceConfig { // Default 5s. optional uint32 flush_timeout_ms = 14; - // Disable emitting clock timestamps into the trace. - optional bool disable_clock_snapshotting = 15; + reserved 15; // |disable_clock_snapshotting| moved. // Android-only. If set, sends an intent to the Traceur system app when the // trace ends to notify it about the trace readiness. @@ -236,9 +247,35 @@ message TraceConfig { // that were previous configured to use a TriggerConfig. repeated string activate_triggers = 18; + // Configuration for trace contents that reference earlier trace data. For + // example, a data source might intern strings, and emit packets containing + // {interned id : string} pairs. Future packets from that data source can then + // use the interned ids instead of duplicating the raw string contents. The + // trace parser will then need to use that interning table to fully interpret + // the rest of the trace. + message IncrementalStateConfig { + // If nonzero, notify eligible data sources to clear their incremental state + // periodically, with the given period. The notification is sent only to + // data sources that have |handles_incremental_state_clear| set in their + // DataSourceDescriptor. The notification requests that the data source + // stops referring to past trace contents. This is particularly useful when + // tracing in ring buffer mode, where it is not exceptional to overwrite old + // trace data. + // + // Warning: this time-based global clearing is likely to be removed in the + // future, to be replaced with a smarter way of sending the notifications + // only when necessary. + optional uint32 clear_period_ms = 1; + } + optional IncrementalStateConfig incremental_state_config = 21; + // Additional guardrail used by the Perfetto command line client. // On user builds when --dropbox is set perfetto will refuse to trace unless // this is also set. // Added in Q. optional bool allow_user_build_tracing = 19; + + // If set the tracing service will ensure there is at most one tracing session + // with this key. + optional string unique_session_name = 22; } diff --git a/protos/perfetto/ipc/producer_port.proto b/protos/perfetto/ipc/producer_port.proto index 797833cb1..24efc27bd 100644 --- a/protos/perfetto/ipc/producer_port.proto +++ b/protos/perfetto/ipc/producer_port.proto @@ -213,7 +213,18 @@ message GetAsyncCommandResponse { optional uint64 request_id = 2; } - // Next id: 7. + // Instructs the given data sources to stop referring to any trace contents + // emitted so far. Sent only to active data sources that set + // |handles_incremental_state_clear| in their DataSourceDescriptor. + // + // Added to perfetto tree in May 2019. + message ClearIncrementalState { + // The instance id (i.e. StartDataSource.new_instance_id) of the data + // sources that should clear their incremental state. + repeated uint64 data_source_ids = 1; + } + + // Next id: 8. oneof cmd { SetupTracing setup_tracing = 3; SetupDataSource setup_data_source = 6; @@ -221,5 +232,6 @@ message GetAsyncCommandResponse { StopDataSource stop_data_source = 2; // id == 4 was teardown_tracing, never implemented. Flush flush = 5; + ClearIncrementalState clear_incremental_state = 7; } } diff --git a/protos/perfetto/trace/chrome/BUILD.gn b/protos/perfetto/trace/chrome/BUILD.gn index f63757379..33297f09e 100644 --- a/protos/perfetto/trace/chrome/BUILD.gn +++ b/protos/perfetto/trace/chrome/BUILD.gn @@ -15,7 +15,9 @@ import("../../../../gn/perfetto.gni") import("../../../../gn/protozero_library.gni") -chrome_proto_names = [ "chrome_trace_event.proto" ] +chrome_proto_names = [ + "chrome_trace_event.proto", +] minimal_chrome_proto_names = [ "chrome_trace_packet.proto" ] proto_library("lite") { diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto index f63998952..d57288446 100644 --- a/protos/perfetto/trace/perfetto_trace.proto +++ b/protos/perfetto/trace/perfetto_trace.proto @@ -2846,7 +2846,7 @@ message Trace { // TracePacket(s). // // Next reserved id: 13 (up to 15). -// Next id: 47. +// Next id: 49. message TracePacket { // TODO(primiano): in future we should add a timestamp_clock_domain field to // allow mixing timestamps from different clock domains. @@ -2887,7 +2887,12 @@ message TracePacket { bytes synchronization_marker = 36; // This field is only used for testing. - // removed field with id 268435455 // 2^28 - 1, max field id for protos. + // In previous versions of this proto this field had the id 268435455 + // This caused many problems: + // - protozero decoder does not handle field ids larger than 999. + // - old versions of protoc produce Java bindings with syntax errors when + // the field id is large enough. + // removed field with id 900 } // Trusted user id of the producer which generated this packet. Keep in sync @@ -3544,7 +3549,7 @@ message TestConfig { // Begin of protos/perfetto/config/trace_config.proto -// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py +// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos // to reflect changes in the corresponding C++ headers. // The overall config that is used when starting a new tracing session through @@ -3552,7 +3557,7 @@ message TestConfig { // It contains the general config for the logging buffer(s) and the configs for // all the data source being enabled. // -// Next id: 20. +// Next id: 23. message TraceConfig { message BufferConfig { optional uint32 size_kb = 1; @@ -3596,6 +3601,18 @@ message TraceConfig { } repeated DataSource data_sources = 2; + // Config for builtin trace packets emitted by perfetto like trace stats, + // system info, etc. + message BuiltinDataSource { + // Disable emitting clock timestamps into the trace. + optional bool disable_clock_snapshotting = 1; + + optional bool disable_trace_config = 2; + + optional bool disable_system_info = 3; + } + optional BuiltinDataSource builtin_data_sources = 20; + // If specified, the trace will be stopped |duration_ms| after starting. // However in case of traces with triggers, see // TriggerConfig.trigger_timeout_ms instead. @@ -3690,8 +3707,7 @@ message TraceConfig { // Default 5s. optional uint32 flush_timeout_ms = 14; - // Disable emitting clock timestamps into the trace. - optional bool disable_clock_snapshotting = 15; + reserved 15; // |disable_clock_snapshotting| moved. // Android-only. If set, sends an intent to the Traceur system app when the // trace ends to notify it about the trace readiness. @@ -3759,11 +3775,37 @@ message TraceConfig { // that were previous configured to use a TriggerConfig. repeated string activate_triggers = 18; + // Configuration for trace contents that reference earlier trace data. For + // example, a data source might intern strings, and emit packets containing + // {interned id : string} pairs. Future packets from that data source can then + // use the interned ids instead of duplicating the raw string contents. The + // trace parser will then need to use that interning table to fully interpret + // the rest of the trace. + message IncrementalStateConfig { + // If nonzero, notify eligible data sources to clear their incremental state + // periodically, with the given period. The notification is sent only to + // data sources that have |handles_incremental_state_clear| set in their + // DataSourceDescriptor. The notification requests that the data source + // stops referring to past trace contents. This is particularly useful when + // tracing in ring buffer mode, where it is not exceptional to overwrite old + // trace data. + // + // Warning: this time-based global clearing is likely to be removed in the + // future, to be replaced with a smarter way of sending the notifications + // only when necessary. + optional uint32 clear_period_ms = 1; + } + optional IncrementalStateConfig incremental_state_config = 21; + // Additional guardrail used by the Perfetto command line client. // On user builds when --dropbox is set perfetto will refuse to trace unless // this is also set. // Added in Q. optional bool allow_user_build_tracing = 19; + + // If set the tracing service will ensure there is at most one tracing session + // with this key. + optional string unique_session_name = 22; } // 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 0a4a497bf..1a29ea6b4 100644 --- a/protos/perfetto/trace/trace_packet.proto +++ b/protos/perfetto/trace/trace_packet.proto @@ -46,7 +46,7 @@ package perfetto.protos; // TracePacket(s). // // Next reserved id: 13 (up to 15). -// Next id: 47. +// Next id: 49. message TracePacket { // TODO(primiano): in future we should add a timestamp_clock_domain field to // allow mixing timestamps from different clock domains. @@ -87,7 +87,12 @@ message TracePacket { bytes synchronization_marker = 36; // This field is only used for testing. - TestEvent for_testing = 268435455; // 2^28 - 1, max field id for protos. + // In previous versions of this proto this field had the id 268435455 + // This caused many problems: + // - protozero decoder does not handle field ids larger than 999. + // - old versions of protoc produce Java bindings with syntax errors when + // the field id is large enough. + TestEvent for_testing = 900; } // Trusted user id of the producer which generated this packet. Keep in sync diff --git a/src/base/metatrace.cc b/src/base/metatrace.cc index baae16457..99b787f4a 100644 --- a/src/base/metatrace.cc +++ b/src/base/metatrace.cc @@ -40,6 +40,8 @@ int MaybeOpenTraceFile() { } } // namespace +constexpr uint32_t MetaTrace::kMainThreadCpu; + void MetaTrace::WriteEvent(char type, const char* evt_name, size_t cpu) { int fd = MaybeOpenTraceFile(); if (fd == -1) diff --git a/src/perfetto_cmd/BUILD.gn b/src/perfetto_cmd/BUILD.gn index 2a5408ba2..b4ec76ceb 100644 --- a/src/perfetto_cmd/BUILD.gn +++ b/src/perfetto_cmd/BUILD.gn @@ -24,6 +24,7 @@ source_set("perfetto_cmd") { ":trigger_producer", "../../buildtools:protobuf_lite", "../../gn:default_deps", + "../../protos/perfetto/common:lite", "../../protos/perfetto/config:lite", "../base", "../protozero", @@ -84,7 +85,6 @@ proto_library("protos") { generate_python = false deps = [] sources = [ - "descriptor.proto", "perfetto_cmd_state.proto", ] proto_in_dir = perfetto_root_path diff --git a/src/perfetto_cmd/config.cc b/src/perfetto_cmd/config.cc index 7e23df59c..5b881def7 100644 --- a/src/perfetto_cmd/config.cc +++ b/src/perfetto_cmd/config.cc @@ -22,7 +22,6 @@ namespace perfetto { namespace { -using protos::TraceConfig; using ValueUnit = std::pair<uint64_t, std::string>; using UnitMultipler = std::pair<const char*, uint64_t>; @@ -84,7 +83,7 @@ bool ConvertSizeToKb(const std::string& arg, uint64_t* out) { } // namespace bool CreateConfigFromOptions(const ConfigOptions& options, - TraceConfig* config) { + protos::TraceConfig* config) { uint64_t duration_ms = 0; if (!ConvertTimeToMs(options.time, &duration_ms)) { PERFETTO_ELOG("--time argument is invalid"); diff --git a/src/perfetto_cmd/pbtxt_to_pb.cc b/src/perfetto_cmd/pbtxt_to_pb.cc index 4dc051894..cc123a93c 100644 --- a/src/perfetto_cmd/pbtxt_to_pb.cc +++ b/src/perfetto_cmd/pbtxt_to_pb.cc @@ -22,12 +22,12 @@ #include "src/perfetto_cmd/pbtxt_to_pb.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" -#include "src/perfetto_cmd/descriptor.pb.h" #include "perfetto/base/file_utils.h" #include "perfetto/base/logging.h" #include "perfetto/base/string_view.h" #include "perfetto/base/utils.h" +#include "perfetto/common/descriptor.pb.h" #include "perfetto/protozero/message.h" #include "perfetto/protozero/message_handle.h" #include "perfetto/protozero/scattered_heap_buffer.h" @@ -661,17 +661,12 @@ std::vector<uint8_t> PbtxtToPb(const std::string& input, const DescriptorProto* descriptor = name_to_descriptor[kConfigProtoName]; PERFETTO_CHECK(descriptor); - protozero::ScatteredHeapBuffer stream_delegate(base::kPageSize); - protozero::ScatteredStreamWriter stream(&stream_delegate); - stream_delegate.set_writer(&stream); - - protozero::Message message; - message.Reset(&stream); - ParserDelegate delegate(descriptor, &message, reporter, + protozero::HeapBuffered<protozero::Message> message; + ParserDelegate delegate(descriptor, message.get(), reporter, std::move(name_to_descriptor), std::move(name_to_enum)); Parse(input, &delegate); - return stream_delegate.StitchSlices(); + return message.SerializeAsArray(); } } // namespace perfetto diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc index 6648c43a5..aa3feb955 100644 --- a/src/perfetto_cmd/perfetto_cmd.cc +++ b/src/perfetto_cmd/perfetto_cmd.cc @@ -517,6 +517,13 @@ int PerfettoCmd::Main(int argc, char** argv) { args.max_upload_bytes_override = trace_config_->guardrail_overrides().max_upload_per_day_bytes(); #endif + + if ((trace_config_->duration_ms() == 0) && args.is_dropbox && + !args.ignore_guardrails) { + PERFETTO_ELOG("Can't trace indefinitely when uploading via Dropbox."); + return 1; + } + if (!limiter.ShouldTrace(args)) return 1; diff --git a/src/perfetto_cmd/perfetto_config.descriptor.h b/src/perfetto_cmd/perfetto_config.descriptor.h index c49b14fb9..e0dfe44fb 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) // e329b1e1e964417db57f83d8ecf081e041923e78 // SHA1(protos/perfetto/config/perfetto_config.proto) -// 8132339dc93464524410353c402ee3225d79b74a +// e0639d910f73cc9395ffafe5c153ac28982e742f // 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, 10710> kPerfettoConfigDescriptor{ - {0x0a, 0xd3, 0x53, 0x0a, 0x25, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, +constexpr std::array<uint8_t, 11159> kPerfettoConfigDescriptor{ + {0x0a, 0x94, 0x57, 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, @@ -352,8 +352,8 @@ constexpr std::array<uint8_t, 10710> kPerfettoConfigDescriptor{ 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x74, 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, 0xdf, - 0x12, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0xa0, + 0x16, 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, 0x6f, 0x74, 0x6f, @@ -366,70 +366,73 @@ constexpr std::array<uint8_t, 10710> kPerfettoConfigDescriptor{ 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, - 0x12, 0x36, 0x0a, 0x17, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, - 0x78, 0x74, 0x72, 0x61, 0x5f, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, - 0x69, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x65, - 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x72, 0x61, 0x47, 0x75, - 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x57, 0x0a, 0x0d, - 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x6d, 0x6f, 0x64, - 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x70, 0x65, + 0x63, 0x65, 0x73, 0x12, 0x60, 0x0a, 0x14, 0x62, 0x75, 0x69, 0x6c, 0x74, + 0x69, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 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, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x44, + 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x12, 0x62, + 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x4d, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x5f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x67, 0x75, 0x61, 0x72, 0x64, + 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x15, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x72, 0x61, + 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x57, + 0x0a, 0x0d, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x6d, + 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 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, 0x4c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, + 0x4d, 0x6f, 0x64, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x0c, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x4d, + 0x6f, 0x64, 0x65, 0x12, 0x49, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x64, 0x75, + 0x63, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, + 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, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, + 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x70, 0x72, 0x6f, + 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x12, 0x54, 0x0a, 0x0f, 0x73, 0x74, + 0x61, 0x74, 0x73, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 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, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x2e, 0x4c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x4d, 0x6f, - 0x64, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0c, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x4d, 0x6f, 0x64, - 0x65, 0x12, 0x49, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, - 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 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, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x64, 0x75, - 0x63, 0x65, 0x72, 0x73, 0x12, 0x54, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x74, - 0x73, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, + 0x67, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x64, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x64, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x26, 0x0a, 0x0f, + 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x6f, 0x5f, 0x66, + 0x69, 0x6c, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x77, + 0x72, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x6f, 0x46, 0x69, 0x6c, 0x65, + 0x12, 0x2f, 0x0a, 0x14, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x77, 0x72, 0x69, + 0x74, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d, 0x73, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x66, 0x69, 0x6c, 0x65, + 0x57, 0x72, 0x69, 0x74, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, + 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x66, 0x69, 0x6c, + 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x46, + 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, + 0x12, 0x60, 0x0a, 0x13, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, + 0x6c, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, + 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 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, - 0x53, 0x74, 0x61, 0x74, 0x73, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x64, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x72, - 0x69, 0x74, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x6f, 0x5f, 0x66, 0x69, 0x6c, - 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x77, 0x72, 0x69, - 0x74, 0x65, 0x49, 0x6e, 0x74, 0x6f, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x2f, - 0x0a, 0x14, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, - 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x66, 0x69, 0x6c, 0x65, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73, 0x12, - 0x2d, 0x0a, 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, - 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x46, 0x69, 0x6c, - 0x65, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x60, - 0x0a, 0x13, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x5f, - 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2f, 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, 0x47, 0x75, - 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x73, 0x52, 0x12, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, - 0x61, 0x69, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, - 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, - 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0d, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x53, 0x74, - 0x61, 0x72, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x66, 0x6c, 0x75, 0x73, 0x68, - 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x50, - 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x66, - 0x6c, 0x75, 0x73, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x5f, 0x6d, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x66, - 0x6c, 0x75, 0x73, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, - 0x73, 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, 0x0f, 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, 0x25, 0x0a, 0x0e, 0x6e, 0x6f, 0x74, 0x69, 0x66, + 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x12, 0x67, 0x75, 0x61, 0x72, + 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, + 0x65, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x66, 0x6c, 0x75, + 0x73, 0x68, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d, 0x73, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x66, 0x6c, 0x75, 0x73, + 0x68, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73, 0x12, 0x28, 0x0a, + 0x10, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, + 0x75, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0e, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, + 0x74, 0x4d, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x75, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x54, 0x72, 0x61, 0x63, 0x65, 0x75, 0x72, 0x12, 0x51, 0x0a, 0x0e, 0x74, 0x72, @@ -443,476 +446,510 @@ constexpr std::array<uint8_t, 10710> kPerfettoConfigDescriptor{ 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, - 0x72, 0x73, 0x12, 0x37, 0x0a, 0x18, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x74, - 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x15, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x55, 0x73, 0x65, 0x72, 0x42, - 0x75, 0x69, 0x6c, 0x64, 0x54, 0x72, 0x61, 0x63, 0x69, 0x6e, 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, 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, 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, + 0x72, 0x73, 0x12, 0x6d, 0x0a, 0x18, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x33, 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, 0x49, 0x6e, 0x63, 0x72, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x16, 0x69, 0x6e, 0x63, 0x72, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x37, 0x0a, 0x18, 0x61, 0x6c, 0x6c, + 0x6f, 0x77, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x62, 0x75, 0x69, 0x6c, + 0x64, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x18, 0x13, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x15, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x55, 0x73, + 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x54, 0x72, 0x61, 0x63, 0x69, + 0x6e, 0x67, 0x12, 0x2e, 0x0a, 0x13, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, + 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x6e, 0x69, + 0x71, 0x75, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x61, + 0x6d, 0x65, 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, - 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, 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, 0xe4, 0x03, 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, + 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, 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, 0x4a, + 0x04, 0x08, 0x0f, 0x10, 0x10, 0x22, 0xe4, 0x03, 0x0a, 0x0f, 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, 0x1a, 0x64, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, + 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, 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, 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, + 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, 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, + 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, - 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, 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, + 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, - 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, 0xff, 0x14, 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, 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, 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, + 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, 0xff, 0x14, + 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, 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, 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, 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, + 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, 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, 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, + 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, 0x4d, 0x4f, 0x56, 0x41, 0x42, - 0x4c, 0x45, 0x10, 0x38, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, + 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, 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, + 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, 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, + 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, 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, 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, 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, + 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, 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, 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}}; + 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}}; } // namespace perfetto diff --git a/src/perfetto_cmd/trigger_producer.cc b/src/perfetto_cmd/trigger_producer.cc index 45d6c4c63..c84716fae 100644 --- a/src/perfetto_cmd/trigger_producer.cc +++ b/src/perfetto_cmd/trigger_producer.cc @@ -87,4 +87,10 @@ void TriggerProducer::Flush(FlushRequestID, PERFETTO_DFATAL("Attempted to Flush() on commandline producer"); } +void TriggerProducer::ClearIncrementalState(const DataSourceInstanceID*, + size_t) { + PERFETTO_DFATAL( + "Attempted to ClearIncrementalState() on commandline producer"); +} + } // namespace perfetto diff --git a/src/perfetto_cmd/trigger_producer.h b/src/perfetto_cmd/trigger_producer.h index dfd189c91..6abab0e99 100644 --- a/src/perfetto_cmd/trigger_producer.h +++ b/src/perfetto_cmd/trigger_producer.h @@ -50,6 +50,8 @@ class TriggerProducer : public Producer { void StartDataSource(DataSourceInstanceID, const DataSourceConfig&) override; void StopDataSource(DataSourceInstanceID) override; void Flush(FlushRequestID, const DataSourceInstanceID*, size_t) override; + void ClearIncrementalState(const DataSourceInstanceID* data_source_ids, + size_t num_data_sources) override; private: bool issued_callback_ = false; diff --git a/src/profiling/memory/heapprofd_producer.h b/src/profiling/memory/heapprofd_producer.h index d100be11c..567cca0a2 100644 --- a/src/profiling/memory/heapprofd_producer.h +++ b/src/profiling/memory/heapprofd_producer.h @@ -115,6 +115,8 @@ class HeapprofdProducer : public Producer, public UnwindingWorker::Delegate { void Flush(FlushRequestID, const DataSourceInstanceID* data_source_ids, size_t num_data_sources) override; + void ClearIncrementalState(const DataSourceInstanceID* /*data_source_ids*/, + size_t /*num_data_sources*/) override {} // TODO(fmayer): Refactor once/if we have generic reconnect logic. void ConnectWithRetries(const char* socket_name); diff --git a/src/protozero/proto_decoder_unittest.cc b/src/protozero/proto_decoder_unittest.cc index 16efd9a97..2f5ab5356 100644 --- a/src/protozero/proto_decoder_unittest.cc +++ b/src/protozero/proto_decoder_unittest.cc @@ -32,19 +32,12 @@ using ::testing::Invoke; using namespace proto_utils; TEST(ProtoDecoderTest, ReadString) { - Message message; - ScatteredHeapBuffer delegate(512, 512); - ScatteredStreamWriter writer(&delegate); - delegate.set_writer(&writer); - message.Reset(&writer); + HeapBuffered<Message> message; static constexpr char kTestString[] = "test"; - message.AppendString(1, kTestString); - - delegate.AdjustUsedSizeOfCurrentSlice(); - auto used_range = delegate.slices()[0].GetUsedRange(); - - TypedProtoDecoder<32, false> decoder(used_range.begin, used_range.size()); + message->AppendString(1, kTestString); + std::vector<uint8_t> proto = message.SerializeAsArray(); + TypedProtoDecoder<32, false> decoder(proto.data(), proto.size()); const auto& field = decoder.Get(1); ASSERT_EQ(field.type(), ProtoWireType::kLengthDelimited); diff --git a/src/traced/probes/ftrace/cpu_reader.cc b/src/traced/probes/ftrace/cpu_reader.cc index fc2e720b4..436edfbe4 100644 --- a/src/traced/probes/ftrace/cpu_reader.cc +++ b/src/traced/probes/ftrace/cpu_reader.cc @@ -52,8 +52,6 @@ constexpr uint32_t kTypePadding = 29; constexpr uint32_t kTypeTimeExtend = 30; constexpr uint32_t kTypeTimeStamp = 31; -constexpr uint32_t kMainThread = 255; // for METATRACE - struct PageHeader { uint64_t timestamp; uint64_t size; @@ -401,7 +399,8 @@ void CpuReader::RunWorkerThread(size_t cpu, // first CPU wakes up from the blocking read()/splice(). void CpuReader::Drain(const std::set<FtraceDataSource*>& data_sources) { PERFETTO_DCHECK_THREAD(thread_checker_); - PERFETTO_METATRACE("Drain(" + std::to_string(cpu_) + ")", kMainThread); + PERFETTO_METATRACE("Drain(" + std::to_string(cpu_) + ")", + base::MetaTrace::kMainThreadCpu); auto page_blocks = pool_.BeginRead(); for (const auto& page_block : page_blocks) { @@ -583,6 +582,15 @@ bool CpuReader::ParseEvent(uint16_t ftrace_event_id, } } + if (PERFETTO_UNLIKELY(info.proto_field_id == + protos::pbzero::FtraceEvent::kTaskRenameFieldNumber)) { + // For task renames, we want to store that the pid was renamed. We use the + // common pid to reduce code complexity as in all the cases we care about, + // the common pid is the same as the renamed pid (the pid inside the event). + PERFETTO_DCHECK(metadata->last_seen_common_pid); + metadata->AddRenamePid(metadata->last_seen_common_pid); + } + // This finalizes |nested| and |proto_field| automatically. message->Finalize(); metadata->FinishEvent(); diff --git a/src/traced/probes/ftrace/cpu_reader_unittest.cc b/src/traced/probes/ftrace/cpu_reader_unittest.cc index fe2ca7635..0631ecb8f 100644 --- a/src/traced/probes/ftrace/cpu_reader_unittest.cc +++ b/src/traced/probes/ftrace/cpu_reader_unittest.cc @@ -902,6 +902,33 @@ TEST_F(CpuReaderTableTest, ParseAllFields) { Contains(Pair(99u, k64BitUserspaceBlockDeviceId))); } +TEST(CpuReaderTest, TaskRenameEvent) { + BundleProvider bundle_provider(base::kPageSize); + + BinaryWriter writer; + ProtoTranslationTable* table = GetTable("android_seed_N2F62_3.10.49"); + + constexpr uint32_t kTaskRenameId = 19; + + writer.Write<int32_t>(1001); // Common field. + writer.Write<int32_t>(9999); // Common pid + writer.Write<int32_t>(9999); // Pid + writer.WriteFixedString(16, "Hello"); // Old Comm + writer.WriteFixedString(16, "Goodbye"); // New Comm + writer.Write<uint64_t>(10); // flags + writer.Write<int16_t>(10); // oom_score_adj + + auto input = writer.GetCopy(); + auto length = writer.written(); + FtraceMetadata metadata{}; + + ASSERT_TRUE(CpuReader::ParseEvent(kTaskRenameId, input.get(), + input.get() + length, table, + bundle_provider.writer(), &metadata)); + EXPECT_THAT(metadata.rename_pids, Contains(9999)); + EXPECT_THAT(metadata.pids, Contains(9999)); +} + TEST(CpuReaderTest, TranslateBlockDeviceIDToUserspace) { const uint32_t kKernelBlockDeviceId = 271581216; const BlockDeviceID kUserspaceBlockDeviceId = 66336; diff --git a/src/traced/probes/ftrace/ftrace_controller.cc b/src/traced/probes/ftrace/ftrace_controller.cc index eff826220..b1b379314 100644 --- a/src/traced/probes/ftrace/ftrace_controller.cc +++ b/src/traced/probes/ftrace/ftrace_controller.cc @@ -48,10 +48,9 @@ namespace perfetto { namespace { constexpr int kDefaultDrainPeriodMs = 100; -constexpr int kFlushTimeoutMs = 500; +constexpr int kControllerFlushTimeoutMs = 500; constexpr int kMinDrainPeriodMs = 1; constexpr int kMaxDrainPeriodMs = 1000 * 60; -constexpr uint32_t kMainThread = 255; // for METATRACE uint32_t ClampDrainPeriodMs(uint32_t drain_period_ms) { if (drain_period_ms == 0) { @@ -220,7 +219,7 @@ void FtraceController::OnCpuReaderFlush(size_t cpu, void FtraceController::DrainCPUs(int generation) { PERFETTO_DCHECK_THREAD(thread_checker_); - PERFETTO_METATRACE("DrainCPUs()", kMainThread); + PERFETTO_METATRACE("DrainCPUs()", base::MetaTrace::kMainThreadCpu); if (generation != generation_) return; @@ -279,7 +278,7 @@ void FtraceController::DrainCPUs(int generation) { } void FtraceController::UnblockReaders() { - PERFETTO_METATRACE("UnblockReaders()", kMainThread); + PERFETTO_METATRACE("UnblockReaders()", base::MetaTrace::kMainThreadCpu); // If a flush or a quit is pending, do nothing. std::unique_lock<std::mutex> lock(thread_sync_.mutex); @@ -357,25 +356,25 @@ void FtraceController::Flush(FlushRequestID flush_id) { if (weak_this) weak_this->OnFlushTimeout(flush_id); }, - kFlushTimeoutMs); + kControllerFlushTimeoutMs); } void FtraceController::OnFlushTimeout(FlushRequestID flush_request_id) { if (flush_request_id != cur_flush_request_id_) return; - uint64_t acks = 0; // For debugging purposes only. + std::string acks; // For debugging purposes only. { // Unlock the cpu readers and move on. std::unique_lock<std::mutex> lock(thread_sync_.mutex); - acks = thread_sync_.flush_acks.to_ulong(); + acks = thread_sync_.flush_acks.to_string(); thread_sync_.flush_acks.reset(); if (thread_sync_.cmd == FtraceThreadSync::kFlush) IssueThreadSyncCmd(FtraceThreadSync::kRun, std::move(lock)); } - PERFETTO_ELOG("Ftrace flush(%" PRIu64 ") timed out. Acked cpus: 0x%" PRIx64, - flush_request_id, acks); + PERFETTO_ELOG("Ftrace flush(%" PRIu64 ") timed out. Acked cpus mask: [%s]", + flush_request_id, acks.c_str()); cur_flush_request_id_ = 0; NotifyFlushCompleteToStartedDataSources(flush_request_id); } diff --git a/src/traced/probes/ftrace/ftrace_metadata.cc b/src/traced/probes/ftrace/ftrace_metadata.cc index 8660a852d..3ae8aaa96 100644 --- a/src/traced/probes/ftrace/ftrace_metadata.cc +++ b/src/traced/probes/ftrace/ftrace_metadata.cc @@ -24,6 +24,8 @@ FtraceMetadata::FtraceMetadata() { // A sched_switch is 64 bytes, a page is 4096 bytes and we expect // 2 pid's per sched_switch. 4096/64*2=128 pids.reserve(128); + // We expect to see only a small number of task rename events. + rename_pids.reserve(16); } void FtraceMetadata::AddDevice(BlockDeviceID device_id) { @@ -63,6 +65,10 @@ void FtraceMetadata::AddPid(int32_t pid) { pids.push_back(pid); } +void FtraceMetadata::AddRenamePid(int32_t pid) { + rename_pids.push_back(pid); +} + void FtraceMetadata::FinishEvent() { last_seen_device_id = 0; #if PERFETTO_DCHECK_IS_ON() @@ -74,6 +80,7 @@ void FtraceMetadata::FinishEvent() { void FtraceMetadata::Clear() { inode_and_device.clear(); pids.clear(); + rename_pids.clear(); overwrite_count = 0; FinishEvent(); } diff --git a/src/traced/probes/ftrace/ftrace_metadata.h b/src/traced/probes/ftrace/ftrace_metadata.h index 4e2e04a8c..9d8f98d91 100644 --- a/src/traced/probes/ftrace/ftrace_metadata.h +++ b/src/traced/probes/ftrace/ftrace_metadata.h @@ -44,11 +44,13 @@ struct FtraceMetadata { // A vector not a set to keep the writer_fast. std::vector<std::pair<Inode, BlockDeviceID>> inode_and_device; std::vector<int32_t> pids; + std::vector<int32_t> rename_pids; void AddDevice(BlockDeviceID); void AddInode(Inode); void AddPid(int32_t); void AddCommonPid(int32_t); + void AddRenamePid(int32_t); void Clear(); void FinishEvent(); }; diff --git a/src/traced/probes/probes_data_source.h b/src/traced/probes/probes_data_source.h index 1e0e8cb5b..7c92ede7a 100644 --- a/src/traced/probes/probes_data_source.h +++ b/src/traced/probes/probes_data_source.h @@ -19,6 +19,7 @@ #include <functional> +#include "perfetto/base/logging.h" #include "perfetto/tracing/core/basic_types.h" namespace perfetto { @@ -33,6 +34,14 @@ class ProbesDataSource { virtual void Start() = 0; virtual void Flush(FlushRequestID, std::function<void()> callback) = 0; + // Only data sources that opt in via DataSourceDescriptor should receive this + // call. + virtual void ClearIncrementalState() { + PERFETTO_ELOG( + "ClearIncrementalState received by data source that doesn't provide " + "its own implementation."); + } + const TracingSessionID tracing_session_id; const int type_id; bool started = false; // Set by probes_producer.cc. diff --git a/src/traced/probes/probes_producer.cc b/src/traced/probes/probes_producer.cc index 193334474..ebe68675a 100644 --- a/src/traced/probes/probes_producer.cc +++ b/src/traced/probes/probes_producer.cc @@ -53,7 +53,7 @@ namespace { constexpr uint32_t kInitialConnectionBackoffMs = 100; constexpr uint32_t kMaxConnectionBackoffMs = 30 * 1000; -// Should be larger than FtraceController::kFlushTimeoutMs. +// Should be larger than FtraceController::kControllerFlushTimeoutMs. constexpr uint32_t kFlushTimeoutMs = 1000; constexpr char kFtraceSourceName[] = "linux.ftrace"; @@ -96,6 +96,7 @@ void ProbesProducer::OnConnect() { { DataSourceDescriptor desc; desc.set_name(kProcessStatsSourceName); + desc.set_handles_incremental_state_clear(true); endpoint_->RegisterDataSource(desc); } @@ -396,6 +397,19 @@ void ProbesProducer::OnFlushTimeout(FlushRequestID flush_request_id) { endpoint_->NotifyFlushComplete(flush_request_id); } +void ProbesProducer::ClearIncrementalState( + const DataSourceInstanceID* data_source_ids, + size_t num_data_sources) { + for (size_t i = 0; i < num_data_sources; i++) { + DataSourceInstanceID ds_id = data_source_ids[i]; + auto it = data_sources_.find(ds_id); + if (it == data_sources_.end() || !it->second->started) + continue; + + it->second->ClearIncrementalState(); + } +} + // This function is called by the FtraceController in batches, whenever it has // read one or more pages from one or more cpus and written that into the // userspace tracing buffer. If more than one ftrace data sources are active, @@ -414,8 +428,13 @@ void ProbesProducer::OnFtraceDataWrittenIntoDataSourceBuffers() { if (it == session_data_sources_.end() || it->first != last_session_id) { bool has_inodes = metadata && !metadata->inode_and_device.empty(); bool has_pids = metadata && !metadata->pids.empty(); + bool has_rename_pids = metadata && !metadata->rename_pids.empty(); if (has_inodes && inode_data_source) inode_data_source->OnInodes(metadata->inode_and_device); + // Ordering the rename pids before the seen pids is important so that any + // renamed processes get scraped in the OnPids call. + if (has_rename_pids && ps_data_source) + ps_data_source->OnRenamePids(metadata->rename_pids); if (has_pids && ps_data_source) ps_data_source->OnPids(metadata->pids); if (metadata) diff --git a/src/traced/probes/probes_producer.h b/src/traced/probes/probes_producer.h index e8b3a6c37..2184830f3 100644 --- a/src/traced/probes/probes_producer.h +++ b/src/traced/probes/probes_producer.h @@ -54,6 +54,8 @@ class ProbesProducer : public Producer, public FtraceController::Observer { void Flush(FlushRequestID, const DataSourceInstanceID* data_source_ids, size_t num_data_sources) override; + void ClearIncrementalState(const DataSourceInstanceID* data_source_ids, + size_t num_data_sources) override; // FtraceController::Observer implementation. void OnFtraceDataWrittenIntoDataSourceBuffers() override; diff --git a/src/traced/probes/ps/process_stats_data_source.cc b/src/traced/probes/ps/process_stats_data_source.cc index 40441e23d..524a8b468 100644 --- a/src/traced/probes/ps/process_stats_data_source.cc +++ b/src/traced/probes/ps/process_stats_data_source.cc @@ -176,6 +176,19 @@ void ProcessStatsDataSource::OnPids(const std::vector<int32_t>& pids) { FinalizeCurPacket(); } +void ProcessStatsDataSource::OnRenamePids(const std::vector<int32_t>& pids) { + PERFETTO_METATRACE("OnRenamePids", 0); + if (!enable_on_demand_dumps_) + return; + PERFETTO_DCHECK(!cur_ps_tree_); + for (int32_t pid : pids) { + auto pid_it = seen_pids_.find(pid); + if (pid_it == seen_pids_.end()) + continue; + seen_pids_.erase(pid_it); + } +} + void ProcessStatsDataSource::Flush(FlushRequestID, std::function<void()> callback) { // We shouldn't get this in the middle of WriteAllProcesses() or OnPids(). @@ -269,6 +282,11 @@ void ProcessStatsDataSource::StartNewPacketIfNeeded() { cur_packet_ = writer_->NewTracePacket(); uint64_t now = static_cast<uint64_t>(base::GetBootTimeNs().count()); cur_packet_->set_timestamp(now); + + if (did_clear_incremental_state_) { + cur_packet_->set_incremental_state_cleared(true); + did_clear_incremental_state_ = false; + } } protos::pbzero::ProcessTree* ProcessStatsDataSource::GetOrCreatePsTree() { @@ -320,8 +338,8 @@ void ProcessStatsDataSource::Tick( thiz.WriteAllProcessStats(); // We clear the cache every process_stats_cache_ttl_ticks_ ticks. - if (++thiz.ticks_ == thiz.process_stats_cache_ttl_ticks_) { - thiz.ticks_ = 0; + if (++thiz.cache_ticks_ == thiz.process_stats_cache_ttl_ticks_) { + thiz.cache_ticks_ = 0; thiz.process_stats_cache_.clear(); } } @@ -487,4 +505,16 @@ bool ProcessStatsDataSource::WriteMemCounters(int32_t pid, return proc_status_has_mem_counters; } +void ProcessStatsDataSource::ClearIncrementalState() { + PERFETTO_DLOG("ProcessStatsDataSource clearing incremental state."); + seen_pids_.clear(); + skip_stats_for_pids_.clear(); + + cache_ticks_ = 0; + process_stats_cache_.clear(); + + // Set the relevant flag in the next packet. + did_clear_incremental_state_ = true; +} + } // namespace perfetto diff --git a/src/traced/probes/ps/process_stats_data_source.h b/src/traced/probes/ps/process_stats_data_source.h index 96869475d..efea49487 100644 --- a/src/traced/probes/ps/process_stats_data_source.h +++ b/src/traced/probes/ps/process_stats_data_source.h @@ -57,10 +57,12 @@ class ProcessStatsDataSource : public ProbesDataSource { base::WeakPtr<ProcessStatsDataSource> GetWeakPtr() const; void WriteAllProcesses(); void OnPids(const std::vector<int32_t>& pids); + void OnRenamePids(const std::vector<int32_t>& pids); // ProbesDataSource implementation. void Start() override; void Flush(FlushRequestID, std::function<void()> callback) override; + void ClearIncrementalState() override; bool on_demand_dumps_enabled() const { return enable_on_demand_dumps_; } @@ -120,7 +122,7 @@ class ProcessStatsDataSource : public ProbesDataSource { // Fields for keeping track of the periodic stats/counters. uint32_t poll_period_ms_ = 0; - uint64_t ticks_ = 0; + uint64_t cache_ticks_ = 0; protos::pbzero::ProcessStats* cur_ps_stats_ = nullptr; protos::pbzero::ProcessStats_Process* cur_ps_stats_process_ = nullptr; std::vector<bool> skip_stats_for_pids_; @@ -130,6 +132,15 @@ class ProcessStatsDataSource : public ProbesDataSource { uint32_t process_stats_cache_ttl_ticks_ = 0; std::unordered_map<int32_t, CachedProcessStats> process_stats_cache_; + // If true, the next trace packet will have the |incremental_state_cleared| + // flag set. Set when handling a ClearIncrementalState call. + // + // TODO(rsavitski): initialized to true since the first packet also doesn't + // have any prior state to refer to. It might make more sense to let the + // tracing service set this for every first packet (as it does for + // |previous_packet_dropped|). + bool did_clear_incremental_state_ = true; + base::WeakPtrFactory<ProcessStatsDataSource> weak_factory_; // Keep last. }; diff --git a/src/traced/probes/ps/process_stats_data_source_unittest.cc b/src/traced/probes/ps/process_stats_data_source_unittest.cc index 2dd9ebba7..0ccd7036a 100644 --- a/src/traced/probes/ps/process_stats_data_source_unittest.cc +++ b/src/traced/probes/ps/process_stats_data_source_unittest.cc @@ -18,20 +18,20 @@ #include <dirent.h> -#include "perfetto/base/temp_file.h" -#include "src/base/test/test_task_runner.h" -#include "src/tracing/core/trace_writer_for_testing.h" - #include "gmock/gmock.h" #include "gtest/gtest.h" - +#include "perfetto/base/temp_file.h" #include "perfetto/trace/trace_packet.pb.h" #include "perfetto/trace/trace_packet.pbzero.h" +#include "src/base/test/test_task_runner.h" +#include "src/tracing/core/trace_writer_for_testing.h" using ::testing::_; using ::testing::ElementsAreArray; using ::testing::Invoke; +using ::testing::Mock; using ::testing::Return; +using ::testing::Truly; namespace perfetto { namespace { @@ -74,16 +74,32 @@ TEST_F(ProcessStatsDataSourceTest, WriteOnceProcess) { .WillOnce(Return(std::string("foo\0bar\0baz\0", 12))); data_source->OnPids({42}); - std::unique_ptr<protos::TracePacket> packet = writer_raw_->ParseProto(); - ASSERT_TRUE(packet->has_process_tree()); - ASSERT_EQ(packet->process_tree().processes_size(), 1); - auto first_process = packet->process_tree().processes(0); + + std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets(); + ASSERT_EQ(trace.size(), 1); + auto ps_tree = trace[0].process_tree(); + ASSERT_EQ(ps_tree.processes_size(), 1); + auto first_process = ps_tree.processes(0); ASSERT_EQ(first_process.pid(), 42); ASSERT_EQ(first_process.ppid(), 17); - EXPECT_THAT(first_process.cmdline(), ElementsAreArray({"foo", "bar", "baz"})); + ASSERT_THAT(first_process.cmdline(), ElementsAreArray({"foo", "bar", "baz"})); } TEST_F(ProcessStatsDataSourceTest, DontRescanCachedPIDsAndTIDs) { + // assertion helpers + auto expected_process = [](int pid) { + return [pid](protos::ProcessTree::Process process) { + return process.pid() == pid && process.cmdline_size() > 0 && + process.cmdline(0) == "proc_" + std::to_string(pid); + }; + }; + auto expected_thread = [](int tid) { + return [tid](protos::ProcessTree::Thread thread) { + return thread.tid() == tid && thread.tgid() == tid / 10 * 10 && + thread.name() == "thread_" + std::to_string(tid); + }; + }; + DataSourceConfig config; config.mutable_process_stats_config()->set_record_thread_names(true); auto data_source = GetProcessStatsDataSource(config); @@ -107,25 +123,163 @@ TEST_F(ProcessStatsDataSourceTest, DontRescanCachedPIDsAndTIDs) { data_source->OnPids({30}); data_source->OnPids({10, 30, 10, 31, 32}); - std::unique_ptr<protos::TracePacket> packet = writer_raw_->ParseProto(); - ASSERT_TRUE(packet->has_process_tree()); - const auto& proceses = packet->process_tree().processes(); - const auto& threads = packet->process_tree().threads(); - ASSERT_EQ(proceses.size(), 3); - int tid_idx = 0; - for (int pid_idx = 0; pid_idx < 3; pid_idx++) { - int pid = (pid_idx + 1) * 10; - std::string proc_name = "proc_" + std::to_string(pid); - ASSERT_EQ(proceses.Get(pid_idx).pid(), pid); - ASSERT_EQ(proceses.Get(pid_idx).cmdline().Get(0), proc_name); - for (int tid = pid + 1; tid < pid + 3; tid++, tid_idx++) { - ASSERT_EQ(threads.Get(tid_idx).tid(), tid); - ASSERT_EQ(threads.Get(tid_idx).tgid(), pid); - ASSERT_EQ(threads.Get(tid_idx).name(), "thread_" + std::to_string(tid)); - } + // check written contents + std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets(); + EXPECT_EQ(trace.size(), 3); + + // first packet - two unique processes, four threads + auto ps_tree = trace[0].process_tree(); + EXPECT_THAT(ps_tree.processes(), + UnorderedElementsAre(Truly(expected_process(10)), + Truly(expected_process(20)))); + EXPECT_THAT(ps_tree.threads(), + UnorderedElementsAre( + Truly(expected_thread(11)), Truly(expected_thread(12)), + Truly(expected_thread(21)), Truly(expected_thread(22)))); + + // second packet - one new process + ps_tree = trace[1].process_tree(); + EXPECT_THAT(ps_tree.processes(), + UnorderedElementsAre(Truly(expected_process(30)))); + EXPECT_EQ(ps_tree.threads_size(), 0); + + // third packet - two threads that haven't been seen before + ps_tree = trace[2].process_tree(); + EXPECT_EQ(ps_tree.processes_size(), 0); + EXPECT_THAT(ps_tree.threads(), + UnorderedElementsAre(Truly(expected_thread(31)), + Truly(expected_thread(32)))); +} + +TEST_F(ProcessStatsDataSourceTest, IncrementalStateClear) { + auto data_source = GetProcessStatsDataSource(DataSourceConfig()); + EXPECT_CALL(*data_source, ReadProcPidFile(42, "status")) + .WillOnce(Return("Name: foo\nTgid:\t42\nPid: 42\nPPid: 17\n")); + EXPECT_CALL(*data_source, ReadProcPidFile(42, "cmdline")) + .WillOnce(Return(std::string("first_cmdline\0", 14))); + + data_source->OnPids({42}); + + { + std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets(); + ASSERT_EQ(trace.size(), 1); + auto packet = trace[0]; + // First packet in the trace has no previous state, so the clear marker is + // emitted. + ASSERT_TRUE(packet.incremental_state_cleared()); + + auto ps_tree = packet.process_tree(); + ASSERT_EQ(ps_tree.processes_size(), 1); + ASSERT_EQ(ps_tree.processes(0).pid(), 42); + ASSERT_EQ(ps_tree.processes(0).ppid(), 17); + ASSERT_THAT(ps_tree.processes(0).cmdline(), + ElementsAreArray({"first_cmdline"})); + } + + // Look up the same pid, which shouldn't be re-emitted. + Mock::VerifyAndClearExpectations(data_source.get()); + EXPECT_CALL(*data_source, ReadProcPidFile(42, "status")).Times(0); + EXPECT_CALL(*data_source, ReadProcPidFile(42, "cmdline")).Times(0); + + data_source->OnPids({42}); + + { + std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets(); + ASSERT_EQ(trace.size(), 1); + } + + // Invalidate incremental state, and look up the same pid again, which should + // re-emit the proc tree info. + Mock::VerifyAndClearExpectations(data_source.get()); + EXPECT_CALL(*data_source, ReadProcPidFile(42, "status")) + .WillOnce(Return("Name: foo\nTgid:\t42\nPid: 42\nPPid: 18\n")); + EXPECT_CALL(*data_source, ReadProcPidFile(42, "cmdline")) + .WillOnce(Return(std::string("second_cmdline\0", 15))); + + data_source->ClearIncrementalState(); + data_source->OnPids({42}); + + { + // Second packet with new proc information. + std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets(); + ASSERT_EQ(trace.size(), 2); + auto packet = trace[1]; + ASSERT_TRUE(packet.incremental_state_cleared()); + + auto ps_tree = packet.process_tree(); + ASSERT_EQ(ps_tree.processes_size(), 1); + ASSERT_EQ(ps_tree.processes(0).pid(), 42); + ASSERT_EQ(ps_tree.processes(0).ppid(), 18); + ASSERT_THAT(ps_tree.processes(0).cmdline(), + ElementsAreArray({"second_cmdline"})); } } +TEST_F(ProcessStatsDataSourceTest, RenamePids) { + // assertion helpers + auto expected_old_process = [](int pid) { + return [pid](protos::ProcessTree::Process process) { + return process.pid() == pid && process.cmdline_size() > 0 && + process.cmdline(0) == "proc_" + std::to_string(pid); + }; + }; + auto expected_new_process = [](int pid) { + return [pid](protos::ProcessTree::Process process) { + return process.pid() == pid && process.cmdline_size() > 0 && + process.cmdline(0) == "new_" + std::to_string(pid); + }; + }; + + DataSourceConfig config; + auto data_source = GetProcessStatsDataSource(config); + for (int p : {10, 20}) { + EXPECT_CALL(*data_source, ReadProcPidFile(p, "status")) + .WillRepeatedly(Invoke([](int32_t pid, const std::string&) { + return "Name: \tthread_" + std::to_string(pid) + + "\nTgid: " + std::to_string(pid) + + "\nPid: " + std::to_string(pid) + "\nPPid: 1\n"; + })); + + std::string old_proc_name = "proc_" + std::to_string(p); + old_proc_name.resize(old_proc_name.size() + 1); // Add a trailing \0. + + std::string new_proc_name = "new_" + std::to_string(p); + new_proc_name.resize(new_proc_name.size() + 1); // Add a trailing \0. + EXPECT_CALL(*data_source, ReadProcPidFile(p, "cmdline")) + .WillOnce(Return(old_proc_name)) + .WillOnce(Return(new_proc_name)); + } + + data_source->OnPids({10, 20}); + data_source->OnRenamePids({10}); + data_source->OnPids({10, 20}); + data_source->OnRenamePids({20}); + data_source->OnPids({10, 20}); + + // check written contents + std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets(); + EXPECT_EQ(trace.size(), 3); + + // first packet - two unique processes + auto ps_tree = trace[0].process_tree(); + EXPECT_THAT(ps_tree.processes(), + UnorderedElementsAre(Truly(expected_old_process(10)), + Truly(expected_old_process(20)))); + EXPECT_EQ(ps_tree.threads_size(), 0); + + // second packet - one new process + ps_tree = trace[1].process_tree(); + EXPECT_THAT(ps_tree.processes(), + UnorderedElementsAre(Truly(expected_new_process(10)))); + EXPECT_EQ(ps_tree.threads_size(), 0); + + // third packet - two threads that haven't been seen before + ps_tree = trace[2].process_tree(); + EXPECT_THAT(ps_tree.processes(), + UnorderedElementsAre(Truly(expected_new_process(20)))); + EXPECT_EQ(ps_tree.threads_size(), 0); +} + TEST_F(ProcessStatsDataSourceTest, ProcessStats) { DataSourceConfig cfg; cfg.mutable_process_stats_config()->set_proc_stats_poll_ms(1); @@ -178,14 +332,16 @@ TEST_F(ProcessStatsDataSourceTest, ProcessStats) { task_runner_.RunUntilCheckpoint("all_done"); data_source->Flush(1 /* FlushRequestId */, []() {}); - // |packet| will contain the merge of all kNumIter packets written. - std::unique_ptr<protos::TracePacket> packet = writer_raw_->ParseProto(); - ASSERT_TRUE(packet); - ASSERT_TRUE(packet->has_process_stats()); - const auto& ps_stats = packet->process_stats(); - ASSERT_EQ(ps_stats.processes_size(), kNumIters * base::ArraySize(kPids)); + std::vector<protos::ProcessStats::Process> processes; + std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets(); + for (const auto& packet : trace) { + for (const auto& process : packet.process_stats().processes()) { + processes.push_back(process); + } + } + ASSERT_EQ(processes.size(), kNumIters * base::ArraySize(kPids)); iter = 0; - for (const auto& proc_counters : ps_stats.processes()) { + for (const auto& proc_counters : processes) { int32_t pid = proc_counters.pid(); ASSERT_EQ(proc_counters.vm_size_kb(), pid * 100 + iter * 10 + 1); ASSERT_EQ(proc_counters.vm_rss_kb(), pid * 100 + iter * 10 + 2); @@ -243,17 +399,19 @@ TEST_F(ProcessStatsDataSourceTest, CacheProcessStats) { task_runner_.RunUntilCheckpoint("all_done"); data_source->Flush(1 /* FlushRequestId */, []() {}); - std::unique_ptr<protos::TracePacket> packet = writer_raw_->ParseProto(); - ASSERT_TRUE(packet); - ASSERT_TRUE(packet->has_process_stats()); - const auto& ps_stats = packet->process_stats(); - ASSERT_EQ(ps_stats.processes_size(), 2); - + std::vector<protos::ProcessStats::Process> processes; + std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets(); + for (const auto& packet : trace) { + for (const auto& process : packet.process_stats().processes()) { + processes.push_back(process); + } + } // We should get two counter events because: // a) emissions happen at 0ms, 105ms, 210ms, 315ms // b) clear events happen at 220ms, 440ms... // Therefore, we should see the emissions at 0ms and 315ms. - for (const auto& proc_counters : ps_stats.processes()) { + ASSERT_EQ(processes.size(), 2); + for (const auto& proc_counters : processes) { ASSERT_EQ(proc_counters.pid(), kPid); ASSERT_EQ(proc_counters.vm_size_kb(), kPid * 100 + 1); ASSERT_EQ(proc_counters.vm_rss_kb(), kPid * 100 + 2); diff --git a/src/traced/service/lazy_producer.h b/src/traced/service/lazy_producer.h index 85510df8e..541b5baef 100644 --- a/src/traced/service/lazy_producer.h +++ b/src/traced/service/lazy_producer.h @@ -47,6 +47,8 @@ class LazyProducer : public Producer { size_t) override { endpoint_->NotifyFlushComplete(flush_id); } + void ClearIncrementalState(const DataSourceInstanceID* /*data_source_ids*/, + size_t /*num_data_sources*/) override {} void OnConnect() override; void SetupDataSource(DataSourceInstanceID, const DataSourceConfig&) override; diff --git a/src/tracing/core/data_source_descriptor.cc b/src/tracing/core/data_source_descriptor.cc index 96cc87efd..1ab58d45b 100644 --- a/src/tracing/core/data_source_descriptor.cc +++ b/src/tracing/core/data_source_descriptor.cc @@ -47,7 +47,9 @@ DataSourceDescriptor& DataSourceDescriptor::operator=(DataSourceDescriptor&&) = bool DataSourceDescriptor::operator==(const DataSourceDescriptor& other) const { return (name_ == other.name_) && (will_notify_on_stop_ == other.will_notify_on_stop_) && - (will_notify_on_start_ == other.will_notify_on_start_); + (will_notify_on_start_ == other.will_notify_on_start_) && + (handles_incremental_state_clear_ == + other.handles_incremental_state_clear_); } #pragma GCC diagnostic pop @@ -67,6 +69,13 @@ void DataSourceDescriptor::FromProto( "size mismatch"); will_notify_on_start_ = static_cast<decltype(will_notify_on_start_)>( proto.will_notify_on_start()); + + static_assert(sizeof(handles_incremental_state_clear_) == + sizeof(proto.handles_incremental_state_clear()), + "size mismatch"); + handles_incremental_state_clear_ = + static_cast<decltype(handles_incremental_state_clear_)>( + proto.handles_incremental_state_clear()); unknown_fields_ = proto.unknown_fields(); } @@ -90,6 +99,13 @@ void DataSourceDescriptor::ToProto( proto->set_will_notify_on_start( static_cast<decltype(proto->will_notify_on_start())>( will_notify_on_start_)); + + static_assert(sizeof(handles_incremental_state_clear_) == + sizeof(proto->handles_incremental_state_clear()), + "size mismatch"); + proto->set_handles_incremental_state_clear( + static_cast<decltype(proto->handles_incremental_state_clear())>( + handles_incremental_state_clear_)); *(proto->mutable_unknown_fields()) = unknown_fields_; } diff --git a/src/tracing/core/trace_buffer.h b/src/tracing/core/trace_buffer.h index d86037a25..35bd5fb81 100644 --- a/src/tracing/core/trace_buffer.h +++ b/src/tracing/core/trace_buffer.h @@ -27,6 +27,7 @@ #include "perfetto/base/logging.h" #include "perfetto/base/paged_memory.h" +#include "perfetto/base/thread_annotations.h" #include "perfetto/tracing/core/basic_types.h" #include "perfetto/tracing/core/slice.h" #include "perfetto/tracing/core/trace_stats.h" @@ -586,6 +587,16 @@ class TraceBuffer { PERFETTO_CHECK(wptr + sizeof(record) + size <= end()); memcpy(wptr, &record, sizeof(record)); if (PERFETTO_LIKELY(src)) { + // If the producer modifies the data in the shared memory buffer while we + // are copying it to the central buffer, TSAN will (rightfully) flag that + // as a race. However the entire purpose of copying the data into the + // central buffer is that we can validate it without worrying that the + // producer changes it from under our feet, so this race is benign. The + // alternative would be to try computing which part of the buffer is safe + // to read (assuming a well-behaving client), but the risk of introducing + // a bug that way outweighs the benefit. + PERFETTO_ANNOTATE_BENIGN_RACE_SIZED( + src, size, "Benign race when copying chunk from shared memory."); memcpy(wptr + sizeof(record), src, size); } else { PERFETTO_DCHECK(size == record.size - sizeof(record)); diff --git a/src/tracing/core/trace_config.cc b/src/tracing/core/trace_config.cc index 54ce848f8..866b2f3ec 100644 --- a/src/tracing/core/trace_config.cc +++ b/src/tracing/core/trace_config.cc @@ -44,6 +44,7 @@ TraceConfig& TraceConfig::operator=(TraceConfig&&) = default; bool TraceConfig::operator==(const TraceConfig& other) const { return (buffers_ == other.buffers_) && (data_sources_ == other.data_sources_) && + (builtin_data_sources_ == other.builtin_data_sources_) && (duration_ms_ == other.duration_ms_) && (enable_extra_guardrails_ == other.enable_extra_guardrails_) && (lockdown_mode_ == other.lockdown_mode_) && @@ -56,11 +57,12 @@ bool TraceConfig::operator==(const TraceConfig& other) const { (deferred_start_ == other.deferred_start_) && (flush_period_ms_ == other.flush_period_ms_) && (flush_timeout_ms_ == other.flush_timeout_ms_) && - (disable_clock_snapshotting_ == other.disable_clock_snapshotting_) && (notify_traceur_ == other.notify_traceur_) && (trigger_config_ == other.trigger_config_) && (activate_triggers_ == other.activate_triggers_) && - (allow_user_build_tracing_ == other.allow_user_build_tracing_); + (incremental_state_config_ == other.incremental_state_config_) && + (allow_user_build_tracing_ == other.allow_user_build_tracing_) && + (unique_session_name_ == other.unique_session_name_); } #pragma GCC diagnostic pop @@ -77,6 +79,8 @@ void TraceConfig::FromProto(const perfetto::protos::TraceConfig& proto) { data_sources_.back().FromProto(field); } + builtin_data_sources_.FromProto(proto.builtin_data_sources()); + static_assert(sizeof(duration_ms_) == sizeof(proto.duration_ms()), "size mismatch"); duration_ms_ = static_cast<decltype(duration_ms_)>(proto.duration_ms()); @@ -133,13 +137,6 @@ void TraceConfig::FromProto(const perfetto::protos::TraceConfig& proto) { flush_timeout_ms_ = static_cast<decltype(flush_timeout_ms_)>(proto.flush_timeout_ms()); - static_assert(sizeof(disable_clock_snapshotting_) == - sizeof(proto.disable_clock_snapshotting()), - "size mismatch"); - disable_clock_snapshotting_ = - static_cast<decltype(disable_clock_snapshotting_)>( - proto.disable_clock_snapshotting()); - static_assert(sizeof(notify_traceur_) == sizeof(proto.notify_traceur()), "size mismatch"); notify_traceur_ = @@ -157,11 +154,19 @@ void TraceConfig::FromProto(const perfetto::protos::TraceConfig& proto) { static_cast<decltype(activate_triggers_)::value_type>(field); } + incremental_state_config_.FromProto(proto.incremental_state_config()); + static_assert(sizeof(allow_user_build_tracing_) == sizeof(proto.allow_user_build_tracing()), "size mismatch"); allow_user_build_tracing_ = static_cast<decltype(allow_user_build_tracing_)>( proto.allow_user_build_tracing()); + + static_assert( + sizeof(unique_session_name_) == sizeof(proto.unique_session_name()), + "size mismatch"); + unique_session_name_ = + static_cast<decltype(unique_session_name_)>(proto.unique_session_name()); unknown_fields_ = proto.unknown_fields(); } @@ -178,6 +183,8 @@ void TraceConfig::ToProto(perfetto::protos::TraceConfig* proto) const { it.ToProto(entry); } + builtin_data_sources_.ToProto(proto->mutable_builtin_data_sources()); + static_assert(sizeof(duration_ms_) == sizeof(proto->duration_ms()), "size mismatch"); proto->set_duration_ms( @@ -238,13 +245,6 @@ void TraceConfig::ToProto(perfetto::protos::TraceConfig* proto) const { proto->set_flush_timeout_ms( static_cast<decltype(proto->flush_timeout_ms())>(flush_timeout_ms_)); - static_assert(sizeof(disable_clock_snapshotting_) == - sizeof(proto->disable_clock_snapshotting()), - "size mismatch"); - proto->set_disable_clock_snapshotting( - static_cast<decltype(proto->disable_clock_snapshotting())>( - disable_clock_snapshotting_)); - static_assert(sizeof(notify_traceur_) == sizeof(proto->notify_traceur()), "size mismatch"); proto->set_notify_traceur( @@ -259,12 +259,21 @@ void TraceConfig::ToProto(perfetto::protos::TraceConfig* proto) const { "size mismatch"); } + incremental_state_config_.ToProto(proto->mutable_incremental_state_config()); + static_assert(sizeof(allow_user_build_tracing_) == sizeof(proto->allow_user_build_tracing()), "size mismatch"); proto->set_allow_user_build_tracing( static_cast<decltype(proto->allow_user_build_tracing())>( allow_user_build_tracing_)); + + static_assert( + sizeof(unique_session_name_) == sizeof(proto->unique_session_name()), + "size mismatch"); + proto->set_unique_session_name( + static_cast<decltype(proto->unique_session_name())>( + unique_session_name_)); *(proto->mutable_unknown_fields()) = unknown_fields_; } @@ -362,6 +371,77 @@ void TraceConfig::DataSource::ToProto( *(proto->mutable_unknown_fields()) = unknown_fields_; } +TraceConfig::BuiltinDataSource::BuiltinDataSource() = default; +TraceConfig::BuiltinDataSource::~BuiltinDataSource() = default; +TraceConfig::BuiltinDataSource::BuiltinDataSource( + const TraceConfig::BuiltinDataSource&) = default; +TraceConfig::BuiltinDataSource& TraceConfig::BuiltinDataSource::operator=( + const TraceConfig::BuiltinDataSource&) = default; +TraceConfig::BuiltinDataSource::BuiltinDataSource( + TraceConfig::BuiltinDataSource&&) noexcept = default; +TraceConfig::BuiltinDataSource& TraceConfig::BuiltinDataSource::operator=( + TraceConfig::BuiltinDataSource&&) = default; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +bool TraceConfig::BuiltinDataSource::operator==( + const TraceConfig::BuiltinDataSource& other) const { + return (disable_clock_snapshotting_ == other.disable_clock_snapshotting_) && + (disable_trace_config_ == other.disable_trace_config_) && + (disable_system_info_ == other.disable_system_info_); +} +#pragma GCC diagnostic pop + +void TraceConfig::BuiltinDataSource::FromProto( + const perfetto::protos::TraceConfig_BuiltinDataSource& proto) { + static_assert(sizeof(disable_clock_snapshotting_) == + sizeof(proto.disable_clock_snapshotting()), + "size mismatch"); + disable_clock_snapshotting_ = + static_cast<decltype(disable_clock_snapshotting_)>( + proto.disable_clock_snapshotting()); + + static_assert( + sizeof(disable_trace_config_) == sizeof(proto.disable_trace_config()), + "size mismatch"); + disable_trace_config_ = static_cast<decltype(disable_trace_config_)>( + proto.disable_trace_config()); + + static_assert( + sizeof(disable_system_info_) == sizeof(proto.disable_system_info()), + "size mismatch"); + disable_system_info_ = + static_cast<decltype(disable_system_info_)>(proto.disable_system_info()); + unknown_fields_ = proto.unknown_fields(); +} + +void TraceConfig::BuiltinDataSource::ToProto( + perfetto::protos::TraceConfig_BuiltinDataSource* proto) const { + proto->Clear(); + + static_assert(sizeof(disable_clock_snapshotting_) == + sizeof(proto->disable_clock_snapshotting()), + "size mismatch"); + proto->set_disable_clock_snapshotting( + static_cast<decltype(proto->disable_clock_snapshotting())>( + disable_clock_snapshotting_)); + + static_assert( + sizeof(disable_trace_config_) == sizeof(proto->disable_trace_config()), + "size mismatch"); + proto->set_disable_trace_config( + static_cast<decltype(proto->disable_trace_config())>( + disable_trace_config_)); + + static_assert( + sizeof(disable_system_info_) == sizeof(proto->disable_system_info()), + "size mismatch"); + proto->set_disable_system_info( + static_cast<decltype(proto->disable_system_info())>( + disable_system_info_)); + *(proto->mutable_unknown_fields()) = unknown_fields_; +} + TraceConfig::ProducerConfig::ProducerConfig() = default; TraceConfig::ProducerConfig::~ProducerConfig() = default; TraceConfig::ProducerConfig::ProducerConfig( @@ -669,4 +749,43 @@ void TraceConfig::TriggerConfig::Trigger::ToProto( *(proto->mutable_unknown_fields()) = unknown_fields_; } +TraceConfig::IncrementalStateConfig::IncrementalStateConfig() = default; +TraceConfig::IncrementalStateConfig::~IncrementalStateConfig() = default; +TraceConfig::IncrementalStateConfig::IncrementalStateConfig( + const TraceConfig::IncrementalStateConfig&) = default; +TraceConfig::IncrementalStateConfig& TraceConfig::IncrementalStateConfig:: +operator=(const TraceConfig::IncrementalStateConfig&) = default; +TraceConfig::IncrementalStateConfig::IncrementalStateConfig( + TraceConfig::IncrementalStateConfig&&) noexcept = default; +TraceConfig::IncrementalStateConfig& TraceConfig::IncrementalStateConfig:: +operator=(TraceConfig::IncrementalStateConfig&&) = default; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +bool TraceConfig::IncrementalStateConfig::operator==( + const TraceConfig::IncrementalStateConfig& other) const { + return (clear_period_ms_ == other.clear_period_ms_); +} +#pragma GCC diagnostic pop + +void TraceConfig::IncrementalStateConfig::FromProto( + const perfetto::protos::TraceConfig_IncrementalStateConfig& proto) { + static_assert(sizeof(clear_period_ms_) == sizeof(proto.clear_period_ms()), + "size mismatch"); + clear_period_ms_ = + static_cast<decltype(clear_period_ms_)>(proto.clear_period_ms()); + unknown_fields_ = proto.unknown_fields(); +} + +void TraceConfig::IncrementalStateConfig::ToProto( + perfetto::protos::TraceConfig_IncrementalStateConfig* proto) const { + proto->Clear(); + + static_assert(sizeof(clear_period_ms_) == sizeof(proto->clear_period_ms()), + "size mismatch"); + proto->set_clear_period_ms( + static_cast<decltype(proto->clear_period_ms())>(clear_period_ms_)); + *(proto->mutable_unknown_fields()) = unknown_fields_; +} + } // namespace perfetto diff --git a/src/tracing/core/trace_writer_for_testing.cc b/src/tracing/core/trace_writer_for_testing.cc index b77a19d14..6cfb559ea 100644 --- a/src/tracing/core/trace_writer_for_testing.cc +++ b/src/tracing/core/trace_writer_for_testing.cc @@ -18,9 +18,10 @@ #include "perfetto/base/logging.h" #include "perfetto/base/utils.h" - #include "perfetto/protozero/message.h" - +#include "perfetto/trace/trace.pb.h" +#include "perfetto/trace/trace.pbzero.h" +#include "perfetto/trace/trace_packet.pb.h" #include "perfetto/trace/trace_packet.pbzero.h" namespace perfetto { @@ -44,12 +45,28 @@ void TraceWriterForTesting::Flush(std::function<void()> callback) { callback(); } -std::unique_ptr<protos::TracePacket> TraceWriterForTesting::ParseProto() { +std::vector<protos::TracePacket> TraceWriterForTesting::GetAllTracePackets() { PERFETTO_CHECK(cur_packet_->is_finalized()); - auto packet = std::unique_ptr<protos::TracePacket>(new protos::TracePacket()); + + auto trace = protos::Trace(); std::vector<uint8_t> buffer = delegate_.StitchSlices(); - if (!packet->ParseFromArray(buffer.data(), static_cast<int>(buffer.size()))) - return nullptr; + if (!trace.ParseFromArray(buffer.data(), static_cast<int>(buffer.size()))) + return {}; + + std::vector<protos::TracePacket> ret; + for (const auto& packet : trace.packet()) { + ret.emplace_back(packet); + } + return ret; +} + +std::unique_ptr<protos::TracePacket> TraceWriterForTesting::ParseProto() { + PERFETTO_CHECK(cur_packet_->is_finalized()); + + auto trace = GetAllTracePackets(); + PERFETTO_CHECK(!trace.empty()); + auto packet = + std::unique_ptr<protos::TracePacket>(new protos::TracePacket(trace[0])); return packet; } @@ -59,7 +76,22 @@ TraceWriterForTesting::NewTracePacket() { // finalized the previous packet. PERFETTO_DCHECK(cur_packet_->is_finalized()); cur_packet_->Reset(&stream_); - return TraceWriter::TracePacketHandle(cur_packet_.get()); + + // Instead of storing the contents of the TracePacket directly in the backing + // buffer like the real trace writers, we prepend the proto preamble to make + // the buffer contents parsable as a sequence of TracePacket protos. + + uint8_t data[protozero::proto_utils::kMaxTagEncodedSize]; + uint8_t* data_end = protozero::proto_utils::WriteVarInt( + protozero::proto_utils::MakeTagLengthDelimited( + protos::pbzero::Trace::kPacketFieldNumber), + data); + stream_.WriteBytes(data, static_cast<uint32_t>(data_end - data)); + + auto packet = TraceWriter::TracePacketHandle(cur_packet_.get()); + packet->set_size_field( + stream_.ReserveBytes(protozero::proto_utils::kMessageLengthFieldSize)); + return packet; } WriterID TraceWriterForTesting::writer_id() const { diff --git a/src/tracing/core/trace_writer_for_testing.h b/src/tracing/core/trace_writer_for_testing.h index 4475d6dc9..f7a1a883b 100644 --- a/src/tracing/core/trace_writer_for_testing.h +++ b/src/tracing/core/trace_writer_for_testing.h @@ -16,6 +16,8 @@ #ifndef SRC_TRACING_CORE_TRACE_WRITER_FOR_TESTING_H_ #define SRC_TRACING_CORE_TRACE_WRITER_FOR_TESTING_H_ +#include <vector> + #include "perfetto/protozero/message_handle.h" #include "perfetto/protozero/scattered_heap_buffer.h" #include "perfetto/trace/trace_packet.pb.h" @@ -28,7 +30,6 @@ namespace perfetto { // See //include/perfetto/tracing/core/trace_writer.h for docs. class TraceWriterForTesting : public TraceWriter { public: - // TraceWriterForTesting(const protozero::ScatteredHeapBuffer& delegate); TraceWriterForTesting(); ~TraceWriterForTesting() override; @@ -37,6 +38,8 @@ class TraceWriterForTesting : public TraceWriter { TracePacketHandle NewTracePacket() override; void Flush(std::function<void()> callback = {}) override; + std::vector<protos::TracePacket> GetAllTracePackets(); + // TODO(rsavitski): rewrite as "get only packet". std::unique_ptr<protos::TracePacket> ParseProto(); WriterID writer_id() const override; diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc index 11b1ef157..c6aac42c2 100644 --- a/src/tracing/core/tracing_service_impl.cc +++ b/src/tracing/core/tracing_service_impl.cc @@ -362,6 +362,18 @@ bool TracingServiceImpl::EnableTracing(ConsumerEndpointImpl* consumer, return false; } + if (!cfg.unique_session_name().empty()) { + const std::string& name = cfg.unique_session_name(); + for (auto& kv : tracing_sessions_) { + if (kv.second.config.unique_session_name() == name) { + PERFETTO_ELOG( + "A trace wtih this unique session name (%s) already exists", + name.c_str()); + return false; + } + } + } + // TODO(primiano): This is a workaround to prevent that a producer gets stuck // in a state where it stalls by design by having more TraceWriterImpl // instances than free pages in the buffer. This is really a bug in @@ -642,6 +654,12 @@ bool TracingServiceImpl::StartTracing(TracingSessionID tsid) { tracing_session->state = TracingSession::STARTED; + if (!tracing_session->config.builtin_data_sources() + .disable_clock_snapshotting()) { + SnapshotClocks(&tracing_session->initial_clock_snapshot_, + /*set_root_timestamp=*/true); + } + // Trigger delayed task if the trace is time limited. const uint32_t trace_duration_ms = tracing_session->config.duration_ms(); if (trace_duration_ms > 0) { @@ -684,6 +702,12 @@ bool TracingServiceImpl::StartTracing(TracingSessionID tsid) { if (tracing_session->config.flush_period_ms()) PeriodicFlushTask(tsid, /*post_next_only=*/true); + // Start the periodic incremental state clear tasks if the config specified a + // period. + if (tracing_session->config.incremental_state_config().clear_period_ms()) { + PeriodicClearIncrementalStateTask(tsid, /*post_next_only=*/true); + } + for (auto& kv : tracing_session->data_source_instances) { ProducerID producer_id = kv.first; DataSourceInstance& data_source = kv.second; @@ -1046,7 +1070,7 @@ void TracingServiceImpl::Flush(TracingSessionID tsid, } // If there are no producers to flush (realistically this happens only in - // some tests) fire OnFlushTimeout() straight away, without waiting. + // some tests) fire OnFlushTimeout() straight away, without waiting. if (flush_map.empty()) timeout_ms = 0; @@ -1280,13 +1304,60 @@ void TracingServiceImpl::PeriodicFlushTask(TracingSessionID tsid, if (post_next_only) return; - PERFETTO_DLOG("Triggering periodic flush for %" PRIu64, tsid); + PERFETTO_DLOG("Triggering periodic flush for trace session %" PRIu64, tsid); Flush(tsid, 0, [](bool success) { if (!success) PERFETTO_ELOG("Periodic flush timed out"); }); } +void TracingServiceImpl::PeriodicClearIncrementalStateTask( + TracingSessionID tsid, + bool post_next_only) { + PERFETTO_DCHECK_THREAD(thread_checker_); + TracingSession* tracing_session = GetTracingSession(tsid); + if (!tracing_session || tracing_session->state != TracingSession::STARTED) + return; + + uint32_t clear_period_ms = + tracing_session->config.incremental_state_config().clear_period_ms(); + auto weak_this = weak_ptr_factory_.GetWeakPtr(); + task_runner_->PostDelayedTask( + [weak_this, tsid] { + if (weak_this) + weak_this->PeriodicClearIncrementalStateTask( + tsid, /*post_next_only=*/false); + }, + clear_period_ms - (base::GetWallTimeMs().count() % clear_period_ms)); + + if (post_next_only) + return; + + PERFETTO_DLOG( + "Performing periodic incremental state clear for trace session %" PRIu64, + tsid); + + // Queue the IPCs to producers with active data sources that opted in. + std::map<ProducerID, std::vector<DataSourceInstanceID>> clear_map; + for (const auto& kv : tracing_session->data_source_instances) { + ProducerID producer_id = kv.first; + const DataSourceInstance& data_source = kv.second; + if (data_source.handles_incremental_state_clear) + clear_map[producer_id].push_back(data_source.instance_id); + } + + for (const auto& kv : clear_map) { + ProducerID producer_id = kv.first; + const std::vector<DataSourceInstanceID>& data_sources = kv.second; + ProducerEndpointImpl* producer = GetProducer(producer_id); + if (!producer) { + PERFETTO_DFATAL("Producer does not exist."); + continue; + } + producer->ClearIncrementalState(data_sources); + } +} + // Note: when this is called to write into a file passed when starting tracing // |consumer| will be == nullptr (as opposite to the case of a consumer asking // to send the trace data back over IPC). @@ -1326,25 +1397,38 @@ void TracingServiceImpl::ReadBuffers(TracingSessionID tsid, // If the consumer enabled tracing and asked to save the contents into the // passed file makes little sense to also try to read the buffers over IPC, // as that would just steal data from the periodic draining task. - PERFETTO_DFATAL("Consumer trying to read from write_to_file session."); + PERFETTO_DFATAL("Consumer trying to read from write_into_file session."); return; } std::vector<TracePacket> packets; packets.reserve(1024); // Just an educated guess to avoid trivial expansions. + std::move(tracing_session->initial_clock_snapshot_.begin(), + tracing_session->initial_clock_snapshot_.end(), + std::back_inserter(packets)); + tracing_session->initial_clock_snapshot_.clear(); + base::TimeMillis now = base::GetWallTimeMs(); if (now >= tracing_session->last_snapshot_time + kSnapshotsInterval) { tracing_session->last_snapshot_time = now; SnapshotSyncMarker(&packets); SnapshotStats(tracing_session, &packets); - if (!tracing_session->config.disable_clock_snapshotting()) - SnapshotClocks(&packets); + if (!tracing_session->config.builtin_data_sources() + .disable_clock_snapshotting()) { + // We don't want to put a root timestamp in this snapshot as the packet + // may be very out of order with respect to the actual trace packets + // since consuming the trace may happen at any point after it starts. + SnapshotClocks(&packets, /*set_root_timestamp=*/false); + } + } + if (!tracing_session->config.builtin_data_sources().disable_trace_config()) { + MaybeEmitTraceConfig(tracing_session, &packets); + MaybeEmitReceivedTriggers(tracing_session, &packets); } - MaybeEmitTraceConfig(tracing_session, &packets); - MaybeEmitSystemInfo(tracing_session, &packets); - MaybeEmitReceivedTriggers(tracing_session, &packets); + if (!tracing_session->config.builtin_data_sources().disable_system_info()) + MaybeEmitSystemInfo(tracing_session, &packets); size_t packets_bytes = 0; // SUM(slice.size() for each slice in |packets|). size_t total_slices = 0; // SUM(#slices in |packets|). @@ -1707,11 +1791,13 @@ TracingServiceImpl::DataSourceInstance* TracingServiceImpl::SetupDataSource( auto insert_iter = tracing_session->data_source_instances.emplace( std::piecewise_construct, // std::forward_as_tuple(producer->id_), - std::forward_as_tuple(inst_id, - cfg_data_source.config(), // Deliberate copy. - data_source.descriptor.name(), - data_source.descriptor.will_notify_on_start(), - data_source.descriptor.will_notify_on_stop())); + std::forward_as_tuple( + inst_id, + cfg_data_source.config(), // Deliberate copy. + data_source.descriptor.name(), + data_source.descriptor.will_notify_on_start(), + data_source.descriptor.will_notify_on_stop(), + data_source.descriptor.handles_incremental_state_clear())); DataSourceInstance* ds_instance = &insert_iter->second; // New data source instance starts out in CONFIGURED state. @@ -2000,7 +2086,8 @@ void TracingServiceImpl::SnapshotSyncMarker(std::vector<TracePacket>* packets) { packets->back().AddSlice(&sync_marker_packet_[0], sync_marker_packet_size_); } -void TracingServiceImpl::SnapshotClocks(std::vector<TracePacket>* packets) { +void TracingServiceImpl::SnapshotClocks(std::vector<TracePacket>* packets, + bool set_root_timestamp) { protos::TrustedPacket packet; protos::ClockSnapshot* clock_snapshot = packet.mutable_clock_snapshot(); @@ -2036,15 +2123,23 @@ void TracingServiceImpl::SnapshotClocks(std::vector<TracePacket>* packets) { PERFETTO_DLOG("clock_gettime failed for clock %d", clock.id); } for (auto& clock : clocks) { + if (set_root_timestamp && + clock.type == protos::ClockSnapshot::Clock::BOOTTIME) { + packet.set_timestamp( + static_cast<uint64_t>(base::FromPosixTimespec(clock.ts).count())); + }; protos::ClockSnapshot::Clock* c = clock_snapshot->add_clocks(); c->set_type(clock.type); c->set_timestamp( static_cast<uint64_t>(base::FromPosixTimespec(clock.ts).count())); } #else // !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) + auto wall_time_ns = static_cast<uint64_t>(base::GetWallTimeNs().count()); + if (set_root_timestamp) + packet.set_timestamp(wall_time_ns); protos::ClockSnapshot::Clock* c = clock_snapshot->add_clocks(); c->set_type(protos::ClockSnapshot::Clock::MONOTONIC); - c->set_timestamp(static_cast<uint64_t>(base::GetWallTimeNs().count())); + c->set_timestamp(wall_time_ns); #endif // !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) packet.set_trusted_uid(static_cast<int32_t>(uid_)); @@ -2622,6 +2717,18 @@ void TracingServiceImpl::ProducerEndpointImpl::OnFreeBuffers( allowed_target_buffers_.erase(buffer); } +void TracingServiceImpl::ProducerEndpointImpl::ClearIncrementalState( + const std::vector<DataSourceInstanceID>& data_sources) { + PERFETTO_DCHECK_THREAD(thread_checker_); + auto weak_this = weak_ptr_factory_.GetWeakPtr(); + task_runner_->PostTask([weak_this, data_sources] { + if (weak_this) { + weak_this->producer_->ClearIncrementalState(data_sources.data(), + data_sources.size()); + } + }); +} + //////////////////////////////////////////////////////////////////////////////// // TracingServiceImpl::TracingSession implementation //////////////////////////////////////////////////////////////////////////////// diff --git a/src/tracing/core/tracing_service_impl.h b/src/tracing/core/tracing_service_impl.h index 474bd7be2..fbae3b607 100644 --- a/src/tracing/core/tracing_service_impl.h +++ b/src/tracing/core/tracing_service_impl.h @@ -102,6 +102,7 @@ class TracingServiceImpl : public TracingService { void StopDataSource(DataSourceInstanceID); void Flush(FlushRequestID, const std::vector<DataSourceInstanceID>&); void OnFreeBuffers(const std::vector<BufferID>& target_buffers); + void ClearIncrementalState(const std::vector<DataSourceInstanceID>&); bool is_allowed_target_buffer(BufferID buffer_id) const { return allowed_target_buffers_.count(buffer_id); @@ -289,12 +290,15 @@ class TracingServiceImpl : public TracingService { const DataSourceConfig& cfg, const std::string& ds_name, bool notify_on_start, - bool notify_on_stop) + bool notify_on_stop, + bool handles_incremental_state_invalidation) : instance_id(id), config(cfg), data_source_name(ds_name), will_notify_on_start(notify_on_start), - will_notify_on_stop(notify_on_stop) {} + will_notify_on_stop(notify_on_stop), + handles_incremental_state_clear( + handles_incremental_state_invalidation) {} DataSourceInstance(const DataSourceInstance&) = delete; DataSourceInstance& operator=(const DataSourceInstance&) = delete; @@ -303,6 +307,7 @@ class TracingServiceImpl : public TracingService { std::string data_source_name; bool will_notify_on_start; bool will_notify_on_stop; + bool handles_incremental_state_clear; enum DataSourceInstanceState { CONFIGURED, @@ -412,6 +417,9 @@ class TracingServiceImpl : public TracingService { // List of data source instances that have been enabled on the various // producers for this tracing session. + // TODO(rsavitski): at the time of writing, the map structure is unused + // (even when the calling code has a key). This is also an opportunity to + // consider an alternative data type, e.g. a map of vectors. std::multimap<ProducerID, DataSourceInstance> data_source_instances; // For each Flush(N) request, keeps track of the set of producers for which @@ -440,6 +448,11 @@ class TracingServiceImpl : public TracingService { // The number of received triggers we've emitted into the trace output. size_t num_triggers_emitted_into_trace = 0; + // Initial clock snapshot, captured at trace start time (when state goes + // to TracingSession::STARTED). Emitted into the trace when the consumer + // first begins reading the trace. + std::vector<TracePacket> initial_clock_snapshot_; + State state = DISABLED; // If the consumer detached the session, this variable defines the key used @@ -483,7 +496,7 @@ class TracingServiceImpl : public TracingService { TracingSession* tracing_session, DataSourceInstance* instance); void SnapshotSyncMarker(std::vector<TracePacket>*); - void SnapshotClocks(std::vector<TracePacket>*); + void SnapshotClocks(std::vector<TracePacket>*, bool set_root_timestamp); void SnapshotStats(TracingSession*, std::vector<TracePacket>*); TraceStats GetTraceStats(TracingSession* tracing_session); void MaybeEmitTraceConfig(TracingSession*, std::vector<TracePacket>*); @@ -498,6 +511,7 @@ class TracingServiceImpl : public TracingService { bool success); void ScrapeSharedMemoryBuffers(TracingSession* tracing_session, ProducerEndpointImpl* producer); + void PeriodicClearIncrementalStateTask(TracingSessionID, bool post_next_only); TraceBuffer* GetBufferByID(BufferID); void OnStartTriggersTimeout(TracingSessionID tsid); diff --git a/src/tracing/core/tracing_service_impl_unittest.cc b/src/tracing/core/tracing_service_impl_unittest.cc index a4c05bdc0..74eeacf01 100644 --- a/src/tracing/core/tracing_service_impl_unittest.cc +++ b/src/tracing/core/tracing_service_impl_unittest.cc @@ -186,6 +186,33 @@ class TracingServiceImplTest : public testing::Test { std::unique_ptr<TracingServiceImpl> svc; }; +TEST_F(TracingServiceImplTest, AtMostOneConfig) { + std::unique_ptr<MockConsumer> consumer_a = CreateMockConsumer(); + std::unique_ptr<MockConsumer> consumer_b = CreateMockConsumer(); + + consumer_a->Connect(svc.get()); + consumer_b->Connect(svc.get()); + + TraceConfig trace_config_a; + trace_config_a.add_buffers()->set_size_kb(128); + trace_config_a.set_duration_ms(0); + trace_config_a.set_unique_session_name("foo"); + + TraceConfig trace_config_b; + trace_config_b.add_buffers()->set_size_kb(128); + trace_config_b.set_duration_ms(0); + trace_config_b.set_unique_session_name("foo"); + + consumer_a->EnableTracing(trace_config_a); + consumer_b->EnableTracing(trace_config_b); + + // This will stop immediately since it has the same unique session name. + consumer_b->WaitForTracingDisabled(); + + consumer_a->DisableTracing(); + consumer_a->WaitForTracingDisabled(); +} + TEST_F(TracingServiceImplTest, RegisterAndUnregister) { std::unique_ptr<MockProducer> mock_producer_1 = CreateMockProducer(); std::unique_ptr<MockProducer> mock_producer_2 = CreateMockProducer(); @@ -1315,11 +1342,14 @@ TEST_F(TracingServiceImplTest, WriteIntoFileAndStopOnMaxSize) { producer->WaitForDataSourceStart("data_source"); // The preamble packets are: + // Trace start clocksnapshot // Config // SystemInfo - // 3x unknown - static const int kNumPreamblePackets = 5; - static const int kNumTestPackets = 10; + // Trace read clocksnapshot + // Trace synchronisation + // Trace stats + static const int kNumPreamblePackets = 6; + static const int kNumTestPackets = 9; static const char kPayload[] = "1234567890abcdef-"; std::unique_ptr<TraceWriter> writer = @@ -1615,6 +1645,83 @@ TEST_F(TracingServiceImplTest, PeriodicFlush) { } } +TEST_F(TracingServiceImplTest, PeriodicClearIncrementalState) { + std::unique_ptr<MockConsumer> consumer = CreateMockConsumer(); + consumer->Connect(svc.get()); + std::unique_ptr<MockProducer> producer = CreateMockProducer(); + producer->Connect(svc.get(), "mock_producer"); + + // Incremental data source that expects to receive the clear. + producer->RegisterDataSource("ds_incremental1", false, false, + /*handles_incremental_state_clear=*/true); + + // Incremental data source that expects to receive the clear. + producer->RegisterDataSource("ds_incremental2", false, false, + /*handles_incremental_state_clear=*/true); + + // Data source that does *not* advertise itself as supporting incremental + // state clears. + producer->RegisterDataSource("ds_selfcontained", false, false, + /*handles_incremental_state_clear=*/false); + + // Incremental data source that is registered, but won't be active within the + // test's tracing session. + producer->RegisterDataSource("ds_inactive", false, false, + /*handles_incremental_state_clear=*/true); + + TraceConfig trace_config; + trace_config.add_buffers()->set_size_kb(128); + trace_config.mutable_incremental_state_config()->set_clear_period_ms(1); + trace_config.add_data_sources()->mutable_config()->set_name( + "ds_selfcontained"); + trace_config.add_data_sources()->mutable_config()->set_name( + "ds_incremental1"); + trace_config.add_data_sources()->mutable_config()->set_name( + "ds_incremental2"); + + // note: the mocking is very brittle, and has to assume a specific order of + // the data sources' setup/start. + consumer->EnableTracing(trace_config); + producer->WaitForTracingSetup(); + producer->WaitForDataSourceSetup("ds_selfcontained"); + producer->WaitForDataSourceSetup("ds_incremental1"); + producer->WaitForDataSourceSetup("ds_incremental2"); + producer->WaitForDataSourceStart("ds_selfcontained"); + producer->WaitForDataSourceStart("ds_incremental1"); + producer->WaitForDataSourceStart("ds_incremental2"); + + DataSourceInstanceID ds_incremental1 = + producer->GetDataSourceInstanceId("ds_incremental1"); + DataSourceInstanceID ds_incremental2 = + producer->GetDataSourceInstanceId("ds_incremental2"); + + const size_t kNumClears = 3; + std::function<void()> checkpoint = + task_runner.CreateCheckpoint("clears_received"); + std::vector<std::vector<DataSourceInstanceID>> clears_seen; + EXPECT_CALL(*producer, ClearIncrementalState(_, _)) + .WillRepeatedly(Invoke([&clears_seen, &checkpoint]( + const DataSourceInstanceID* data_source_ids, + size_t num_data_sources) { + std::vector<DataSourceInstanceID> ds_ids; + for (size_t i = 0; i < num_data_sources; i++) { + ds_ids.push_back(*data_source_ids++); + } + clears_seen.push_back(ds_ids); + if (clears_seen.size() >= kNumClears) + checkpoint(); + })); + task_runner.RunUntilCheckpoint("clears_received"); + + consumer->DisableTracing(); + + // Assert that the clears were only for the active incremental data sources. + ASSERT_EQ(clears_seen.size(), kNumClears); + for (const std::vector<DataSourceInstanceID>& ds_ids : clears_seen) { + ASSERT_THAT(ds_ids, ElementsAreArray({ds_incremental1, ds_incremental2})); + } +} + // Creates a tracing session where some of the data sources set the // |will_notify_on_stop| flag and checks that the OnTracingDisabled notification // to the consumer is delayed until the acks are received. @@ -2327,6 +2434,62 @@ TEST_F(TracingServiceImplTest, ScrapeBuffersOnFlush) { consumer->WaitForTracingDisabled(); } +TEST_F(TracingServiceImplTest, ScrapeBuffersFromAnotherThread) { + // This test verifies that there are no reported TSAN races while scraping + // buffers from a producer which is actively writing more trace data + // concurrently. + svc->SetSMBScrapingEnabled(true); + + std::unique_ptr<MockConsumer> consumer = CreateMockConsumer(); + consumer->Connect(svc.get()); + + std::unique_ptr<MockProducer> producer = CreateMockProducer(); + producer->Connect(svc.get(), "mock_producer"); + ProducerID producer_id = *last_producer_id(); + producer->RegisterDataSource("data_source"); + + TraceConfig trace_config; + trace_config.add_buffers()->set_size_kb(128); + auto* ds_config = trace_config.add_data_sources()->mutable_config(); + ds_config->set_name("data_source"); + ds_config->set_target_buffer(0); + consumer->EnableTracing(trace_config); + + producer->WaitForTracingSetup(); + producer->WaitForDataSourceSetup("data_source"); + producer->WaitForDataSourceStart("data_source"); + consumer->StartTracing(); + + std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter( + tracing_session()->buffers_index[0]); + WaitForTraceWritersChanged(producer_id); + + constexpr int kPacketCount = 10; + std::atomic<int> packets_written{}; + std::thread writer_thread([&] { + for (int i = 0; i < kPacketCount; i++) { + writer->NewTracePacket()->set_for_testing()->set_str("payload"); + packets_written.store(i, std::memory_order_relaxed); + } + }); + + // Wait until the thread has had some time to write some packets. + while (packets_written.load(std::memory_order_relaxed) < kPacketCount / 2) + base::SleepMicroseconds(5000); + + // Disabling tracing will trigger scraping. + consumer->DisableTracing(); + writer_thread.join(); + + // Because we don't synchronize with the producer thread, we can't make any + // guarantees about the number of packets we will successfully read. We just + // verify that no TSAN races are reported. + consumer->ReadBuffers(); + + producer->WaitForDataSourceStop("data_source"); + consumer->WaitForTracingDisabled(); +} + // Test scraping on producer disconnect. TEST_F(TracingServiceImplTest, ScrapeBuffersOnProducerDisconnect) { svc->SetSMBScrapingEnabled(true); diff --git a/src/tracing/ipc/producer/producer_ipc_client_impl.cc b/src/tracing/ipc/producer/producer_ipc_client_impl.cc index bb929f159..54bcb8066 100644 --- a/src/tracing/ipc/producer/producer_ipc_client_impl.cc +++ b/src/tracing/ipc/producer/producer_ipc_client_impl.cc @@ -164,11 +164,25 @@ void ProducerIPCClientImpl::OnServiceRequest( // uint64 and not stdint's uint64_t. On some 64 bit archs they differ on the // type (long vs long long) even though they have the same size. const auto* data_source_ids = cmd.flush().data_source_ids().data(); - static_assert(sizeof(data_source_ids[0]) == sizeof(FlushRequestID), + static_assert(sizeof(data_source_ids[0]) == sizeof(DataSourceInstanceID), "data_source_ids should be 64-bit"); - producer_->Flush(cmd.flush().request_id(), - reinterpret_cast<const FlushRequestID*>(data_source_ids), - static_cast<size_t>(cmd.flush().data_source_ids().size())); + producer_->Flush( + cmd.flush().request_id(), + reinterpret_cast<const DataSourceInstanceID*>(data_source_ids), + static_cast<size_t>(cmd.flush().data_source_ids().size())); + return; + } + + if (cmd.cmd_case() == + protos::GetAsyncCommandResponse::kClearIncrementalState) { + const auto* data_source_ids = + cmd.clear_incremental_state().data_source_ids().data(); + static_assert(sizeof(data_source_ids[0]) == sizeof(DataSourceInstanceID), + "data_source_ids should be 64-bit"); + producer_->ClearIncrementalState( + reinterpret_cast<const DataSourceInstanceID*>(data_source_ids), + static_cast<size_t>( + cmd.clear_incremental_state().data_source_ids().size())); return; } diff --git a/src/tracing/ipc/service/producer_ipc_service.cc b/src/tracing/ipc/service/producer_ipc_service.cc index 1eba3a801..90510589f 100644 --- a/src/tracing/ipc/service/producer_ipc_service.cc +++ b/src/tracing/ipc/service/producer_ipc_service.cc @@ -397,4 +397,21 @@ void ProducerIPCService::RemoteProducer::Flush( async_producer_commands.Resolve(std::move(cmd)); } +void ProducerIPCService::RemoteProducer::ClearIncrementalState( + const DataSourceInstanceID* data_source_ids, + size_t num_data_sources) { + if (!async_producer_commands.IsBound()) { + PERFETTO_DLOG( + "The Service tried to request an incremental state invalidation, but " + "the remote Producer has not yet initialized the connection"); + return; + } + auto cmd = ipc::AsyncResult<protos::GetAsyncCommandResponse>::Create(); + cmd.set_has_more(true); + for (size_t i = 0; i < num_data_sources; i++) + cmd->mutable_clear_incremental_state()->add_data_source_ids( + data_source_ids[i]); + async_producer_commands.Resolve(std::move(cmd)); +} + } // namespace perfetto diff --git a/src/tracing/ipc/service/producer_ipc_service.h b/src/tracing/ipc/service/producer_ipc_service.h index e6ebf0a08..5954680a9 100644 --- a/src/tracing/ipc/service/producer_ipc_service.h +++ b/src/tracing/ipc/service/producer_ipc_service.h @@ -92,6 +92,9 @@ class ProducerIPCService : public protos::ProducerPort { const DataSourceInstanceID* data_source_ids, size_t num_data_sources) override; + void ClearIncrementalState(const DataSourceInstanceID* data_source_ids, + size_t num_data_sources) override; + // The interface obtained from the core service business logic through // Service::ConnectProducer(this). This allows to invoke methods for a // specific Producer on the Service business logic. diff --git a/src/tracing/test/mock_producer.cc b/src/tracing/test/mock_producer.cc index 003a053a3..02c33ba88 100644 --- a/src/tracing/test/mock_producer.cc +++ b/src/tracing/test/mock_producer.cc @@ -59,11 +59,13 @@ void MockProducer::Connect(TracingService* svc, void MockProducer::RegisterDataSource(const std::string& name, bool ack_stop, - bool ack_start) { + bool ack_start, + bool handle_incremental_state_clear) { DataSourceDescriptor ds_desc; ds_desc.set_name(name); ds_desc.set_will_notify_on_stop(ack_stop); ds_desc.set_will_notify_on_start(ack_start); + ds_desc.set_handles_incremental_state_clear(handle_incremental_state_clear); service_endpoint_->RegisterDataSource(ds_desc); } diff --git a/src/tracing/test/mock_producer.h b/src/tracing/test/mock_producer.h index 9d785512b..309467865 100644 --- a/src/tracing/test/mock_producer.h +++ b/src/tracing/test/mock_producer.h @@ -49,7 +49,8 @@ class MockProducer : public Producer { size_t shared_memory_size_hint_bytes = 0); void RegisterDataSource(const std::string& name, bool ack_stop = false, - bool ack_start = false); + bool ack_start = false, + bool handle_incremental_state_clear = false); void UnregisterDataSource(const std::string& name); void RegisterTraceWriter(uint32_t writer_id, uint32_t target_buffer); void UnregisterTraceWriter(uint32_t writer_id); @@ -84,6 +85,8 @@ class MockProducer : public Producer { MOCK_METHOD0(OnTracingSetup, void()); MOCK_METHOD3(Flush, void(FlushRequestID, const DataSourceInstanceID*, size_t)); + MOCK_METHOD2(ClearIncrementalState, + void(const DataSourceInstanceID*, size_t)); private: base::TestTaskRunner* const task_runner_; diff --git a/src/tracing/test/tracing_integration_test.cc b/src/tracing/test/tracing_integration_test.cc index 161713cfb..41fd1d4f9 100644 --- a/src/tracing/test/tracing_integration_test.cc +++ b/src/tracing/test/tracing_integration_test.cc @@ -50,6 +50,7 @@ using testing::_; constexpr char kProducerSockName[] = TEST_SOCK_NAME("tracing_test-producer"); constexpr char kConsumerSockName[] = TEST_SOCK_NAME("tracing_test-consumer"); +// TODO(rsavitski): consider using src/tracing/test/mock_producer.h. class MockProducer : public Producer { public: ~MockProducer() override {} @@ -66,6 +67,8 @@ class MockProducer : public Producer { MOCK_METHOD0(OnTracingSetup, void()); MOCK_METHOD3(Flush, void(FlushRequestID, const DataSourceInstanceID*, size_t)); + MOCK_METHOD2(ClearIncrementalState, + void(const DataSourceInstanceID*, size_t)); }; class MockConsumer : public Consumer { diff --git a/test/end_to_end_integrationtest.cc b/test/end_to_end_integrationtest.cc index 267635427..b9d14e976 100644 --- a/test/end_to_end_integrationtest.cc +++ b/test/end_to_end_integrationtest.cc @@ -658,10 +658,10 @@ TEST_F(PerfettoCmdlineTest, NoSanitizers(StartTracingTrigger)) { // time. trigger->set_stop_delay_ms(500); - // We have 5 normal preample packets (trace config, clock, system info, sync - // marker, stats) and then since this is a trace with a trigger config we have - // an additional ReceivedTriggers packet. - constexpr size_t kPreamblePackets = 6; + // We have 6 normal preamble packets (start clock, trace config, clock, + // system info, sync marker, stats) and then since this is a trace with a + // trigger config we have an additional ReceivedTriggers packet. + constexpr size_t kPreamblePackets = 7; base::TestTaskRunner task_runner; @@ -735,10 +735,10 @@ TEST_F(PerfettoCmdlineTest, NoSanitizers(StopTracingTrigger)) { trigger->set_name("trigger_name_3"); trigger->set_stop_delay_ms(60000); - // We have 5 normal preample packets (trace config, clock, system info, sync - // marker, stats) and then since this is a trace with a trigger config we have - // an additional ReceivedTriggers packet. - constexpr size_t kPreamblePackets = 7; + // We have 6 normal preamble packets (start clock, trace config, clock, + // system info, sync marker, stats) and then since this is a trace with a + // trigger config we have an additional ReceivedTriggers packet. + constexpr size_t kPreamblePackets = 8; base::TestTaskRunner task_runner; diff --git a/test/end_to_end_shared_memory_fuzzer.cc b/test/end_to_end_shared_memory_fuzzer.cc index 3c324097e..c390340e0 100644 --- a/test/end_to_end_shared_memory_fuzzer.cc +++ b/test/end_to_end_shared_memory_fuzzer.cc @@ -99,6 +99,7 @@ class FakeProducer : public Producer { void StopDataSource(DataSourceInstanceID) override {} void OnTracingSetup() override {} void Flush(FlushRequestID, const DataSourceInstanceID*, size_t) override {} + void ClearIncrementalState(const DataSourceInstanceID*, size_t) {} private: const std::string name_; diff --git a/test/fake_producer.h b/test/fake_producer.h index 5e8d58759..460d88c11 100644 --- a/test/fake_producer.h +++ b/test/fake_producer.h @@ -54,6 +54,8 @@ class FakeProducer : public Producer { void StopDataSource(DataSourceInstanceID) override; void OnTracingSetup() override; void Flush(FlushRequestID, const DataSourceInstanceID*, size_t) override; + void ClearIncrementalState(const DataSourceInstanceID* /*data_source_ids*/, + size_t /*num_data_sources*/) override {} private: void Shutdown(); diff --git a/tools/gen_build b/tools/gen_build index d03f8d2f8..2bfbb3d0b 100755 --- a/tools/gen_build +++ b/tools/gen_build @@ -54,7 +54,8 @@ header = """# Copyright (C) 2019 The Android Open Source Project """.format(__file__) # Arguments for the GN output directory. -gn_args = 'target_os="linux" is_debug=false' +# host_os="linux" is to generate the right build files from Mac OS. +gn_args = 'target_os="linux" is_debug=false host_os="linux"' # Default targets to translate to the blueprint file. default_targets = [ diff --git a/tools/gen_tracing_cpp_headers_from_protos b/tools/gen_tracing_cpp_headers_from_protos index 7728949d9..9ae472a8d 100755 --- a/tools/gen_tracing_cpp_headers_from_protos +++ b/tools/gen_tracing_cpp_headers_from_protos @@ -40,7 +40,7 @@ PROTOS = ( HEADER_PATH = 'include/perfetto/tracing/core' CPP_PATH = 'src/tracing/core' INCLUDE_PATH = 'perfetto/tracing/core' - +ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) def run(cmd): print('\nRunning ' + ' '.join(cmd)) @@ -55,7 +55,9 @@ def main(): print('Usage: %s out/xxx' % sys.argv[0]) return 1 out_dir = sys.argv[1] - clang_format = ['clang-format', '-i', '--sort-includes'] + arch = 'mac' if sys.platform == 'darwin' else 'linux64' + clang_format_path = os.path.join(ROOT_DIR, 'buildtools', arch, 'clang-format') + clang_format = [clang_format_path, '-i', '--sort-includes'] tool = os.path.join(out_dir, 'proto_to_cpp') if not os.path.exists(tool): print('Could not find %s, run ninja -C %s proto_to_cpp' % (tool, out_dir)) |