Merge "Add producer for Perfetto Java Heap Profiler."
diff --git a/Android.bp b/Android.bp
index d5c0aeb..e3c6e27 100644
--- a/Android.bp
+++ b/Android.bp
@@ -73,7 +73,9 @@
":perfetto_protos_perfetto_config_sys_stats_zero_gen",
":perfetto_protos_perfetto_config_zero_gen",
":perfetto_protos_perfetto_ipc_ipc_gen",
+ ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
":perfetto_protos_perfetto_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_appended_data_zero_gen",
":perfetto_protos_perfetto_trace_chrome_zero_gen",
":perfetto_protos_perfetto_trace_filesystem_zero_gen",
":perfetto_protos_perfetto_trace_ftrace_zero_gen",
@@ -89,7 +91,6 @@
":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
":perfetto_protos_perfetto_trace_track_event_zero_gen",
":perfetto_protos_perfetto_trace_trusted_lite_gen",
- ":perfetto_src_ipc_wire_protocol_gen",
"src/base/event_fd.cc",
"src/base/file_utils.cc",
"src/base/metatrace.cc",
@@ -158,6 +159,13 @@
"src/tracing/core/tracing_service_impl.cc",
"src/tracing/core/tracing_service_state.cc",
"src/tracing/core/virtual_destructors.cc",
+ "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
+ "src/tracing/ipc/default_socket.cc",
+ "src/tracing/ipc/posix_shared_memory.cc",
+ "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
+ "src/tracing/ipc/service/consumer_ipc_service.cc",
+ "src/tracing/ipc/service/producer_ipc_service.cc",
+ "src/tracing/ipc/service/service_ipc_host_impl.cc",
"src/tracing/trace_writer_base.cc",
],
shared_libs: [
@@ -167,9 +175,6 @@
"libprotobuf-cpp-lite",
"libunwindstack",
],
- static_libs: [
- "perfetto_src_tracing_ipc",
- ],
init_rc: [
"heapprofd.rc",
],
@@ -195,7 +200,9 @@
"perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
"perfetto_protos_perfetto_config_zero_gen_headers",
"perfetto_protos_perfetto_ipc_ipc_gen_headers",
+ "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
"perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_zero_gen_headers",
"perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
"perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
"perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
@@ -211,7 +218,6 @@
"perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
"perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
"perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
- "perfetto_src_ipc_wire_protocol_gen_headers",
],
defaults: [
"perfetto_defaults",
@@ -299,7 +305,9 @@
":perfetto_protos_perfetto_config_sys_stats_zero_gen",
":perfetto_protos_perfetto_config_zero_gen",
":perfetto_protos_perfetto_ipc_ipc_gen",
+ ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
":perfetto_protos_perfetto_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_appended_data_zero_gen",
":perfetto_protos_perfetto_trace_chrome_zero_gen",
":perfetto_protos_perfetto_trace_filesystem_zero_gen",
":perfetto_protos_perfetto_trace_ftrace_zero_gen",
@@ -315,7 +323,6 @@
":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
":perfetto_protos_perfetto_trace_track_event_zero_gen",
":perfetto_protos_perfetto_trace_trusted_lite_gen",
- ":perfetto_src_ipc_wire_protocol_gen",
"src/android_internal/lazy_library_loader.cc",
"src/base/event_fd.cc",
"src/base/file_utils.cc",
@@ -404,15 +411,19 @@
"src/tracing/core/tracing_service_impl.cc",
"src/tracing/core/tracing_service_state.cc",
"src/tracing/core/virtual_destructors.cc",
+ "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
+ "src/tracing/ipc/default_socket.cc",
+ "src/tracing/ipc/posix_shared_memory.cc",
+ "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
+ "src/tracing/ipc/service/consumer_ipc_service.cc",
+ "src/tracing/ipc/service/producer_ipc_service.cc",
+ "src/tracing/ipc/service/service_ipc_host_impl.cc",
"src/tracing/trace_writer_base.cc",
],
shared_libs: [
"liblog",
"libprotobuf-cpp-lite",
],
- static_libs: [
- "perfetto_src_tracing_ipc",
- ],
export_include_dirs: [
"include",
"include/perfetto/base/build_configs/android_tree",
@@ -439,7 +450,9 @@
"perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
"perfetto_protos_perfetto_config_zero_gen_headers",
"perfetto_protos_perfetto_ipc_ipc_gen_headers",
+ "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
"perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_zero_gen_headers",
"perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
"perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
"perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
@@ -455,7 +468,6 @@
"perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
"perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
"perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
- "perfetto_src_ipc_wire_protocol_gen_headers",
],
defaults: [
"perfetto_defaults",
@@ -530,7 +542,9 @@
":perfetto_protos_perfetto_config_sys_stats_zero_gen",
":perfetto_protos_perfetto_config_zero_gen",
":perfetto_protos_perfetto_ipc_ipc_gen",
+ ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
":perfetto_protos_perfetto_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_appended_data_zero_gen",
":perfetto_protos_perfetto_trace_chrome_zero_gen",
":perfetto_protos_perfetto_trace_filesystem_zero_gen",
":perfetto_protos_perfetto_trace_ftrace_zero_gen",
@@ -546,7 +560,6 @@
":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
":perfetto_protos_perfetto_trace_track_event_zero_gen",
":perfetto_protos_perfetto_trace_trusted_lite_gen",
- ":perfetto_src_ipc_wire_protocol_gen",
"src/base/event_fd.cc",
"src/base/file_utils.cc",
"src/base/metatrace.cc",
@@ -604,6 +617,13 @@
"src/tracing/internal/in_process_tracing_backend.cc",
"src/tracing/internal/system_tracing_backend.cc",
"src/tracing/internal/tracing_muxer_impl.cc",
+ "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
+ "src/tracing/ipc/default_socket.cc",
+ "src/tracing/ipc/posix_shared_memory.cc",
+ "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
+ "src/tracing/ipc/service/consumer_ipc_service.cc",
+ "src/tracing/ipc/service/producer_ipc_service.cc",
+ "src/tracing/ipc/service/service_ipc_host_impl.cc",
"src/tracing/platform.cc",
"src/tracing/platform_posix.cc",
"src/tracing/trace_writer_base.cc",
@@ -614,9 +634,6 @@
shared_libs: [
"libprotobuf-cpp-lite",
],
- static_libs: [
- "perfetto_src_tracing_ipc",
- ],
export_include_dirs: [
"include",
"include/perfetto/base/build_configs/android_tree",
@@ -643,7 +660,9 @@
"perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
"perfetto_protos_perfetto_config_zero_gen_headers",
"perfetto_protos_perfetto_ipc_ipc_gen_headers",
+ "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
"perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_zero_gen_headers",
"perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
"perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
"perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
@@ -659,7 +678,6 @@
"perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
"perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
"perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
- "perfetto_src_ipc_wire_protocol_gen_headers",
],
export_generated_headers: [
"perfetto_protos_perfetto_common_lite_gen_headers",
@@ -683,7 +701,9 @@
"perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
"perfetto_protos_perfetto_config_zero_gen_headers",
"perfetto_protos_perfetto_ipc_ipc_gen_headers",
+ "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
"perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_zero_gen_headers",
"perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
"perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
"perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
@@ -699,7 +719,6 @@
"perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
"perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
"perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
- "perfetto_src_ipc_wire_protocol_gen_headers",
],
defaults: [
"perfetto_defaults",
@@ -735,7 +754,9 @@
":perfetto_protos_perfetto_config_sys_stats_zero_gen",
":perfetto_protos_perfetto_config_zero_gen",
":perfetto_protos_perfetto_ipc_ipc_gen",
+ ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
":perfetto_protos_perfetto_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_appended_data_zero_gen",
":perfetto_protos_perfetto_trace_chrome_zero_gen",
":perfetto_protos_perfetto_trace_filesystem_zero_gen",
":perfetto_protos_perfetto_trace_ftrace_zero_gen",
@@ -751,7 +772,6 @@
":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
":perfetto_protos_perfetto_trace_track_event_zero_gen",
":perfetto_protos_perfetto_trace_trusted_lite_gen",
- ":perfetto_src_ipc_wire_protocol_gen",
":perfetto_src_perfetto_cmd_protos_gen",
"src/android_internal/lazy_library_loader.cc",
"src/base/event_fd.cc",
@@ -815,6 +835,13 @@
"src/tracing/core/tracing_service_impl.cc",
"src/tracing/core/tracing_service_state.cc",
"src/tracing/core/virtual_destructors.cc",
+ "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
+ "src/tracing/ipc/default_socket.cc",
+ "src/tracing/ipc/posix_shared_memory.cc",
+ "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
+ "src/tracing/ipc/service/consumer_ipc_service.cc",
+ "src/tracing/ipc/service/producer_ipc_service.cc",
+ "src/tracing/ipc/service/service_ipc_host_impl.cc",
"src/tracing/trace_writer_base.cc",
],
shared_libs: [
@@ -822,9 +849,6 @@
"libprotobuf-cpp-lite",
"libz",
],
- static_libs: [
- "perfetto_src_tracing_ipc",
- ],
generated_headers: [
"perfetto_protos_perfetto_common_lite_gen_headers",
"perfetto_protos_perfetto_common_zero_gen_headers",
@@ -847,7 +871,9 @@
"perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
"perfetto_protos_perfetto_config_zero_gen_headers",
"perfetto_protos_perfetto_ipc_ipc_gen_headers",
+ "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
"perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_zero_gen_headers",
"perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
"perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
"perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
@@ -863,7 +889,6 @@
"perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
"perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
"perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
- "perfetto_src_ipc_wire_protocol_gen_headers",
"perfetto_src_perfetto_cmd_protos_gen_headers",
],
defaults: [
@@ -930,8 +955,11 @@
":perfetto_protos_perfetto_config_sys_stats_zero_gen",
":perfetto_protos_perfetto_config_zero_gen",
":perfetto_protos_perfetto_ipc_ipc_gen",
+ ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
":perfetto_protos_perfetto_trace_android_lite_gen",
":perfetto_protos_perfetto_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_appended_data_lite_gen",
+ ":perfetto_protos_perfetto_trace_appended_data_zero_gen",
":perfetto_protos_perfetto_trace_chrome_lite_gen",
":perfetto_protos_perfetto_trace_chrome_zero_gen",
":perfetto_protos_perfetto_trace_filesystem_lite_gen",
@@ -959,7 +987,6 @@
":perfetto_protos_perfetto_trace_track_event_lite_gen",
":perfetto_protos_perfetto_trace_track_event_zero_gen",
":perfetto_protos_perfetto_trace_trusted_lite_gen",
- ":perfetto_src_ipc_wire_protocol_gen",
"src/android_internal/lazy_library_loader.cc",
"src/base/event_fd.cc",
"src/base/file_utils.cc",
@@ -1070,6 +1097,13 @@
"src/tracing/internal/in_process_tracing_backend.cc",
"src/tracing/internal/system_tracing_backend.cc",
"src/tracing/internal/tracing_muxer_impl.cc",
+ "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
+ "src/tracing/ipc/default_socket.cc",
+ "src/tracing/ipc/posix_shared_memory.cc",
+ "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
+ "src/tracing/ipc/service/consumer_ipc_service.cc",
+ "src/tracing/ipc/service/producer_ipc_service.cc",
+ "src/tracing/ipc/service/service_ipc_host_impl.cc",
"src/tracing/platform.cc",
"src/tracing/platform_posix.cc",
"src/tracing/test/api_test_support.cc",
@@ -1093,7 +1127,6 @@
static_libs: [
"libgmock",
"libperfetto_client_experimental",
- "perfetto_src_tracing_ipc",
],
generated_headers: [
"perfetto_protos_perfetto_common_lite_gen_headers",
@@ -1117,8 +1150,11 @@
"perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
"perfetto_protos_perfetto_config_zero_gen_headers",
"perfetto_protos_perfetto_ipc_ipc_gen_headers",
+ "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
"perfetto_protos_perfetto_trace_android_lite_gen_headers",
"perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_zero_gen_headers",
"perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
"perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
"perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
@@ -1146,7 +1182,6 @@
"perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
"perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
"perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
- "perfetto_src_ipc_wire_protocol_gen_headers",
],
defaults: [
"perfetto_defaults",
@@ -2013,6 +2048,40 @@
],
}
+// GN target: //protos/perfetto/ipc:wire_protocol_gen
+genrule {
+ name: "perfetto_protos_perfetto_ipc_wire_protocol_gen",
+ srcs: [
+ "protos/perfetto/ipc/wire_protocol.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/ipc/wire_protocol.pb.cc",
+ ],
+}
+
+// GN target: //protos/perfetto/ipc:wire_protocol_gen
+genrule {
+ name: "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
+ srcs: [
+ "protos/perfetto/ipc/wire_protocol.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/ipc/wire_protocol.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
+}
+
// GN target: //protos/perfetto/metrics/android:zero_gen
genrule {
name: "perfetto_protos_perfetto_metrics_android_zero_gen",
@@ -2211,6 +2280,76 @@
],
}
+// GN target: //protos/perfetto/trace/appended_data:lite_gen
+genrule {
+ name: "perfetto_protos_perfetto_trace_appended_data_lite_gen",
+ srcs: [
+ "protos/perfetto/trace/appended_data/appended_data.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/trace/appended_data/appended_data.pb.cc",
+ ],
+}
+
+// GN target: //protos/perfetto/trace/appended_data:lite_gen
+genrule {
+ name: "perfetto_protos_perfetto_trace_appended_data_lite_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/appended_data/appended_data.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/trace/appended_data/appended_data.pb.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
+}
+
+// GN target: //protos/perfetto/trace/appended_data:zero_gen
+genrule {
+ name: "perfetto_protos_perfetto_trace_appended_data_zero_gen",
+ srcs: [
+ "protos/perfetto/trace/appended_data/appended_data.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_protozero_plugin___gn_standalone_toolchain_gcc_like_host_",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protozero_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/trace/appended_data/appended_data.pbzero.cc",
+ ],
+}
+
+// GN target: //protos/perfetto/trace/appended_data:zero_gen
+genrule {
+ name: "perfetto_protos_perfetto_trace_appended_data_zero_gen_headers",
+ srcs: [
+ "protos/perfetto/trace/appended_data/appended_data.proto",
+ ],
+ tools: [
+ "aprotoc",
+ "perfetto_src_protozero_protoc_plugin_protozero_plugin___gn_standalone_toolchain_gcc_like_host_",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protozero_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto $(in)",
+ out: [
+ "external/perfetto/protos/perfetto/trace/appended_data/appended_data.pbzero.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
+}
+
// GN target: //protos/perfetto/trace/chrome:lite_gen
genrule {
name: "perfetto_protos_perfetto_trace_chrome_lite_gen",
@@ -2385,7 +2524,6 @@
"protos/perfetto/trace/ftrace/ftrace_event_bundle.proto",
"protos/perfetto/trace/ftrace/ftrace_stats.proto",
"protos/perfetto/trace/ftrace/generic.proto",
- "protos/perfetto/trace/ftrace/gpu.proto",
"protos/perfetto/trace/ftrace/i2c.proto",
"protos/perfetto/trace/ftrace/ipi.proto",
"protos/perfetto/trace/ftrace/irq.proto",
@@ -2425,7 +2563,6 @@
"external/perfetto/protos/perfetto/trace/ftrace/ftrace_event_bundle.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/generic.pb.cc",
- "external/perfetto/protos/perfetto/trace/ftrace/gpu.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/i2c.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/ipi.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/irq.pb.cc",
@@ -2466,7 +2603,6 @@
"protos/perfetto/trace/ftrace/ftrace_event_bundle.proto",
"protos/perfetto/trace/ftrace/ftrace_stats.proto",
"protos/perfetto/trace/ftrace/generic.proto",
- "protos/perfetto/trace/ftrace/gpu.proto",
"protos/perfetto/trace/ftrace/i2c.proto",
"protos/perfetto/trace/ftrace/ipi.proto",
"protos/perfetto/trace/ftrace/irq.proto",
@@ -2506,7 +2642,6 @@
"external/perfetto/protos/perfetto/trace/ftrace/ftrace_event_bundle.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/generic.pb.h",
- "external/perfetto/protos/perfetto/trace/ftrace/gpu.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/i2c.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/ipi.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/irq.pb.h",
@@ -2551,7 +2686,6 @@
"protos/perfetto/trace/ftrace/ftrace_event_bundle.proto",
"protos/perfetto/trace/ftrace/ftrace_stats.proto",
"protos/perfetto/trace/ftrace/generic.proto",
- "protos/perfetto/trace/ftrace/gpu.proto",
"protos/perfetto/trace/ftrace/i2c.proto",
"protos/perfetto/trace/ftrace/ipi.proto",
"protos/perfetto/trace/ftrace/irq.proto",
@@ -2592,7 +2726,6 @@
"external/perfetto/protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/generic.pbzero.cc",
- "external/perfetto/protos/perfetto/trace/ftrace/gpu.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/i2c.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/ipi.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/irq.pbzero.cc",
@@ -2633,7 +2766,6 @@
"protos/perfetto/trace/ftrace/ftrace_event_bundle.proto",
"protos/perfetto/trace/ftrace/ftrace_stats.proto",
"protos/perfetto/trace/ftrace/generic.proto",
- "protos/perfetto/trace/ftrace/gpu.proto",
"protos/perfetto/trace/ftrace/i2c.proto",
"protos/perfetto/trace/ftrace/ipi.proto",
"protos/perfetto/trace/ftrace/irq.proto",
@@ -2674,7 +2806,6 @@
"external/perfetto/protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/generic.pbzero.h",
- "external/perfetto/protos/perfetto/trace/ftrace/gpu.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/i2c.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/ipi.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/irq.pbzero.h",
@@ -3645,6 +3776,23 @@
cc_binary_host {
name: "perfetto_src_ipc_protoc_plugin_ipc_plugin___gn_standalone_toolchain_gcc_like_host_",
srcs: [
+ "src/base/event_fd.cc",
+ "src/base/file_utils.cc",
+ "src/base/metatrace.cc",
+ "src/base/paged_memory.cc",
+ "src/base/pipe.cc",
+ "src/base/string_splitter.cc",
+ "src/base/string_utils.cc",
+ "src/base/string_view.cc",
+ "src/base/temp_file.cc",
+ "src/base/thread_checker.cc",
+ "src/base/thread_task_runner.cc",
+ "src/base/time.cc",
+ "src/base/unix_task_runner.cc",
+ "src/base/uuid.cc",
+ "src/base/virtual_destructors.cc",
+ "src/base/waitable_event.cc",
+ "src/base/watchdog_posix.cc",
"src/ipc/protoc_plugin/ipc_plugin.cc",
],
shared_libs: [
@@ -3709,40 +3857,6 @@
],
}
-// GN target: //src/ipc:wire_protocol_gen
-genrule {
- name: "perfetto_src_ipc_wire_protocol_gen",
- srcs: [
- "src/ipc/wire_protocol.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto $(in)",
- out: [
- "external/perfetto/src/ipc/wire_protocol.pb.cc",
- ],
-}
-
-// GN target: //src/ipc:wire_protocol_gen
-genrule {
- name: "perfetto_src_ipc_wire_protocol_gen_headers",
- srcs: [
- "src/ipc/wire_protocol.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto $(in)",
- out: [
- "external/perfetto/src/ipc/wire_protocol.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- ],
-}
-
// GN target: //src/perfetto_cmd:protos_gen
genrule {
name: "perfetto_src_perfetto_cmd_protos_gen",
@@ -3781,6 +3895,23 @@
cc_binary_host {
name: "perfetto_src_protozero_protoc_plugin_protozero_plugin___gn_standalone_toolchain_gcc_like_host_",
srcs: [
+ "src/base/event_fd.cc",
+ "src/base/file_utils.cc",
+ "src/base/metatrace.cc",
+ "src/base/paged_memory.cc",
+ "src/base/pipe.cc",
+ "src/base/string_splitter.cc",
+ "src/base/string_utils.cc",
+ "src/base/string_view.cc",
+ "src/base/temp_file.cc",
+ "src/base/thread_checker.cc",
+ "src/base/thread_task_runner.cc",
+ "src/base/time.cc",
+ "src/base/unix_task_runner.cc",
+ "src/base/uuid.cc",
+ "src/base/virtual_destructors.cc",
+ "src/base/waitable_event.cc",
+ "src/base/watchdog_posix.cc",
"src/protozero/protoc_plugin/protozero_plugin.cc",
],
shared_libs: [
@@ -3959,206 +4090,6 @@
],
}
-// GN target: //src/tracing:ipc
-cc_library_static {
- name: "perfetto_src_tracing_ipc",
- srcs: [
- ":perfetto_protos_perfetto_common_lite_gen",
- ":perfetto_protos_perfetto_common_zero_gen",
- ":perfetto_protos_perfetto_config_android_lite_gen",
- ":perfetto_protos_perfetto_config_android_zero_gen",
- ":perfetto_protos_perfetto_config_ftrace_lite_gen",
- ":perfetto_protos_perfetto_config_ftrace_zero_gen",
- ":perfetto_protos_perfetto_config_gpu_lite_gen",
- ":perfetto_protos_perfetto_config_gpu_zero_gen",
- ":perfetto_protos_perfetto_config_inode_file_lite_gen",
- ":perfetto_protos_perfetto_config_inode_file_zero_gen",
- ":perfetto_protos_perfetto_config_lite_gen",
- ":perfetto_protos_perfetto_config_power_lite_gen",
- ":perfetto_protos_perfetto_config_power_zero_gen",
- ":perfetto_protos_perfetto_config_process_stats_lite_gen",
- ":perfetto_protos_perfetto_config_process_stats_zero_gen",
- ":perfetto_protos_perfetto_config_profiling_lite_gen",
- ":perfetto_protos_perfetto_config_profiling_zero_gen",
- ":perfetto_protos_perfetto_config_sys_stats_lite_gen",
- ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
- ":perfetto_protos_perfetto_config_zero_gen",
- ":perfetto_protos_perfetto_ipc_ipc_gen",
- ":perfetto_protos_perfetto_trace_android_zero_gen",
- ":perfetto_protos_perfetto_trace_chrome_zero_gen",
- ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
- ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
- ":perfetto_protos_perfetto_trace_gpu_zero_gen",
- ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
- ":perfetto_protos_perfetto_trace_minimal_lite_gen",
- ":perfetto_protos_perfetto_trace_minimal_zero_gen",
- ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
- ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
- ":perfetto_protos_perfetto_trace_power_zero_gen",
- ":perfetto_protos_perfetto_trace_profiling_zero_gen",
- ":perfetto_protos_perfetto_trace_ps_zero_gen",
- ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
- ":perfetto_protos_perfetto_trace_track_event_zero_gen",
- ":perfetto_protos_perfetto_trace_trusted_lite_gen",
- ":perfetto_src_ipc_wire_protocol_gen",
- "src/base/event_fd.cc",
- "src/base/file_utils.cc",
- "src/base/metatrace.cc",
- "src/base/paged_memory.cc",
- "src/base/pipe.cc",
- "src/base/string_splitter.cc",
- "src/base/string_utils.cc",
- "src/base/string_view.cc",
- "src/base/temp_file.cc",
- "src/base/thread_checker.cc",
- "src/base/thread_task_runner.cc",
- "src/base/time.cc",
- "src/base/unix_socket.cc",
- "src/base/unix_task_runner.cc",
- "src/base/uuid.cc",
- "src/base/virtual_destructors.cc",
- "src/base/waitable_event.cc",
- "src/base/watchdog_posix.cc",
- "src/ipc/buffered_frame_deserializer.cc",
- "src/ipc/client_impl.cc",
- "src/ipc/deferred.cc",
- "src/ipc/host_impl.cc",
- "src/ipc/service_proxy.cc",
- "src/ipc/virtual_destructors.cc",
- "src/protozero/message.cc",
- "src/protozero/message_handle.cc",
- "src/protozero/proto_decoder.cc",
- "src/protozero/scattered_heap_buffer.cc",
- "src/protozero/scattered_stream_null_delegate.cc",
- "src/protozero/scattered_stream_writer.cc",
- "src/tracing/core/chrome_config.cc",
- "src/tracing/core/commit_data_request.cc",
- "src/tracing/core/data_source_config.cc",
- "src/tracing/core/data_source_descriptor.cc",
- "src/tracing/core/id_allocator.cc",
- "src/tracing/core/metatrace_writer.cc",
- "src/tracing/core/null_trace_writer.cc",
- "src/tracing/core/observable_events.cc",
- "src/tracing/core/packet_stream_validator.cc",
- "src/tracing/core/shared_memory_abi.cc",
- "src/tracing/core/shared_memory_arbiter_impl.cc",
- "src/tracing/core/sliced_protobuf_input_stream.cc",
- "src/tracing/core/startup_trace_writer.cc",
- "src/tracing/core/startup_trace_writer_registry.cc",
- "src/tracing/core/test_config.cc",
- "src/tracing/core/trace_buffer.cc",
- "src/tracing/core/trace_config.cc",
- "src/tracing/core/trace_packet.cc",
- "src/tracing/core/trace_stats.cc",
- "src/tracing/core/trace_writer_impl.cc",
- "src/tracing/core/tracing_service_impl.cc",
- "src/tracing/core/tracing_service_state.cc",
- "src/tracing/core/virtual_destructors.cc",
- "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
- "src/tracing/ipc/default_socket.cc",
- "src/tracing/ipc/posix_shared_memory.cc",
- "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
- "src/tracing/ipc/service/consumer_ipc_service.cc",
- "src/tracing/ipc/service/producer_ipc_service.cc",
- "src/tracing/ipc/service/service_ipc_host_impl.cc",
- "src/tracing/trace_writer_base.cc",
- ],
- shared_libs: [
- "libprotobuf-cpp-lite",
- ],
- export_include_dirs: [
- "include",
- "include/perfetto/base/build_configs/android_tree",
- ],
- generated_headers: [
- "perfetto_protos_perfetto_common_lite_gen_headers",
- "perfetto_protos_perfetto_common_zero_gen_headers",
- "perfetto_protos_perfetto_config_android_lite_gen_headers",
- "perfetto_protos_perfetto_config_android_zero_gen_headers",
- "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
- "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
- "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
- "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
- "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
- "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
- "perfetto_protos_perfetto_config_lite_gen_headers",
- "perfetto_protos_perfetto_config_power_lite_gen_headers",
- "perfetto_protos_perfetto_config_power_zero_gen_headers",
- "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
- "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
- "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
- "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
- "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
- "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
- "perfetto_protos_perfetto_config_zero_gen_headers",
- "perfetto_protos_perfetto_ipc_ipc_gen_headers",
- "perfetto_protos_perfetto_trace_android_zero_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
- "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
- "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
- "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
- "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
- "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
- "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
- "perfetto_protos_perfetto_trace_power_zero_gen_headers",
- "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
- "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
- "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
- "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
- "perfetto_src_ipc_wire_protocol_gen_headers",
- ],
- export_generated_headers: [
- "perfetto_protos_perfetto_common_lite_gen_headers",
- "perfetto_protos_perfetto_common_zero_gen_headers",
- "perfetto_protos_perfetto_config_android_lite_gen_headers",
- "perfetto_protos_perfetto_config_android_zero_gen_headers",
- "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
- "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
- "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
- "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
- "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
- "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
- "perfetto_protos_perfetto_config_lite_gen_headers",
- "perfetto_protos_perfetto_config_power_lite_gen_headers",
- "perfetto_protos_perfetto_config_power_zero_gen_headers",
- "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
- "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
- "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
- "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
- "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
- "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
- "perfetto_protos_perfetto_config_zero_gen_headers",
- "perfetto_protos_perfetto_ipc_ipc_gen_headers",
- "perfetto_protos_perfetto_trace_android_zero_gen_headers",
- "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
- "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
- "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
- "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
- "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
- "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
- "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
- "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
- "perfetto_protos_perfetto_trace_power_zero_gen_headers",
- "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
- "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
- "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
- "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
- "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
- "perfetto_src_ipc_wire_protocol_gen_headers",
- ],
- defaults: [
- "perfetto_defaults",
- ],
- cflags: [
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- ],
-}
-
// GN target: //protos/perfetto/trace:perfetto_trace_protos
cc_library_static {
name: "perfetto_trace_protos",
@@ -4174,6 +4105,7 @@
":perfetto_protos_perfetto_config_profiling_lite_gen",
":perfetto_protos_perfetto_config_sys_stats_lite_gen",
":perfetto_protos_perfetto_trace_android_lite_gen",
+ ":perfetto_protos_perfetto_trace_appended_data_lite_gen",
":perfetto_protos_perfetto_trace_chrome_lite_gen",
":perfetto_protos_perfetto_trace_filesystem_lite_gen",
":perfetto_protos_perfetto_trace_ftrace_lite_gen",
@@ -4208,6 +4140,7 @@
"perfetto_protos_perfetto_config_profiling_lite_gen_headers",
"perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
"perfetto_protos_perfetto_trace_android_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_lite_gen_headers",
"perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
"perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
"perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
@@ -4234,6 +4167,7 @@
"perfetto_protos_perfetto_config_profiling_lite_gen_headers",
"perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
"perfetto_protos_perfetto_trace_android_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_lite_gen_headers",
"perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
"perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
"perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
@@ -4282,10 +4216,13 @@
":perfetto_protos_perfetto_config_sys_stats_zero_gen",
":perfetto_protos_perfetto_config_zero_gen",
":perfetto_protos_perfetto_ipc_ipc_gen",
+ ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
":perfetto_protos_perfetto_metrics_android_zero_gen",
":perfetto_protos_perfetto_metrics_zero_gen",
":perfetto_protos_perfetto_trace_android_lite_gen",
":perfetto_protos_perfetto_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_appended_data_lite_gen",
+ ":perfetto_protos_perfetto_trace_appended_data_zero_gen",
":perfetto_protos_perfetto_trace_chrome_lite_gen",
":perfetto_protos_perfetto_trace_chrome_zero_gen",
":perfetto_protos_perfetto_trace_filesystem_lite_gen",
@@ -4315,7 +4252,6 @@
":perfetto_protos_perfetto_trace_track_event_zero_gen",
":perfetto_protos_perfetto_trace_trusted_lite_gen",
":perfetto_src_ipc_test_messages_gen",
- ":perfetto_src_ipc_wire_protocol_gen",
":perfetto_src_perfetto_cmd_protos_gen",
":perfetto_src_protozero_testing_messages_lite_gen",
":perfetto_src_protozero_testing_messages_zero_gen",
@@ -4514,7 +4450,6 @@
"src/trace_processor/trace_sorter.cc",
"src/trace_processor/trace_sorter_unittest.cc",
"src/trace_processor/trace_storage.cc",
- "src/trace_processor/track_table.cc",
"src/trace_processor/virtual_destructors.cc",
"src/trace_processor/virtual_track_tracker.cc",
"src/trace_processor/window_operator_table.cc",
@@ -4607,7 +4542,14 @@
"src/tracing/core/tracing_service_impl_unittest.cc",
"src/tracing/core/tracing_service_state.cc",
"src/tracing/core/virtual_destructors.cc",
+ "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
+ "src/tracing/ipc/default_socket.cc",
+ "src/tracing/ipc/posix_shared_memory.cc",
"src/tracing/ipc/posix_shared_memory_unittest.cc",
+ "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
+ "src/tracing/ipc/service/consumer_ipc_service.cc",
+ "src/tracing/ipc/service/producer_ipc_service.cc",
+ "src/tracing/ipc/service/service_ipc_host_impl.cc",
"src/tracing/test/aligned_buffer_test.cc",
"src/tracing/test/fake_packet.cc",
"src/tracing/test/mock_consumer.cc",
@@ -4632,7 +4574,6 @@
],
static_libs: [
"libgmock",
- "perfetto_src_tracing_ipc",
],
generated_headers: [
"gen_merged_sql_metrics",
@@ -4657,10 +4598,13 @@
"perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
"perfetto_protos_perfetto_config_zero_gen_headers",
"perfetto_protos_perfetto_ipc_ipc_gen_headers",
+ "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
"perfetto_protos_perfetto_metrics_android_zero_gen_headers",
"perfetto_protos_perfetto_metrics_zero_gen_headers",
"perfetto_protos_perfetto_trace_android_lite_gen_headers",
"perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_zero_gen_headers",
"perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
"perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
"perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
@@ -4690,7 +4634,6 @@
"perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
"perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
"perfetto_src_ipc_test_messages_gen_headers",
- "perfetto_src_ipc_wire_protocol_gen_headers",
"perfetto_src_perfetto_cmd_protos_gen_headers",
"perfetto_src_protozero_testing_messages_lite_gen_headers",
"perfetto_src_protozero_testing_messages_zero_gen_headers",
@@ -4723,7 +4666,7 @@
}
// GN target: //src/trace_processor:trace_processor_shell
-cc_binary {
+cc_binary_host {
name: "trace_processor_shell",
srcs: [
":perfetto_protos_perfetto_common_zero_gen",
@@ -4739,6 +4682,7 @@
":perfetto_protos_perfetto_metrics_android_zero_gen",
":perfetto_protos_perfetto_metrics_zero_gen",
":perfetto_protos_perfetto_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_appended_data_zero_gen",
":perfetto_protos_perfetto_trace_chrome_zero_gen",
":perfetto_protos_perfetto_trace_filesystem_zero_gen",
":perfetto_protos_perfetto_trace_ftrace_zero_gen",
@@ -4839,17 +4783,18 @@
"src/trace_processor/trace_processor_shell.cc",
"src/trace_processor/trace_sorter.cc",
"src/trace_processor/trace_storage.cc",
- "src/trace_processor/track_table.cc",
"src/trace_processor/virtual_destructors.cc",
"src/trace_processor/virtual_track_tracker.cc",
"src/trace_processor/window_operator_table.cc",
],
shared_libs: [
"liblog",
- "libprotobuf-cpp-full",
+ "libprotoc",
"libz",
],
- host_supported: true,
+ static_libs: [
+ "libsqlite",
+ ],
generated_headers: [
"gen_merged_sql_metrics",
"perfetto_protos_perfetto_common_zero_gen_headers",
@@ -4865,6 +4810,7 @@
"perfetto_protos_perfetto_metrics_android_zero_gen_headers",
"perfetto_protos_perfetto_metrics_zero_gen_headers",
"perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_zero_gen_headers",
"perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
"perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
"perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
@@ -4888,21 +4834,6 @@
"-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
"-DHAVE_HIDDEN",
],
- target: {
- android: {
- shared_libs: [
- "libandroidicu",
- "liblog",
- "libsqlite",
- "libutils",
- ],
- },
- host: {
- static_libs: [
- "libsqlite",
- ],
- },
- },
}
// GN target: //tools/trace_to_text:trace_to_text
@@ -4933,6 +4864,8 @@
":perfetto_protos_perfetto_metrics_zero_gen",
":perfetto_protos_perfetto_trace_android_lite_gen",
":perfetto_protos_perfetto_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_appended_data_lite_gen",
+ ":perfetto_protos_perfetto_trace_appended_data_zero_gen",
":perfetto_protos_perfetto_trace_chrome_lite_gen",
":perfetto_protos_perfetto_trace_chrome_zero_gen",
":perfetto_protos_perfetto_trace_filesystem_lite_gen",
@@ -5045,7 +4978,6 @@
"src/trace_processor/trace_processor_impl.cc",
"src/trace_processor/trace_sorter.cc",
"src/trace_processor/trace_storage.cc",
- "src/trace_processor/track_table.cc",
"src/trace_processor/virtual_destructors.cc",
"src/trace_processor/virtual_track_tracker.cc",
"src/trace_processor/window_operator_table.cc",
@@ -5097,6 +5029,8 @@
"perfetto_protos_perfetto_metrics_zero_gen_headers",
"perfetto_protos_perfetto_trace_android_lite_gen_headers",
"perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_lite_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_zero_gen_headers",
"perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
"perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
"perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
@@ -5198,7 +5132,9 @@
":perfetto_protos_perfetto_config_sys_stats_zero_gen",
":perfetto_protos_perfetto_config_zero_gen",
":perfetto_protos_perfetto_ipc_ipc_gen",
+ ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
":perfetto_protos_perfetto_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_appended_data_zero_gen",
":perfetto_protos_perfetto_trace_chrome_zero_gen",
":perfetto_protos_perfetto_trace_filesystem_zero_gen",
":perfetto_protos_perfetto_trace_ftrace_zero_gen",
@@ -5214,7 +5150,6 @@
":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
":perfetto_protos_perfetto_trace_track_event_zero_gen",
":perfetto_protos_perfetto_trace_trusted_lite_gen",
- ":perfetto_src_ipc_wire_protocol_gen",
":perfetto_src_perfetto_cmd_protos_gen",
"src/base/event_fd.cc",
"src/base/file_utils.cc",
@@ -5272,15 +5207,19 @@
"src/tracing/core/tracing_service_impl.cc",
"src/tracing/core/tracing_service_state.cc",
"src/tracing/core/virtual_destructors.cc",
+ "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
+ "src/tracing/ipc/default_socket.cc",
+ "src/tracing/ipc/posix_shared_memory.cc",
+ "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
+ "src/tracing/ipc/service/consumer_ipc_service.cc",
+ "src/tracing/ipc/service/producer_ipc_service.cc",
+ "src/tracing/ipc/service/service_ipc_host_impl.cc",
"src/tracing/trace_writer_base.cc",
],
shared_libs: [
"liblog",
"libprotobuf-cpp-lite",
],
- static_libs: [
- "perfetto_src_tracing_ipc",
- ],
generated_headers: [
"perfetto_protos_perfetto_common_lite_gen_headers",
"perfetto_protos_perfetto_common_zero_gen_headers",
@@ -5303,7 +5242,9 @@
"perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
"perfetto_protos_perfetto_config_zero_gen_headers",
"perfetto_protos_perfetto_ipc_ipc_gen_headers",
+ "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
"perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_appended_data_zero_gen_headers",
"perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
"perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
"perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
@@ -5319,7 +5260,6 @@
"perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
"perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
"perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
- "perfetto_src_ipc_wire_protocol_gen_headers",
"perfetto_src_perfetto_cmd_protos_gen_headers",
],
defaults: [
@@ -5332,6 +5272,7 @@
}
// These targets are appended to the autogenerated Android.bp by tools/gen_android_bp.
+
cc_library_static {
name: "perfetto_cts_deps",
srcs: [
@@ -5355,7 +5296,7 @@
static_libs: [
"libgmock",
"libgtest",
- "perfetto_src_tracing_ipc",
+ "libperfetto_client_experimental",
"perfetto_trace_protos",
],
defaults: [
@@ -5375,7 +5316,7 @@
],
static_libs: [
"libgtest",
- "perfetto_src_tracing_ipc",
+ "libperfetto_client_experimental",
],
defaults: [
"perfetto_defaults",
@@ -5401,7 +5342,6 @@
],
static_libs: [
"libperfetto_client_experimental",
- "perfetto_src_tracing_ipc",
"perfetto_trace_protos",
],
shared_libs: [
@@ -5415,4 +5355,18 @@
defaults: [
"perfetto_defaults",
],
+}
+
+// TODO(primiano): remove this target after the dep from
+// frameworks/native/services/surfaceflinger/Android.bp goes away. This has been
+// introduced only to avoid multi-repo atomic CLs.
+
+cc_library_static {
+ name: "perfetto_src_tracing_ipc",
+ srcs: [
+ "src/android_internal/empty_file.cc",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
}
\ No newline at end of file
diff --git a/Android.bp.extras b/Android.bp.extras
index 354c97a..8aff22b 100644
--- a/Android.bp.extras
+++ b/Android.bp.extras
@@ -1,4 +1,5 @@
// These targets are appended to the autogenerated Android.bp by tools/gen_android_bp.
+
cc_library_static {
name: "perfetto_cts_deps",
srcs: [
@@ -22,7 +23,7 @@
static_libs: [
"libgmock",
"libgtest",
- "perfetto_src_tracing_ipc",
+ "libperfetto_client_experimental",
"perfetto_trace_protos",
],
defaults: [
@@ -42,7 +43,7 @@
],
static_libs: [
"libgtest",
- "perfetto_src_tracing_ipc",
+ "libperfetto_client_experimental",
],
defaults: [
"perfetto_defaults",
@@ -68,7 +69,6 @@
],
static_libs: [
"libperfetto_client_experimental",
- "perfetto_src_tracing_ipc",
"perfetto_trace_protos",
],
shared_libs: [
@@ -83,3 +83,17 @@
"perfetto_defaults",
],
}
+
+// TODO(primiano): remove this target after the dep from
+// frameworks/native/services/surfaceflinger/Android.bp goes away. This has been
+// introduced only to avoid multi-repo atomic CLs.
+
+cc_library_static {
+ name: "perfetto_src_tracing_ipc",
+ srcs: [
+ "src/android_internal/empty_file.cc",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
+}
diff --git a/BUILD b/BUILD
index 2fec784..5177498 100644
--- a/BUILD
+++ b/BUILD
@@ -171,6 +171,8 @@
"//third_party/perfetto/protos:protos_third_party_pprof_cc_proto",
"//third_party/perfetto/protos:trace_android_cc_proto",
"//third_party/perfetto/protos:trace_android_zero_cc_proto",
+ "//third_party/perfetto/protos:trace_appended_data_cc_proto",
+ "//third_party/perfetto/protos:trace_appended_data_zero_cc_proto",
"//third_party/perfetto/protos:trace_chrome_cc_proto",
"//third_party/perfetto/protos:trace_chrome_zero_cc_proto",
"//third_party/perfetto/protos:trace_filesystem_cc_proto",
@@ -270,6 +272,64 @@
cc_binary(
name = "src_protozero_protoc_plugin_protozero_plugin",
srcs = [
+ "include/perfetto/base/build_config.h",
+ "include/perfetto/base/build_configs/bazel/perfetto_build_flags.h",
+ "include/perfetto/base/compiler.h",
+ "include/perfetto/base/copyable_ptr.h",
+ "include/perfetto/base/export.h",
+ "include/perfetto/base/logging.h",
+ "include/perfetto/base/task_runner.h",
+ "include/perfetto/base/time.h",
+ "include/perfetto/ext/base/circular_queue.h",
+ "include/perfetto/ext/base/container_annotations.h",
+ "include/perfetto/ext/base/event_fd.h",
+ "include/perfetto/ext/base/file_utils.h",
+ "include/perfetto/ext/base/hash.h",
+ "include/perfetto/ext/base/lookup_set.h",
+ "include/perfetto/ext/base/metatrace.h",
+ "include/perfetto/ext/base/metatrace_events.h",
+ "include/perfetto/ext/base/no_destructor.h",
+ "include/perfetto/ext/base/optional.h",
+ "include/perfetto/ext/base/paged_memory.h",
+ "include/perfetto/ext/base/pipe.h",
+ "include/perfetto/ext/base/proc_utils.h",
+ "include/perfetto/ext/base/scoped_file.h",
+ "include/perfetto/ext/base/small_set.h",
+ "include/perfetto/ext/base/string_splitter.h",
+ "include/perfetto/ext/base/string_utils.h",
+ "include/perfetto/ext/base/string_view.h",
+ "include/perfetto/ext/base/string_writer.h",
+ "include/perfetto/ext/base/temp_file.h",
+ "include/perfetto/ext/base/thread_annotations.h",
+ "include/perfetto/ext/base/thread_checker.h",
+ "include/perfetto/ext/base/thread_task_runner.h",
+ "include/perfetto/ext/base/thread_utils.h",
+ "include/perfetto/ext/base/unix_socket.h",
+ "include/perfetto/ext/base/unix_task_runner.h",
+ "include/perfetto/ext/base/utils.h",
+ "include/perfetto/ext/base/uuid.h",
+ "include/perfetto/ext/base/waitable_event.h",
+ "include/perfetto/ext/base/watchdog.h",
+ "include/perfetto/ext/base/watchdog_noop.h",
+ "include/perfetto/ext/base/watchdog_posix.h",
+ "include/perfetto/ext/base/weak_ptr.h",
+ "src/base/event_fd.cc",
+ "src/base/file_utils.cc",
+ "src/base/metatrace.cc",
+ "src/base/paged_memory.cc",
+ "src/base/pipe.cc",
+ "src/base/string_splitter.cc",
+ "src/base/string_utils.cc",
+ "src/base/string_view.cc",
+ "src/base/temp_file.cc",
+ "src/base/thread_checker.cc",
+ "src/base/thread_task_runner.cc",
+ "src/base/time.cc",
+ "src/base/unix_task_runner.cc",
+ "src/base/uuid.cc",
+ "src/base/virtual_destructors.cc",
+ "src/base/waitable_event.cc",
+ "src/base/watchdog_posix.cc",
"src/protozero/protoc_plugin/protozero_plugin.cc",
],
deps = [
@@ -455,8 +515,6 @@
"src/trace_processor/trace_sorter.h",
"src/trace_processor/trace_storage.cc",
"src/trace_processor/trace_storage.h",
- "src/trace_processor/track_table.cc",
- "src/trace_processor/track_table.h",
"src/trace_processor/variadic.h",
"src/trace_processor/virtual_destructors.cc",
"src/trace_processor/virtual_track_tracker.cc",
@@ -537,6 +595,7 @@
"//third_party/perfetto/protos:metrics_android_zero_cc_proto",
"//third_party/perfetto/protos:metrics_zero_cc_proto",
"//third_party/perfetto/protos:trace_android_zero_cc_proto",
+ "//third_party/perfetto/protos:trace_appended_data_zero_cc_proto",
"//third_party/perfetto/protos:trace_chrome_zero_cc_proto",
"//third_party/perfetto/protos:trace_filesystem_zero_cc_proto",
"//third_party/perfetto/protos:trace_ftrace_zero_cc_proto",
@@ -562,6 +621,7 @@
name = "trace_processor_shell",
srcs = [
"include/perfetto/base/build_config.h",
+ "include/perfetto/base/build_configs/bazel/perfetto_build_flags.h",
"include/perfetto/base/compiler.h",
"include/perfetto/base/copyable_ptr.h",
"include/perfetto/base/export.h",
@@ -791,8 +851,6 @@
"src/trace_processor/trace_sorter.h",
"src/trace_processor/trace_storage.cc",
"src/trace_processor/trace_storage.h",
- "src/trace_processor/track_table.cc",
- "src/trace_processor/track_table.h",
"src/trace_processor/variadic.h",
"src/trace_processor/virtual_destructors.cc",
"src/trace_processor/virtual_track_tracker.cc",
@@ -817,6 +875,7 @@
"//third_party/perfetto/protos:metrics_android_zero_cc_proto",
"//third_party/perfetto/protos:metrics_zero_cc_proto",
"//third_party/perfetto/protos:trace_android_zero_cc_proto",
+ "//third_party/perfetto/protos:trace_appended_data_zero_cc_proto",
"//third_party/perfetto/protos:trace_chrome_zero_cc_proto",
"//third_party/perfetto/protos:trace_filesystem_zero_cc_proto",
"//third_party/perfetto/protos:trace_ftrace_zero_cc_proto",
@@ -844,6 +903,7 @@
name = "trace_to_text",
srcs = [
"include/perfetto/base/build_config.h",
+ "include/perfetto/base/build_configs/bazel/perfetto_build_flags.h",
"include/perfetto/base/compiler.h",
"include/perfetto/base/copyable_ptr.h",
"include/perfetto/base/export.h",
@@ -1070,8 +1130,6 @@
"src/trace_processor/trace_sorter.h",
"src/trace_processor/trace_storage.cc",
"src/trace_processor/trace_storage.h",
- "src/trace_processor/track_table.cc",
- "src/trace_processor/track_table.h",
"src/trace_processor/variadic.h",
"src/trace_processor/virtual_destructors.cc",
"src/trace_processor/virtual_track_tracker.cc",
@@ -1130,6 +1188,8 @@
"//third_party/perfetto/protos:protos_third_party_pprof_cc_proto",
"//third_party/perfetto/protos:trace_android_cc_proto",
"//third_party/perfetto/protos:trace_android_zero_cc_proto",
+ "//third_party/perfetto/protos:trace_appended_data_cc_proto",
+ "//third_party/perfetto/protos:trace_appended_data_zero_cc_proto",
"//third_party/perfetto/protos:trace_chrome_cc_proto",
"//third_party/perfetto/protos:trace_chrome_zero_cc_proto",
"//third_party/perfetto/protos:trace_filesystem_cc_proto",
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index db40ea5..b491a6e 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -23,7 +23,7 @@
x, white_list=".*",
black_list=['Android[.]bp', '.*[.]json$', '.*[.]sql$', '.*[.]out$',
'test/trace_processor/index$', 'BUILD$', 'protos/BUILD$',
- '.*/Makefile$'])
+ '.*/Makefile$', '/perfetto_build_flags.h$'])
results = []
results += input.canned_checks.CheckDoNotSubmit(input, output)
results += input.canned_checks.CheckChangeHasNoTabs(input, output)
diff --git a/buildtools/BUILD.gn b/buildtools/BUILD.gn
index cdbdb6a..220fb8b 100644
--- a/buildtools/BUILD.gn
+++ b/buildtools/BUILD.gn
@@ -273,111 +273,111 @@
public_configs = [ ":protobuf_gen_config" ]
}
-if (current_toolchain == host_toolchain) {
- source_set("protoc_lib") {
- visibility = _buildtools_visibility
- deps = [
- ":protobuf_full",
- "//gn:default_deps",
- ]
- sources = [
- "protobuf/src/google/protobuf/compiler/code_generator.cc",
- "protobuf/src/google/protobuf/compiler/command_line_interface.cc",
- "protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc",
- "protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc",
- "protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc",
- "protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc",
- "protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc",
- "protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc",
- "protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc",
- "protobuf/src/google/protobuf/compiler/cpp/cpp_map_field.cc",
- "protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc",
- "protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc",
- "protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc",
- "protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc",
- "protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_enum.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_enum_field.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_field_base.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_generator.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_helpers.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_map_field.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_message.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_message_field.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc",
- "protobuf/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc",
- "protobuf/src/google/protobuf/compiler/java/java_context.cc",
- "protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc",
- "protobuf/src/google/protobuf/compiler/java/java_enum.cc",
- "protobuf/src/google/protobuf/compiler/java/java_enum_field.cc",
- "protobuf/src/google/protobuf/compiler/java/java_enum_field_lite.cc",
- "protobuf/src/google/protobuf/compiler/java/java_enum_lite.cc",
- "protobuf/src/google/protobuf/compiler/java/java_extension.cc",
- "protobuf/src/google/protobuf/compiler/java/java_extension_lite.cc",
- "protobuf/src/google/protobuf/compiler/java/java_field.cc",
- "protobuf/src/google/protobuf/compiler/java/java_file.cc",
- "protobuf/src/google/protobuf/compiler/java/java_generator.cc",
- "protobuf/src/google/protobuf/compiler/java/java_generator_factory.cc",
- "protobuf/src/google/protobuf/compiler/java/java_helpers.cc",
- "protobuf/src/google/protobuf/compiler/java/java_lazy_message_field.cc",
- "protobuf/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc",
- "protobuf/src/google/protobuf/compiler/java/java_map_field.cc",
- "protobuf/src/google/protobuf/compiler/java/java_map_field_lite.cc",
- "protobuf/src/google/protobuf/compiler/java/java_message.cc",
- "protobuf/src/google/protobuf/compiler/java/java_message_builder.cc",
- "protobuf/src/google/protobuf/compiler/java/java_message_builder_lite.cc",
- "protobuf/src/google/protobuf/compiler/java/java_message_field.cc",
- "protobuf/src/google/protobuf/compiler/java/java_message_field_lite.cc",
- "protobuf/src/google/protobuf/compiler/java/java_message_lite.cc",
- "protobuf/src/google/protobuf/compiler/java/java_name_resolver.cc",
- "protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc",
- "protobuf/src/google/protobuf/compiler/java/java_primitive_field_lite.cc",
- "protobuf/src/google/protobuf/compiler/java/java_service.cc",
- "protobuf/src/google/protobuf/compiler/java/java_shared_code_generator.cc",
- "protobuf/src/google/protobuf/compiler/java/java_string_field.cc",
- "protobuf/src/google/protobuf/compiler/java/java_string_field_lite.cc",
- "protobuf/src/google/protobuf/compiler/javanano/javanano_enum.cc",
- "protobuf/src/google/protobuf/compiler/javanano/javanano_enum_field.cc",
- "protobuf/src/google/protobuf/compiler/javanano/javanano_extension.cc",
- "protobuf/src/google/protobuf/compiler/javanano/javanano_field.cc",
- "protobuf/src/google/protobuf/compiler/javanano/javanano_file.cc",
- "protobuf/src/google/protobuf/compiler/javanano/javanano_generator.cc",
- "protobuf/src/google/protobuf/compiler/javanano/javanano_helpers.cc",
- "protobuf/src/google/protobuf/compiler/javanano/javanano_map_field.cc",
- "protobuf/src/google/protobuf/compiler/javanano/javanano_message.cc",
- "protobuf/src/google/protobuf/compiler/javanano/javanano_message_field.cc",
- "protobuf/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc",
- "protobuf/src/google/protobuf/compiler/js/js_generator.cc",
- "protobuf/src/google/protobuf/compiler/objectivec/objectivec_enum.cc",
- "protobuf/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc",
- "protobuf/src/google/protobuf/compiler/objectivec/objectivec_extension.cc",
- "protobuf/src/google/protobuf/compiler/objectivec/objectivec_field.cc",
- "protobuf/src/google/protobuf/compiler/objectivec/objectivec_file.cc",
- "protobuf/src/google/protobuf/compiler/objectivec/objectivec_generator.cc",
- "protobuf/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc",
- "protobuf/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc",
- "protobuf/src/google/protobuf/compiler/objectivec/objectivec_message.cc",
- "protobuf/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc",
- "protobuf/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc",
- "protobuf/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc",
- "protobuf/src/google/protobuf/compiler/plugin.cc",
- "protobuf/src/google/protobuf/compiler/plugin.pb.cc",
- "protobuf/src/google/protobuf/compiler/python/python_generator.cc",
- "protobuf/src/google/protobuf/compiler/ruby/ruby_generator.cc",
- "protobuf/src/google/protobuf/compiler/subprocess.cc",
- "protobuf/src/google/protobuf/compiler/zip_writer.cc",
- ]
- configs -= [ "//gn/standalone:extra_warnings" ]
- configs += [ ":protobuf_config" ]
- public_configs = [ ":protobuf_gen_config" ]
- }
+source_set("protoc_lib") {
+ visibility = _buildtools_visibility
+ deps = [
+ ":protobuf_full",
+ "//gn:default_deps",
+ ]
+ sources = [
+ "protobuf/src/google/protobuf/compiler/code_generator.cc",
+ "protobuf/src/google/protobuf/compiler/command_line_interface.cc",
+ "protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc",
+ "protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc",
+ "protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc",
+ "protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc",
+ "protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc",
+ "protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc",
+ "protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc",
+ "protobuf/src/google/protobuf/compiler/cpp/cpp_map_field.cc",
+ "protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc",
+ "protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc",
+ "protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc",
+ "protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc",
+ "protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_enum.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_enum_field.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_field_base.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_generator.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_helpers.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_map_field.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_message.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_message_field.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc",
+ "protobuf/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_context.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_enum.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_enum_field.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_enum_field_lite.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_enum_lite.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_extension.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_extension_lite.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_field.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_file.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_generator.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_generator_factory.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_helpers.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_lazy_message_field.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_map_field.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_map_field_lite.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_message.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_message_builder.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_message_builder_lite.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_message_field.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_message_field_lite.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_message_lite.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_name_resolver.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_primitive_field_lite.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_service.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_shared_code_generator.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_string_field.cc",
+ "protobuf/src/google/protobuf/compiler/java/java_string_field_lite.cc",
+ "protobuf/src/google/protobuf/compiler/javanano/javanano_enum.cc",
+ "protobuf/src/google/protobuf/compiler/javanano/javanano_enum_field.cc",
+ "protobuf/src/google/protobuf/compiler/javanano/javanano_extension.cc",
+ "protobuf/src/google/protobuf/compiler/javanano/javanano_field.cc",
+ "protobuf/src/google/protobuf/compiler/javanano/javanano_file.cc",
+ "protobuf/src/google/protobuf/compiler/javanano/javanano_generator.cc",
+ "protobuf/src/google/protobuf/compiler/javanano/javanano_helpers.cc",
+ "protobuf/src/google/protobuf/compiler/javanano/javanano_map_field.cc",
+ "protobuf/src/google/protobuf/compiler/javanano/javanano_message.cc",
+ "protobuf/src/google/protobuf/compiler/javanano/javanano_message_field.cc",
+ "protobuf/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc",
+ "protobuf/src/google/protobuf/compiler/js/js_generator.cc",
+ "protobuf/src/google/protobuf/compiler/objectivec/objectivec_enum.cc",
+ "protobuf/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc",
+ "protobuf/src/google/protobuf/compiler/objectivec/objectivec_extension.cc",
+ "protobuf/src/google/protobuf/compiler/objectivec/objectivec_field.cc",
+ "protobuf/src/google/protobuf/compiler/objectivec/objectivec_file.cc",
+ "protobuf/src/google/protobuf/compiler/objectivec/objectivec_generator.cc",
+ "protobuf/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc",
+ "protobuf/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc",
+ "protobuf/src/google/protobuf/compiler/objectivec/objectivec_message.cc",
+ "protobuf/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc",
+ "protobuf/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc",
+ "protobuf/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc",
+ "protobuf/src/google/protobuf/compiler/plugin.cc",
+ "protobuf/src/google/protobuf/compiler/plugin.pb.cc",
+ "protobuf/src/google/protobuf/compiler/python/python_generator.cc",
+ "protobuf/src/google/protobuf/compiler/ruby/ruby_generator.cc",
+ "protobuf/src/google/protobuf/compiler/subprocess.cc",
+ "protobuf/src/google/protobuf/compiler/zip_writer.cc",
+ ]
+ configs -= [ "//gn/standalone:extra_warnings" ]
+ configs += [ ":protobuf_config" ]
+ public_configs = [ ":protobuf_gen_config" ]
+}
+if (current_toolchain == host_toolchain) {
executable("protoc") {
visibility = _buildtools_visibility
deps = [
diff --git a/docs/embedder-guide.md b/docs/embedder-guide.md
index 226e086..fbe3be3 100644
--- a/docs/embedder-guide.md
+++ b/docs/embedder-guide.md
@@ -20,7 +20,7 @@
- [service.h](/include/perfetto/tracing/core/tracing_service.h)
- Explain the ABI surface:
- [shared_memory_abi.h](/include/perfetto/tracing/core/shared_memory_abi.h)
- - IPC's [wire protocol](/src/ipc/wire_protocol.proto) (if used)
+ - IPC's [wire protocol](/protos/perfetto/ipc/wire_protocol.proto) (if used)
- The input [config protos](/protos/perfetto/config)
- The output [trace protos](/protos/perfetto/trace)
diff --git a/docs/heapprofd.md b/docs/heapprofd.md
index 2a330cd..96a259c 100644
--- a/docs/heapprofd.md
+++ b/docs/heapprofd.md
@@ -230,6 +230,7 @@
## Known Issues
+### Android 10
* Does not work on x86 platforms (including the Android cuttlefish emulator).
* If heapprofd is run standalone (by running `heapprofd` in a root shell, rather
than through init), `/dev/socket/heapprofd` get assigned an incorrect SELinux
diff --git a/docs/ipc.md b/docs/ipc.md
index 33d3a5c..ac7c36a 100644
--- a/docs/ipc.md
+++ b/docs/ipc.md
@@ -18,7 +18,7 @@
- Allows to send file descriptors over the wire: for setting up shared memory
and passing the FD for the output trace from a consumer to the service.
- Service definition uses same protobuf rpc syntax of [gRPC](https://grpc.io)
-- Extremely simple [wire protocol](/src/ipc/wire_protocol.proto).
+- Extremely simple [wire protocol](/protos/perfetto/ipc/wire_protocol.proto).
- C++11 friendly, allows to bind `std::function` to each request.
- Leak (un)friendly: tries hard to guarantee that callbacks are left unresolved,
using C++11 move semantics.
@@ -31,7 +31,7 @@
- Debugging friendly: single-thread only, based on non-blocking socket I/O.
- Binary size friendly: generates one protobuf per message, doesn't have any
external dependency.
-- Hopefully safe:
+- Safe:
- The rx buffer has guard regions around.
- The wire protocol is based on protobuf.
- [Fuzzed](/src/ipc/buffered_frame_deserializer_fuzzer.cc)
diff --git a/docs/running.md b/docs/running.md
index 13b13ff..7529186 100644
--- a/docs/running.md
+++ b/docs/running.md
@@ -3,17 +3,17 @@
In order to run Perfetto and get a meaningful trace you need to build
(see [build instructions](build-instructions.md)) and run the following:
-`traced`:
+`traced`:
The unprivileged trace daemon that owns the log buffers and maintains
a registry of Producers and Consumers connected.
-`traced_probes`:
+`traced_probes`:
The privileged daemon that has access to the Kernel tracefs
(typically mounted under `/sys/kernel/debug/tracing`). It drives
[Ftrace](https://source.android.com/devices/tech/debug/ftrace) and writes its
protobuf-translated contents into `traced`.
-`perfetto`:
+`perfetto`:
A command line utility client that drive the trace and save back
the results (either to a file or to [Android's Dropbox][dropbox])
@@ -29,10 +29,10 @@
`CONFIG` variable (e.g., [this](https://android.googlesource.com/platform/external/perfetto/+/master/test/configs/ftrace.cfg)) into a protobuf and setup the right paths.
Furthermore it will automatically rebuild if necessary.
-When doing a Linux cross-build it is possible to specify a target to run the
-daemons on via SSH:
+It is possible to push binaries to, and run on, a remote target over ssh (even
+when cross-compiling):
```bash
-CONFIG=ftrace.cfg OUT=out/default TARGET=user@my-device-host ./tools/tmux
+CONFIG=ftrace.cfg OUT=out/default SSH_TARGET=user@my-device-host ./tools/tmux
```
Running from an Android P+ in-tree build
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index 6e2afb4..a8aecc1 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -43,6 +43,15 @@
perfetto_force_dlog_on = perfetto_force_dlog == "on"
perfetto_force_dlog_off = perfetto_force_dlog == "off"
+ # We can't just use (is_linux || is_android) in perfetto.gni because that
+ # doesn't work in Android Mac host builds. We lose the GN notion of OS once
+ # we run the tools/gen_xxx generators.
+ if (enable_perfetto_watchdog) {
+ perfetto_watchdog = "PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() || " +
+ "PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX()"
+ } else {
+ perfetto_watchdog = "0"
+ }
response_file_contents = [
"--flags", # Keep this marker first.
"PERFETTO_ANDROID_BUILD=$perfetto_build_with_android",
@@ -50,7 +59,7 @@
"PERFETTO_STANDALONE_BUILD=$perfetto_build_standalone",
"PERFETTO_START_DAEMONS=$start_daemons_for_testing",
"PERFETTO_IPC=$enable_perfetto_ipc",
- "PERFETTO_WATCHDOG=$enable_perfetto_watchdog",
+ "PERFETTO_WATCHDOG=$perfetto_watchdog",
"PERFETTO_COMPONENT_BUILD=$perfetto_component_build",
"PERFETTO_FORCE_DLOG_ON=$perfetto_force_dlog_on",
"PERFETTO_FORCE_DLOG_OFF=$perfetto_force_dlog_off",
@@ -164,26 +173,39 @@
}
}
-# protoc compiler library, for building protoc plugins on the host.
-if (current_toolchain == host_toolchain) {
- group("protoc_lib") {
+# Full protobuf is just for host tools .No binary shipped on device should
+# depend on this.
+whitelisted_protobuf_full_deps = [
+ "../tools/*",
+ "../src/ipc/protoc_plugin:*",
+ "../src/protozero/protoc_plugin:*",
+ "../src/trace_processor:trace_processor_shell",
+]
+
+group("protoc") {
+ public_deps = [
+ "${perfetto_protobuf_target_prefix}:protoc($host_toolchain)",
+ ]
+}
+
+# protoc compiler library, it's used for building protoc plugins and by
+# trace_processor_shell to dynamically load .proto files for metrics.
+group("protoc_lib") {
+ visibility = whitelisted_protobuf_full_deps
+ if (current_toolchain == host_toolchain) {
public_deps = [
"${perfetto_protobuf_target_prefix}:protoc_lib",
]
}
-
- group("protoc") {
- public_deps = [
- "${perfetto_protobuf_target_prefix}:protoc",
- ]
- }
}
group("protobuf_full") {
- testonly = true
- public_deps = [
- "${perfetto_protobuf_target_prefix}:protobuf_full",
- ]
+ visibility = whitelisted_protobuf_full_deps
+ if (current_toolchain == host_toolchain) {
+ public_deps = [
+ "${perfetto_protobuf_target_prefix}:protobuf_full",
+ ]
+ }
}
group("protobuf_lite") {
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index 0653d07..4bf6252 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -154,13 +154,15 @@
is_perfetto_build_generator
# Enables base::Watchdog. Is supported only on Linux-based platforms.
+ # gn/BUILD.gn further restricts this to OS_LINUX || OS_ANDROID when generating
+ # the perfetto_build_flags.h header.
enable_perfetto_watchdog =
- perfetto_build_with_android ||
- (perfetto_build_standalone && (is_linux || is_android) && !is_wasm)
+ perfetto_build_with_android || perfetto_build_standalone
# Misc host executable under tools/.
enable_perfetto_tools =
- perfetto_build_standalone || perfetto_build_with_android
+ (perfetto_build_standalone && current_toolchain == host_toolchain) ||
+ perfetto_build_with_android
# Allows to build the UI (TypeScript/ HTML / WASM)
enable_perfetto_ui = perfetto_build_standalone
diff --git a/gn/perfetto_benchmarks.gni b/gn/perfetto_benchmarks.gni
index 83f780f..8b6d87e 100644
--- a/gn/perfetto_benchmarks.gni
+++ b/gn/perfetto_benchmarks.gni
@@ -17,6 +17,7 @@
perfetto_benchmarks_targets = [
"gn:default_deps",
"src/traced/probes/ftrace:benchmarks",
+ "src/tracing:benchmarks",
"test:benchmark_main",
"test:end_to_end_benchmarks",
]
diff --git a/gn/perfetto_host_executable.gni b/gn/perfetto_host_executable.gni
index 15e9d4a..2f00737 100644
--- a/gn/perfetto_host_executable.gni
+++ b/gn/perfetto_host_executable.gni
@@ -35,22 +35,32 @@
}
} else {
not_needed(invoker, "*", [ "testonly" ])
- copy(target_name) {
- if (defined(invoker.testonly)) {
- testonly = invoker.testonly
+ _host_target = ":$target_name($host_toolchain)"
+ _testonly = defined(invoker.testonly) && invoker.testonly
+ if (perfetto_build_with_embedder) {
+ # Don't copy anythin in Chromium, just add a dependency to the host
+ # target. V8 and other GN embedder builds. This causes problems on
+ # some bot (see crbug.com/1002599).
+ group(target_name) {
+ testonly = _testonly
+ deps = [
+ _host_target,
+ ]
}
- host_target = ":$target_name($host_toolchain)"
- deps = [
- host_target,
- ]
-
- host_out_dir = get_label_info(host_target, "root_out_dir")
- sources = [
- "$host_out_dir/$target_name",
- ]
- outputs = [
- "$root_out_dir/$target_name",
- ]
+ } else {
+ copy(target_name) {
+ testonly = _testonly
+ deps = [
+ _host_target,
+ ]
+ _host_out_dir = get_label_info(_host_target, "root_out_dir")
+ sources = [
+ "$_host_out_dir/$target_name",
+ ]
+ outputs = [
+ "$root_out_dir/$target_name",
+ ]
+ }
}
}
} # if (is_perfetto_build_generator)
diff --git a/gn/standalone/BUILD.gn b/gn/standalone/BUILD.gn
index f586a24..5d211de 100644
--- a/gn/standalone/BUILD.gn
+++ b/gn/standalone/BUILD.gn
@@ -76,9 +76,12 @@
"-fPIC",
"-g",
"-Wformat",
- "-Werror",
]
+ if (!is_fuzzer) {
+ cflags += [ "-Werror" ]
+ }
+
if (is_clang) {
cflags += [
# Color compiler output, see https://github.com/ninja-build/ninja/wiki/FAQ
@@ -105,7 +108,10 @@
"-msse2",
"-mfpmath=sse",
]
- ldflags += [ "-m32" ]
+ ldflags += [
+ "-m32",
+ "-lgcc",
+ ]
} else if (current_cpu == "arm64") {
cflags += [ "-fno-omit-frame-pointer" ]
}
diff --git a/gn/write_buildflag_header.py b/gn/write_buildflag_header.py
index 449d264..00c8c14 100644
--- a/gn/write_buildflag_header.py
+++ b/gn/write_buildflag_header.py
@@ -54,9 +54,11 @@
lines.append('#ifndef %s' % guard)
lines.append('#define %s' % guard)
lines.append('')
+ lines.append('// clang-format off')
for kv in flags:
lines.append('#define PERFETTO_BUILDFLAG_DEFINE_%s() (%s)' % kv)
lines.append('')
+ lines.append('// clang-format on')
lines.append('#endif // %s' % guard)
lines.append('')
diff --git a/include/perfetto/base/build_config.h b/include/perfetto/base/build_config.h
index 0ed2cb2..bb641f5 100644
--- a/include/perfetto/base/build_config.h
+++ b/include/perfetto/base/build_config.h
@@ -17,18 +17,6 @@
#ifndef INCLUDE_PERFETTO_BASE_BUILD_CONFIG_H_
#define INCLUDE_PERFETTO_BASE_BUILD_CONFIG_H_
-// perfetto_build_flags.h contains the tweakable build flags defined via GN.
-// - In GN builds (e.g., standalone, chromium, v8) this file is generated at
-// build time via the gen_rule //gn/gen_buildflags.
-// - In Android in-tree builds, this file is generated by tools/gen_android_bp
-// and checked in into include/perfetto/base/build_configs/android_tree/. The
-// default cflags add this path to the default include path.
-// - Similarly, in bazel builds, this file is generated by tools/gen_bazel and
-// checked in into include/perfetto/base/build_configs/bazel/.
-// - In amaglamated builds, this file is generated by tools/gen_amalgamated and
-// added to the amalgamated headers.
-#include "perfetto_build_flags.h" // no-include-violation-check
-
// Allows to define build flags that give a compiler error if the header that
// defined the flag is not included, instead of silently ignoring the #if block.
#define PERFETTO_BUILDFLAG_CAT_INDIRECT(a, b) a##b
@@ -106,4 +94,16 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_USERDEBUG_BUILD() 0
#endif
+// perfetto_build_flags.h contains the tweakable build flags defined via GN.
+// - In GN builds (e.g., standalone, chromium, v8) this file is generated at
+// build time via the gen_rule //gn/gen_buildflags.
+// - In Android in-tree builds, this file is generated by tools/gen_android_bp
+// and checked in into include/perfetto/base/build_configs/android_tree/. The
+// default cflags add this path to the default include path.
+// - Similarly, in bazel builds, this file is generated by tools/gen_bazel and
+// checked in into include/perfetto/base/build_configs/bazel/.
+// - In amaglamated builds, this file is generated by tools/gen_amalgamated and
+// added to the amalgamated headers.
+#include "perfetto_build_flags.h" // no-include-violation-check
+
#endif // INCLUDE_PERFETTO_BASE_BUILD_CONFIG_H_
diff --git a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
index bef52ba..f0594ab 100644
--- a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
@@ -4,12 +4,13 @@
#ifndef GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
#define GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
+// clang-format off
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_BUILD() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_CHROMIUM_BUILD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_STANDALONE_BUILD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_START_DAEMONS() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_IPC() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_WATCHDOG() (1)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_WATCHDOG() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() || PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX())
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPONENT_BUILD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_ON() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_OFF() (0)
@@ -18,4 +19,5 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_PERCENTILE() (0)
+// clang-format on
#endif // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
diff --git a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
index d32a21c..92250a0 100644
--- a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
@@ -4,12 +4,13 @@
#ifndef GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
#define GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
+// clang-format off
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_BUILD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_CHROMIUM_BUILD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_STANDALONE_BUILD() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_START_DAEMONS() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_IPC() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_WATCHDOG() (1)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_WATCHDOG() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() || PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX())
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPONENT_BUILD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_ON() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_OFF() (0)
@@ -18,4 +19,5 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_PERCENTILE() (1)
+// clang-format on
#endif // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
diff --git a/include/perfetto/ext/base/string_utils.h b/include/perfetto/ext/base/string_utils.h
index 3220a69..977673f 100644
--- a/include/perfetto/ext/base/string_utils.h
+++ b/include/perfetto/ext/base/string_utils.h
@@ -23,6 +23,14 @@
namespace perfetto {
namespace base {
+inline char Lowercase(char c) {
+ return ('A' <= c && c <= 'Z') ? (c -= 'A' - 'a') : c;
+}
+
+inline char Uppercase(char c) {
+ return ('a' <= c && c <= 'z') ? (c += 'A' - 'a') : c;
+}
+
bool StartsWith(const std::string& str, const std::string& prefix);
bool EndsWith(const std::string& str, const std::string& suffix);
bool Contains(const std::string& haystack, const std::string& needle);
@@ -31,6 +39,16 @@
const std::string& delim);
std::vector<std::string> SplitString(const std::string& text,
const std::string& delimiter);
+std::string StripPrefix(const std::string& str, const std::string& prefix);
+std::string StripSuffix(const std::string& str, const std::string& suffix);
+std::string ToUpper(const std::string& str);
+std::string StripChars(const std::string& str,
+ const std::string& chars,
+ char replacement);
+std::string ToHex(const char* data, size_t size);
+inline std::string ToHex(const std::string& s) {
+ return ToHex(s.c_str(), s.size());
+}
} // namespace base
} // namespace perfetto
diff --git a/include/perfetto/ext/ipc/BUILD.gn b/include/perfetto/ext/ipc/BUILD.gn
index a8aa17e..53a39ee 100644
--- a/include/perfetto/ext/ipc/BUILD.gn
+++ b/include/perfetto/ext/ipc/BUILD.gn
@@ -14,6 +14,7 @@
source_set("ipc") {
public_deps = [
+ "../../../../gn:protobuf_lite",
"../base",
]
sources = [
diff --git a/include/perfetto/ext/ipc/async_result.h b/include/perfetto/ext/ipc/async_result.h
index cb4d849..5cb6140 100644
--- a/include/perfetto/ext/ipc/async_result.h
+++ b/include/perfetto/ext/ipc/async_result.h
@@ -28,8 +28,8 @@
// Wraps the result of an asynchronous invocation. This is the equivalent of a
// std::pair<unique_ptr<T>, bool> with syntactic sugar. It is used as callback
-// argument by Deferred<T>.
-template <typename T = ProtoMessage>
+// argument by Deferred<T>. T is a ProtoMessage subclass (i.e. generated .pb.h).
+template <typename T>
class AsyncResult {
public:
static AsyncResult Create() {
diff --git a/include/perfetto/ext/ipc/basic_types.h b/include/perfetto/ext/ipc/basic_types.h
index 793cc19..f9e330c 100644
--- a/include/perfetto/ext/ipc/basic_types.h
+++ b/include/perfetto/ext/ipc/basic_types.h
@@ -21,11 +21,7 @@
#include <stdint.h>
#include <sys/types.h>
-namespace google {
-namespace protobuf {
-class MessageLite;
-} // namespace protobuf
-} // namespace google
+#include <google/protobuf/message_lite.h>
namespace perfetto {
namespace ipc {
diff --git a/include/perfetto/ext/ipc/codegen_helpers.h b/include/perfetto/ext/ipc/codegen_helpers.h
index 90ca49d..c0235a2 100644
--- a/include/perfetto/ext/ipc/codegen_helpers.h
+++ b/include/perfetto/ext/ipc/codegen_helpers.h
@@ -19,6 +19,12 @@
#ifndef INCLUDE_PERFETTO_EXT_IPC_CODEGEN_HELPERS_H_
#define INCLUDE_PERFETTO_EXT_IPC_CODEGEN_HELPERS_H_
+#include <memory>
+
+#include "perfetto/ext/ipc/basic_types.h"
+#include "perfetto/ext/ipc/deferred.h"
+#include "perfetto/ext/ipc/service.h"
+
// A templated protobuf message decoder. Returns nullptr in case of failure.
template <typename T>
::std::unique_ptr<::perfetto::ipc::ProtoMessage> _IPC_Decoder(
diff --git a/include/perfetto/ext/ipc/deferred.h b/include/perfetto/ext/ipc/deferred.h
index 8b58920..aa4cbbd 100644
--- a/include/perfetto/ext/ipc/deferred.h
+++ b/include/perfetto/ext/ipc/deferred.h
@@ -90,7 +90,7 @@
std::function<void(AsyncResult<ProtoMessage>)> callback_;
};
-template <typename T = ProtoMessage>
+template <typename T> // T : ProtoMessage subclass
class Deferred : public DeferredBase {
public:
explicit Deferred(std::function<void(AsyncResult<T>)> callback = nullptr) {
diff --git a/include/perfetto/ext/traced/data_source_types.h b/include/perfetto/ext/traced/data_source_types.h
index b7732ca..103fd41 100644
--- a/include/perfetto/ext/traced/data_source_types.h
+++ b/include/perfetto/ext/traced/data_source_types.h
@@ -23,8 +23,6 @@
#include <set>
#include <string>
-#include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"
-
namespace perfetto {
// On ARM, st_ino is not ino_t but unsigned long long.
@@ -33,19 +31,19 @@
// On ARM, st_dev is not dev_t but unsigned long long.
using BlockDeviceID = decltype(stat::st_dev);
+// From inode_file_map.pbzero.h
+using InodeFileMap_Entry_Type = int32_t;
+
class InodeMapValue {
public:
- InodeMapValue(protos::pbzero::InodeFileMap_Entry_Type entry_type,
- std::set<std::string> paths)
+ InodeMapValue(InodeFileMap_Entry_Type entry_type, std::set<std::string> paths)
: entry_type_(entry_type), paths_(std::move(paths)) {}
InodeMapValue() {}
- protos::pbzero::InodeFileMap_Entry_Type type() const { return entry_type_; }
+ InodeFileMap_Entry_Type type() const { return entry_type_; }
const std::set<std::string>& paths() const { return paths_; }
- void SetType(protos::pbzero::InodeFileMap_Entry_Type entry_type) {
- entry_type_ = entry_type;
- }
+ void SetType(InodeFileMap_Entry_Type entry_type) { entry_type_ = entry_type; }
void SetPaths(std::set<std::string> paths) { paths_ = std::move(paths); }
void AddPath(std::string path) { paths_.emplace(std::move(path)); }
@@ -54,7 +52,7 @@
}
private:
- protos::pbzero::InodeFileMap_Entry_Type entry_type_;
+ InodeFileMap_Entry_Type entry_type_;
std::set<std::string> paths_;
};
diff --git a/include/perfetto/ext/tracing/core/BUILD.gn b/include/perfetto/ext/tracing/core/BUILD.gn
index 5dc8c88..b263ec0 100644
--- a/include/perfetto/ext/tracing/core/BUILD.gn
+++ b/include/perfetto/ext/tracing/core/BUILD.gn
@@ -28,6 +28,7 @@
"shared_memory_abi.h",
"shared_memory_arbiter.h",
"slice.h",
+ "sliced_protobuf_input_stream.h",
"startup_trace_writer.h",
"startup_trace_writer_registry.h",
"trace_packet.h",
diff --git a/include/perfetto/ext/tracing/core/sliced_protobuf_input_stream.h b/include/perfetto/ext/tracing/core/sliced_protobuf_input_stream.h
new file mode 100644
index 0000000..1a1029c
--- /dev/null
+++ b/include/perfetto/ext/tracing/core/sliced_protobuf_input_stream.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_SLICED_PROTOBUF_INPUT_STREAM_H_
+#define INCLUDE_PERFETTO_EXT_TRACING_CORE_SLICED_PROTOBUF_INPUT_STREAM_H_
+
+#include "perfetto/ext/tracing/core/slice.h"
+
+#include <stdint.h>
+#include <utility>
+
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include "perfetto/base/export.h"
+
+namespace perfetto {
+
+using ZeroCopyInputStream = google::protobuf::io::ZeroCopyInputStream;
+
+// Wraps a sequence of Slice(s) in a protobuf ZeroCopyInputStream that can be
+// passed to protobuf::Message::ParseFromZeroCopyStream().
+class PERFETTO_EXPORT SlicedProtobufInputStream : public ZeroCopyInputStream {
+ public:
+ // This indirection deals with the fact that the public protobuf library and
+ // the internal one diverged on this type. The internal doesn's use a custom
+ // defined type. The public one uses a typedef that isn't compatible with
+ // stdint's int64_t (long long vs long). So insted of trying to use
+ // google::protobuf::int64, infer the type from the return value of the
+ // ByteCount().
+ using int64 = decltype(std::declval<ZeroCopyInputStream>().ByteCount());
+
+ explicit SlicedProtobufInputStream(const Slices*);
+ ~SlicedProtobufInputStream() override;
+
+ // ZeroCopyInputStream implementation. See zero_copy_stream.h for the API
+ // contract of the methods below.
+ bool Next(const void** data, int* size) override;
+ void BackUp(int count) override;
+ bool Skip(int count) override;
+ int64 ByteCount() const override;
+
+ private:
+ bool Validate() const;
+
+ const Slices* const slices_;
+ Slices::const_iterator cur_slice_;
+ size_t pos_in_cur_slice_ = 0;
+};
+
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACING_CORE_SLICED_PROTOBUF_INPUT_STREAM_H_
diff --git a/include/perfetto/ext/tracing/core/trace_packet.h b/include/perfetto/ext/tracing/core/trace_packet.h
index 80f1018..d695165 100644
--- a/include/perfetto/ext/tracing/core/trace_packet.h
+++ b/include/perfetto/ext/tracing/core/trace_packet.h
@@ -21,7 +21,6 @@
#include <memory>
#include <tuple>
-#include <google/protobuf/io/zero_copy_stream.h>
#include "perfetto/base/export.h"
#include "perfetto/base/logging.h"
#include "perfetto/ext/tracing/core/slice.h"
@@ -43,7 +42,6 @@
class PERFETTO_EXPORT TracePacket {
public:
using const_iterator = Slices::const_iterator;
- using ZeroCopyInputStream = ::google::protobuf::io::ZeroCopyInputStream;
// The field id of protos::Trace::packet, static_assert()-ed in the unittest.
static constexpr uint32_t kPacketFieldNumber = 1;
@@ -56,20 +54,6 @@
// Accesses all the raw slices in the packet, for saving them to file/network.
const Slices& slices() const { return slices_; }
- // Decodes the packet. This function requires that the caller:
- // 1) Does #include "protos/perfetto/trace/trace_packet.pb.h"
- // 2) Links against the //protos/trace:lite target.
- // The core service code deliberately doesn't link against that in order to
- // avoid binary bloat. This is the reason why this is a templated function.
- // It doesn't need to be (i.e. the caller should not specify the template
- // argument) but doing so prevents the compiler trying to resolve the
- // TracePacket type until it's needed, in which case the caller needs (1).
- template <typename TracePacketType = protos::TracePacket>
- bool Decode(TracePacketType* packet) const {
- std::unique_ptr<ZeroCopyInputStream> istr = CreateSlicedInputStream();
- return packet->ParseFromZeroCopyStream(istr.get());
- }
-
// Mutator, used only by the service and tests.
void AddSlice(Slice);
@@ -86,12 +70,14 @@
// and its size.
std::tuple<char*, size_t> GetProtoPreamble();
+ // Returns the raw protobuf bytes of the slices, all stitched together into
+ // a string. Only for testing.
+ std::string GetRawBytesForTesting();
+
private:
TracePacket(const TracePacket&) = delete;
TracePacket& operator=(const TracePacket&) = delete;
- std::unique_ptr<ZeroCopyInputStream> CreateSlicedInputStream() const;
-
Slices slices_; // Not owned.
size_t size_ = 0; // SUM(slice.size for slice in slices_).
char preamble_[8]; // Deliberately not initialized.
diff --git a/infra/ci/config.py b/infra/ci/config.py
index 795ace7..8b5e6fb 100755
--- a/infra/ci/config.py
+++ b/infra/ci/config.py
@@ -79,6 +79,11 @@
'PERFETTO_TEST_GN_ARGS': 'is_debug=false is_asan=true is_lsan=true',
'PERFETTO_TEST_SCRIPT': 'test/ci/linux_tests.sh',
},
+ 'linux-clang-x86-asan_lsan': {
+ 'PERFETTO_TEST_GN_ARGS': 'is_debug=false is_asan=true is_lsan=true '
+ 'target_cpu="x86"',
+ 'PERFETTO_TEST_SCRIPT': 'test/ci/linux_tests.sh',
+ },
'linux-gcc7-x86_64-release': {
'PERFETTO_TEST_GN_ARGS': 'is_debug=false is_clang=false ' +
'use_custom_libcxx=false ' +
diff --git a/infra/ci/frontend/Makefile b/infra/ci/frontend/Makefile
index 940f13d..14431aa 100644
--- a/infra/ci/frontend/Makefile
+++ b/infra/ci/frontend/Makefile
@@ -37,23 +37,23 @@
../config.py js > $@
static/third_party/xterm-3.14.4.min.css:
- curl -so $@ https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/xterm.min.css
+ curl -Sso $@ https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/xterm.min.css
echo "ad80f73df001c943cfcd98d706dba050704f715d $@" | ${SHASUM} -c || rm $@
static/third_party/xterm-3.14.4.min.js:
- curl -so $@ https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/xterm.min.js
+ curl -Sso $@ https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/xterm.min.js
echo "9a92b3fbb118fd2a672f7eb4e69598384ca91756 $@" | ${SHASUM} -c || rm $@
static/third_party/xterm-3.14.4-addon-search.min.js:
- curl -so $@ https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/addons/search/search.min.js
+ curl -Sso $@ https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/addons/search/search.min.js
echo "73f55082d00c98b372cac1264ba9da70cdf603d0 $@" | ${SHASUM} -c || rm $@
static/third_party/xterm-3.14.4-addon-fit.min.js:
- curl -so $@ https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/addons/fit/fit.min.js
+ curl -Sso $@ https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/addons/fit/fit.min.js
echo "64835b1b71e8ca2d5bbb1a8e3c7f8a8f1edb2e5c $@" | ${SHASUM} -c || rm $@
static/third_party/mithril-1.1.6.min.js:
- curl -so $@ https://cdnjs.cloudflare.com/ajax/libs/mithril/1.1.6/mithril.min.js
+ curl -Sso $@ https://cdnjs.cloudflare.com/ajax/libs/mithril/1.1.6/mithril.min.js
echo "a204c02ee15c347cf368c3481bdea967b443c8d0 $@" | ${SHASUM} -c || rm $@
static_3p: static/third_party/xterm-3.14.4.min.css static/third_party/xterm-3.14.4.min.js static/third_party/xterm-3.14.4-addon-search.min.js static/third_party/xterm-3.14.4-addon-fit.min.js static/third_party/mithril-1.1.6.min.js
diff --git a/infra/ci/frontend/static/script.js b/infra/ci/frontend/static/script.js
index 6a05246..2be6168 100644
--- a/infra/ci/frontend/static/script.js
+++ b/infra/ci/frontend/static/script.js
@@ -16,12 +16,14 @@
'use strict';
+// If you add or remove job types, do not forget to fix the colspans below.
const JOB_TYPES = [
{ id: 'linux-gcc7-x86_64-release', label: 'rel' },
{ id: 'linux-clang-x86_64-debug', label: 'dbg' },
{ id: 'linux-clang-x86_64-tsan', label: 'tsan' },
{ id: 'linux-clang-x86_64-msan', label: 'msan' },
{ id: 'linux-clang-x86_64-asan_lsan', label: '{a,l}san' },
+ { id: 'linux-clang-x86-asan_lsan', label: 'x86 {a,l}san' },
{ id: 'linux-clang-x86_64-libfuzzer', label: 'fuzzer' },
{ id: 'ui-clang-x86_64-debug', label: 'dbg' },
{ id: 'ui-clang-x86_64-release', label: 'rel' },
@@ -194,15 +196,15 @@
m('td[rowspan=4]', 'Status'),
m('td[rowspan=4]', 'Owner'),
m('td[rowspan=4]', 'Updated'),
- m('td[colspan=10]', 'Bots'),
+ m('td[colspan=11]', 'Bots'),
),
m('tr',
- m('td[colspan=8]', 'linux'),
+ m('td[colspan=9]', 'linux'),
m('td[colspan=2]', 'android'),
),
m('tr',
m('td', 'gcc7'),
- m('td[colspan=5]', 'clang'),
+ m('td[colspan=6]', 'clang'),
m('td[colspan=2]', 'ui'),
m('td[colspan=2]', 'clang-arm'),
),
@@ -814,4 +816,4 @@
});
}
-main();
\ No newline at end of file
+main();
diff --git a/infra/ci/frontend/static/third_party/README.md b/infra/ci/frontend/static/third_party/README.md
new file mode 100644
index 0000000..cecb7e7
--- /dev/null
+++ b/infra/ci/frontend/static/third_party/README.md
@@ -0,0 +1 @@
+This file is needed to keep this directory in git.
diff --git a/infra/ci/sandbox/Dockerfile b/infra/ci/sandbox/Dockerfile
index c53169a..ad6782d 100644
--- a/infra/ci/sandbox/Dockerfile
+++ b/infra/ci/sandbox/Dockerfile
@@ -24,7 +24,7 @@
/etc/apt/sources.list.d/testing.list; \
apt-get update; \
apt-get -y install python git curl sudo lz4 tar ccache tini libpulse0 \
- libgl1 libxml2; \
+ libgl1 libxml2 libc6-dev-i386 libtinfo5; \
apt-get -y -t testing install gcc-7 g++-7 clang; \
curl https://bootstrap.pypa.io/get-pip.py | python -; \
pip install --quiet protobuf; \
diff --git a/protos/BUILD b/protos/BUILD
index 107f145..25b1514 100644
--- a/protos/BUILD
+++ b/protos/BUILD
@@ -883,6 +883,65 @@
],
)
+# GN target: //protos/perfetto/trace/appended_data:lite_gen
+proto_library(
+ name = "trace_appended_data",
+ srcs = [
+ "perfetto/trace/appended_data/appended_data.proto",
+ ],
+ has_services = 1,
+ cc_api_version = 2,
+ cc_generic_services = 1,
+ visibility = [
+ "//visibility:public",
+ ],
+ deps = [
+ "//third_party/perfetto/protos:trace_profiling",
+ ],
+)
+
+# GN target: //protos/perfetto/trace/appended_data:lite_gen
+cc_proto_library(
+ name = "trace_appended_data_cc_proto",
+ visibility = [
+ "//visibility:public",
+ ],
+ deps = [
+ "//third_party/perfetto/protos:trace_appended_data",
+ ],
+)
+
+# GN target: //protos/perfetto/trace/appended_data:lite_gen
+java_proto_library(
+ name = "trace_appended_data_java_proto",
+ visibility = [
+ "//visibility:public",
+ ],
+ deps = [
+ "//third_party/perfetto/protos:trace_appended_data",
+ ],
+)
+
+# GN target: //protos/perfetto/trace/appended_data:zero_gen
+proto_library(
+ name = "trace_appended_data_zero",
+ srcs = [
+ "perfetto/trace/appended_data/appended_data.proto",
+ ],
+ deps = [
+ "//third_party/perfetto/protos:trace_profiling_zero",
+ ],
+)
+
+# GN target: //protos/perfetto/trace/appended_data:zero_gen
+pbzero_cc_proto_library(
+ name = "trace_appended_data_zero_cc_proto",
+ src_proto_library = "//third_party/perfetto/protos:trace_appended_data_zero",
+ deps = [
+ "//third_party/perfetto:libprotozero",
+ ],
+)
+
# GN target: //protos/perfetto/trace/chrome:lite_gen
proto_library(
name = "trace_chrome",
@@ -1011,7 +1070,6 @@
"perfetto/trace/ftrace/ftrace_event_bundle.proto",
"perfetto/trace/ftrace/ftrace_stats.proto",
"perfetto/trace/ftrace/generic.proto",
- "perfetto/trace/ftrace/gpu.proto",
"perfetto/trace/ftrace/i2c.proto",
"perfetto/trace/ftrace/ipi.proto",
"perfetto/trace/ftrace/irq.proto",
@@ -1080,7 +1138,6 @@
"perfetto/trace/ftrace/ftrace_event_bundle.proto",
"perfetto/trace/ftrace/ftrace_stats.proto",
"perfetto/trace/ftrace/generic.proto",
- "perfetto/trace/ftrace/gpu.proto",
"perfetto/trace/ftrace/i2c.proto",
"perfetto/trace/ftrace/ipi.proto",
"perfetto/trace/ftrace/irq.proto",
@@ -1378,6 +1435,7 @@
"//third_party/perfetto/protos:config_profiling",
"//third_party/perfetto/protos:config_sys_stats",
"//third_party/perfetto/protos:trace_android",
+ "//third_party/perfetto/protos:trace_appended_data",
"//third_party/perfetto/protos:trace_chrome",
"//third_party/perfetto/protos:trace_filesystem",
"//third_party/perfetto/protos:trace_ftrace",
@@ -1436,6 +1494,7 @@
"//third_party/perfetto/protos:config_sys_stats_zero",
"//third_party/perfetto/protos:config_zero",
"//third_party/perfetto/protos:trace_android_zero",
+ "//third_party/perfetto/protos:trace_appended_data_zero",
"//third_party/perfetto/protos:trace_chrome_zero",
"//third_party/perfetto/protos:trace_filesystem_zero",
"//third_party/perfetto/protos:trace_ftrace_zero",
@@ -1573,7 +1632,6 @@
name = "trace_processor",
srcs = [
"perfetto/trace_processor/raw_query.proto",
- "perfetto/trace_processor/sched.proto",
"perfetto/trace_processor/trace_processor.proto",
],
has_services = 1,
diff --git a/protos/perfetto/common/gpu_counter_descriptor.proto b/protos/perfetto/common/gpu_counter_descriptor.proto
index 03de9db..e15a6f3 100644
--- a/protos/perfetto/common/gpu_counter_descriptor.proto
+++ b/protos/perfetto/common/gpu_counter_descriptor.proto
@@ -26,13 +26,14 @@
optional uint32 counter_id = 1;
optional string name = 2;
optional string description = 3;
- reserved 4;
+ reserved 4; // MeasureUnit unit (deprecated)
oneof peak_value {
int64 int_peak_value = 5;
double double_peak_value = 6;
};
repeated MeasureUnit numerator_units = 7;
repeated MeasureUnit denominator_units = 8;
+ optional bool select_by_default = 9;
}
repeated GpuCounterSpec specs = 1;
@@ -52,6 +53,15 @@
}
repeated GpuCounterBlock blocks = 2;
+ // optional. Minimum sampling period supported by the producer in nanoseconds.
+ optional uint64 min_sampling_period_ns = 3;
+
+ // optional. Maximum sampling period supported by the producer in nanoseconds.
+ optional uint64 max_sampling_period_ns = 4;
+
+ // optional. The producer supports counter sampling by instrumenting the command buffer.
+ optional bool supports_instrumented_sampling = 5;
+
enum MeasureUnit {
NONE = 0;
diff --git a/protos/perfetto/config/gpu/gpu_counter_config.proto b/protos/perfetto/config/gpu/gpu_counter_config.proto
index 8f499b4..6e448af 100644
--- a/protos/perfetto/config/gpu/gpu_counter_config.proto
+++ b/protos/perfetto/config/gpu/gpu_counter_config.proto
@@ -29,4 +29,10 @@
// List of counters to be sampled. Counter IDs correspond to the ones
// described in GpuCounterSpec in the data source descriptor.
repeated uint32 counter_ids = 2;
+
+ // Sample counters by instrumenting command buffers.
+ optional bool instrumented_sampling = 3;
+
+ // Fix gpu clock rate during trace session.
+ optional bool fix_gpu_clock = 4;
}
diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto
index 3a5f155..259a8b0 100644
--- a/protos/perfetto/config/perfetto_config.proto
+++ b/protos/perfetto/config/perfetto_config.proto
@@ -81,13 +81,14 @@
optional uint32 counter_id = 1;
optional string name = 2;
optional string description = 3;
- reserved 4;
+ reserved 4; // MeasureUnit unit (deprecated)
oneof peak_value {
int64 int_peak_value = 5;
double double_peak_value = 6;
};
repeated MeasureUnit numerator_units = 7;
repeated MeasureUnit denominator_units = 8;
+ optional bool select_by_default = 9;
}
repeated GpuCounterSpec specs = 1;
@@ -107,6 +108,15 @@
}
repeated GpuCounterBlock blocks = 2;
+ // optional. Minimum sampling period supported by the producer in nanoseconds.
+ optional uint64 min_sampling_period_ns = 3;
+
+ // optional. Maximum sampling period supported by the producer in nanoseconds.
+ optional uint64 max_sampling_period_ns = 4;
+
+ // optional. The producer supports counter sampling by instrumenting the command buffer.
+ optional bool supports_instrumented_sampling = 5;
+
enum MeasureUnit {
NONE = 0;
@@ -1256,6 +1266,12 @@
// List of counters to be sampled. Counter IDs correspond to the ones
// described in GpuCounterSpec in the data source descriptor.
repeated uint32 counter_ids = 2;
+
+ // Sample counters by instrumenting command buffers.
+ optional bool instrumented_sampling = 3;
+
+ // Fix gpu clock rate during trace session.
+ optional bool fix_gpu_clock = 4;
}
// End of protos/perfetto/config/gpu/gpu_counter_config.proto
diff --git a/protos/perfetto/ipc/BUILD.gn b/protos/perfetto/ipc/BUILD.gn
index a3e0bfd..48f54a1 100644
--- a/protos/perfetto/ipc/BUILD.gn
+++ b/protos/perfetto/ipc/BUILD.gn
@@ -14,6 +14,7 @@
import("../../../gn/ipc_library.gni")
import("../../../gn/perfetto.gni")
+import("../../../gn/proto_library.gni")
# IPC service definitions.
ipc_library("ipc") {
@@ -28,3 +29,10 @@
"producer_port.proto",
]
}
+
+perfetto_proto_library("wire_protocol") {
+ proto_generators = [ "lite" ]
+ sources = [
+ "wire_protocol.proto",
+ ]
+}
diff --git a/src/ipc/wire_protocol.proto b/protos/perfetto/ipc/wire_protocol.proto
similarity index 100%
rename from src/ipc/wire_protocol.proto
rename to protos/perfetto/ipc/wire_protocol.proto
diff --git a/protos/perfetto/metrics/android/cpu_metric.proto b/protos/perfetto/metrics/android/cpu_metric.proto
index 2be68a9..172a6d8 100644
--- a/protos/perfetto/metrics/android/cpu_metric.proto
+++ b/protos/perfetto/metrics/android/cpu_metric.proto
@@ -36,12 +36,15 @@
message Thread {
optional string name = 1;
repeated CpuFrequencyData cpu = 2;
+ // CPU cycles normalized at 1Ghz frequency.
+ optional int64 normalized_cpu_cycles = 3;
}
// Threads (name and CPU frequency) per process.
message Process {
optional string name = 1;
repeated Thread threads = 2;
+ optional int64 normalized_cpu_cycles = 3;
}
// Process name and CPU frequency data aggregated by thread and cpu.
diff --git a/protos/perfetto/trace/BUILD.gn b/protos/perfetto/trace/BUILD.gn
index 9f0e1c3..65a364a 100644
--- a/protos/perfetto/trace/BUILD.gn
+++ b/protos/perfetto/trace/BUILD.gn
@@ -70,6 +70,7 @@
":minimal_@TYPE@",
"../config:@TYPE@",
"android:@TYPE@",
+ "appended_data:@TYPE@",
"chrome:@TYPE@",
"filesystem:@TYPE@",
"ftrace:@TYPE@",
diff --git a/protos/perfetto/trace/appended_data/BUILD.gn b/protos/perfetto/trace/appended_data/BUILD.gn
new file mode 100644
index 0000000..16c3bc2
--- /dev/null
+++ b/protos/perfetto/trace/appended_data/BUILD.gn
@@ -0,0 +1,24 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("../../../../gn/proto_library.gni")
+
+perfetto_proto_library("@TYPE@") {
+ sources = [
+ "appended_data.proto",
+ ]
+ deps = [
+ "../profiling:@TYPE@",
+ ]
+}
diff --git a/protos/perfetto/trace/appended_data/appended_data.proto b/protos/perfetto/trace/appended_data/appended_data.proto
new file mode 100644
index 0000000..777129a
--- /dev/null
+++ b/protos/perfetto/trace/appended_data/appended_data.proto
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+import "protos/perfetto/trace/profiling/profile_common.proto";
+
+package perfetto.protos;
+
+// Contains data appended to the trace after the fact. Elements referring to
+// past interned data must have a matching trusted_packet_sequence_id.
+//
+// The writer will usually parse the trace, resolve and concatenate
+// AppendedData (and corresponding InternedData) to the end of the trace.
+// Any InternedData must precede or be on the same packet as the AppendedData
+// that uses them.
+//
+// Next id: 2.
+message AppendedData {
+ // Maps between interned frames and their resolved symbols.
+ repeated ProfiledFrameSymbols profiled_frame_symbols = 1;
+}
diff --git a/protos/perfetto/trace/ftrace/all_protos.gni b/protos/perfetto/trace/ftrace/all_protos.gni
index 3a9b0e7..b6278b8 100644
--- a/protos/perfetto/trace/ftrace/all_protos.gni
+++ b/protos/perfetto/trace/ftrace/all_protos.gni
@@ -30,7 +30,6 @@
"fence.proto",
"filemap.proto",
"ftrace.proto",
- "gpu.proto",
"i2c.proto",
"ipi.proto",
"irq.proto",
diff --git a/protos/perfetto/trace/ftrace/ftrace_event.proto b/protos/perfetto/trace/ftrace/ftrace_event.proto
index 53c94d4..c953f36 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event.proto
@@ -15,7 +15,6 @@
import "protos/perfetto/trace/ftrace/fence.proto";
import "protos/perfetto/trace/ftrace/filemap.proto";
import "protos/perfetto/trace/ftrace/ftrace.proto";
-import "protos/perfetto/trace/ftrace/gpu.proto";
import "protos/perfetto/trace/ftrace/i2c.proto";
import "protos/perfetto/trace/ftrace/ipi.proto";
import "protos/perfetto/trace/ftrace/irq.proto";
@@ -396,8 +395,5 @@
SysExitFtraceEvent sys_exit = 330;
ZeroFtraceEvent zero = 331;
GpuFrequencyFtraceEvent gpu_frequency = 332;
- GpuSchedEnqueueFtraceEvent gpu_sched_enqueue = 333;
- GpuSchedSubmitFtraceEvent gpu_sched_submit = 334;
- GpuSchedCompleteFtraceEvent gpu_sched_complete = 335;
}
}
diff --git a/protos/perfetto/trace/ftrace/gpu.proto b/protos/perfetto/trace/ftrace/gpu.proto
deleted file mode 100644
index 033d402..0000000
--- a/protos/perfetto/trace/ftrace/gpu.proto
+++ /dev/null
@@ -1,28 +0,0 @@
-// Autogenerated by:
-// ../../tools/ftrace_proto_gen/ftrace_proto_gen.cc
-// Do not edit.
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-package perfetto.protos;
-
-message GpuSchedEnqueueFtraceEvent {
- optional uint32 ctx_id = 1;
- optional uint32 job_id = 2;
- optional uint32 priority = 3;
- optional uint32 submission_id = 4;
-}
-message GpuSchedSubmitFtraceEvent {
- optional uint32 ctx_id = 1;
- optional uint32 hwqueue_id = 2;
- optional uint32 job_id = 3;
- optional uint32 priority = 4;
- optional uint32 submission_id = 5;
-}
-message GpuSchedCompleteFtraceEvent {
- optional uint32 ctx_id = 1;
- optional uint32 job_id = 2;
- optional string msg = 3;
- optional uint32 priority = 4;
- optional uint32 submission_id = 5;
-}
diff --git a/protos/perfetto/trace/gpu/gpu_counter_event.proto b/protos/perfetto/trace/gpu/gpu_counter_event.proto
index 53574c3..fe3a8f0 100644
--- a/protos/perfetto/trace/gpu/gpu_counter_event.proto
+++ b/protos/perfetto/trace/gpu/gpu_counter_event.proto
@@ -35,4 +35,7 @@
}
}
repeated GpuCounter counters = 2;
+
+ // optional. Identifier for GPU in a multi-gpu device.
+ optional int32 gpu_id = 3;
}
diff --git a/protos/perfetto/trace/gpu/gpu_render_stage_event.proto b/protos/perfetto/trace/gpu/gpu_render_stage_event.proto
index 589f6b7..a2a4cfd 100644
--- a/protos/perfetto/trace/gpu/gpu_render_stage_event.proto
+++ b/protos/perfetto/trace/gpu/gpu_render_stage_event.proto
@@ -24,8 +24,8 @@
// required. Unique ID for the event.
optional uint64 event_id = 1;
- // optional. Duration in GPU clock. If unset, this is a single time point
- // event.
+ // optional. Duration of the event. This should be in the same clock domain as the timestamp of
+ // the packet. If unset, this is a single time point event.
optional uint64 duration = 2;
// required. ID to a hardware queue description in the specifications.
@@ -37,10 +37,10 @@
// required. GL context/VK device.
optional uint64 context = 5;
- // optional. The surface or render target for this event.
- optional uint64 surface_id = 8;
+ // optional. The render target for this event.
+ optional uint64 render_target_handle = 8;
- // optional. Render pass handle.
+ // optional. The Vulkan render pass handle.
optional uint64 render_pass_handle = 9;
// optional. Submission ID generated by the UMD.
@@ -68,21 +68,17 @@
optional string description = 2;
}
- // Labels to categorize the hw Queue this event goes on
+ // Labels to categorize the hw Queue this event goes on.
repeated Description hw_queue = 2;
- // Labels to categorize render stage(binning, render, compute etc)
+ // Labels to categorize render stage(binning, render, compute etc).
repeated Description stage = 3;
}
optional Specifications specifications = 7;
- // optional. If True, duration must not be set and a GpuRenderStageEndEvent is expected.
- optional bool begin_event = 11;
+ // optional. Identifier for GPU in a multi-gpu device.
+ optional int32 gpu_id = 11;
// Extension for vendor's custom proto.
extensions 100;
}
-
-// Message to signal the end of the last render stage event that had set begin_event.
-message GpuRenderStageEndEvent {
-}
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 151424f..1c24dd5 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -81,13 +81,14 @@
optional uint32 counter_id = 1;
optional string name = 2;
optional string description = 3;
- reserved 4;
+ reserved 4; // MeasureUnit unit (deprecated)
oneof peak_value {
int64 int_peak_value = 5;
double double_peak_value = 6;
};
repeated MeasureUnit numerator_units = 7;
repeated MeasureUnit denominator_units = 8;
+ optional bool select_by_default = 9;
}
repeated GpuCounterSpec specs = 1;
@@ -107,6 +108,15 @@
}
repeated GpuCounterBlock blocks = 2;
+ // optional. Minimum sampling period supported by the producer in nanoseconds.
+ optional uint64 min_sampling_period_ns = 3;
+
+ // optional. Maximum sampling period supported by the producer in nanoseconds.
+ optional uint64 max_sampling_period_ns = 4;
+
+ // optional. The producer supports counter sampling by instrumenting the command buffer.
+ optional bool supports_instrumented_sampling = 5;
+
enum MeasureUnit {
NONE = 0;
@@ -615,6 +625,24 @@
// End of protos/perfetto/trace/android/packages_list.proto
+// Begin of protos/perfetto/trace/appended_data/appended_data.proto
+
+// Contains data appended to the trace after the fact. Elements referring to
+// past interned data must have a matching trusted_packet_sequence_id.
+//
+// The writer will usually parse the trace, resolve and concatenate
+// AppendedData (and corresponding InternedData) to the end of the trace.
+// Any InternedData must precede or be on the same packet as the AppendedData
+// that uses them.
+//
+// Next id: 2.
+message AppendedData {
+ // Maps between interned frames and their resolved symbols.
+ repeated ProfiledFrameSymbols profiled_frame_symbols = 1;
+}
+
+// End of protos/perfetto/trace/appended_data/appended_data.proto
+
// Begin of protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto
// This message is not intended to be written by the chrome on the device.
@@ -2277,9 +2305,6 @@
SysExitFtraceEvent sys_exit = 330;
ZeroFtraceEvent zero = 331;
GpuFrequencyFtraceEvent gpu_frequency = 332;
- GpuSchedEnqueueFtraceEvent gpu_sched_enqueue = 333;
- GpuSchedSubmitFtraceEvent gpu_sched_submit = 334;
- GpuSchedCompleteFtraceEvent gpu_sched_complete = 335;
}
}
@@ -2374,31 +2399,6 @@
// End of protos/perfetto/trace/ftrace/generic.proto
-// Begin of protos/perfetto/trace/ftrace/gpu.proto
-
-message GpuSchedEnqueueFtraceEvent {
- optional uint32 ctx_id = 1;
- optional uint32 job_id = 2;
- optional uint32 priority = 3;
- optional uint32 submission_id = 4;
-}
-message GpuSchedSubmitFtraceEvent {
- optional uint32 ctx_id = 1;
- optional uint32 hwqueue_id = 2;
- optional uint32 job_id = 3;
- optional uint32 priority = 4;
- optional uint32 submission_id = 5;
-}
-message GpuSchedCompleteFtraceEvent {
- optional uint32 ctx_id = 1;
- optional uint32 job_id = 2;
- optional string msg = 3;
- optional uint32 priority = 4;
- optional uint32 submission_id = 5;
-}
-
-// End of protos/perfetto/trace/ftrace/gpu.proto
-
// Begin of protos/perfetto/trace/ftrace/kmem.proto
message AllocPagesIommuEndFtraceEvent {
@@ -3403,7 +3403,7 @@
// TracePacket(s).
//
// Next reserved id: 13 (up to 15).
-// Next id: 61.
+// Next id: 62.
message TracePacket {
// The timestamp of the TracePacket.
// By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
@@ -3506,6 +3506,11 @@
// proactively in advance of referring to them in later packets.
optional InternedData interned_data = 12;
+ // Data appended to the trace post-processing (e.g. symbol information). When
+ // the AppendedData contents refer to interned data, they must share the same
+ // |trusted_packet_sequence_id|.
+ optional AppendedData appended_data = 61;
+
enum SequenceFlags {
SEQ_UNSPECIFIED = 0;
@@ -4054,6 +4059,9 @@
}
}
repeated GpuCounter counters = 2;
+
+ // optional. Identifier for GPU in a multi-gpu device.
+ optional int32 gpu_id = 3;
}
// End of protos/perfetto/trace/gpu/gpu_counter_event.proto
@@ -4065,8 +4073,8 @@
// required. Unique ID for the event.
optional uint64 event_id = 1;
- // optional. Duration in GPU clock. If unset, this is a single time point
- // event.
+ // optional. Duration of the event. This should be in the same clock domain as the timestamp of
+ // the packet. If unset, this is a single time point event.
optional uint64 duration = 2;
// required. ID to a hardware queue description in the specifications.
@@ -4078,10 +4086,10 @@
// required. GL context/VK device.
optional uint64 context = 5;
- // optional. The surface or render target for this event.
- optional uint64 surface_id = 8;
+ // optional. The render target for this event.
+ optional uint64 render_target_handle = 8;
- // optional. Render pass handle.
+ // optional. The Vulkan render pass handle.
optional uint64 render_pass_handle = 9;
// optional. Submission ID generated by the UMD.
@@ -4109,25 +4117,21 @@
optional string description = 2;
}
- // Labels to categorize the hw Queue this event goes on
+ // Labels to categorize the hw Queue this event goes on.
repeated Description hw_queue = 2;
- // Labels to categorize render stage(binning, render, compute etc)
+ // Labels to categorize render stage(binning, render, compute etc).
repeated Description stage = 3;
}
optional Specifications specifications = 7;
- // optional. If True, duration must not be set and a GpuRenderStageEndEvent is expected.
- optional bool begin_event = 11;
+ // optional. Identifier for GPU in a multi-gpu device.
+ optional int32 gpu_id = 11;
// Extension for vendor's custom proto.
extensions 100;
}
-// Message to signal the end of the last render stage event that had set begin_event.
-message GpuRenderStageEndEvent {
-}
-
// End of protos/perfetto/trace/gpu/gpu_render_stage_event.proto
// Begin of protos/perfetto/config/android/android_log_config.proto
@@ -4887,6 +4891,12 @@
// List of counters to be sampled. Counter IDs correspond to the ones
// described in GpuCounterSpec in the data source descriptor.
repeated uint32 counter_ids = 2;
+
+ // Sample counters by instrumenting command buffers.
+ optional bool instrumented_sampling = 3;
+
+ // Fix gpu clock rate during trace session.
+ optional bool fix_gpu_clock = 4;
}
// End of protos/perfetto/config/gpu/gpu_counter_config.proto
diff --git a/protos/perfetto/trace/trace_packet.proto b/protos/perfetto/trace/trace_packet.proto
index c050a5c..0afaf8b 100644
--- a/protos/perfetto/trace/trace_packet.proto
+++ b/protos/perfetto/trace/trace_packet.proto
@@ -22,6 +22,7 @@
import "protos/perfetto/trace/android/android_log.proto";
import "protos/perfetto/trace/android/graphics_frame_event.proto";
import "protos/perfetto/trace/android/packages_list.proto";
+import "protos/perfetto/trace/appended_data/appended_data.proto";
import "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto";
import "protos/perfetto/trace/chrome/chrome_metadata.proto";
import "protos/perfetto/trace/chrome/chrome_trace_event.proto";
@@ -56,7 +57,7 @@
// TracePacket(s).
//
// Next reserved id: 13 (up to 15).
-// Next id: 61.
+// Next id: 62.
message TracePacket {
// The timestamp of the TracePacket.
// By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
@@ -159,6 +160,11 @@
// proactively in advance of referring to them in later packets.
optional InternedData interned_data = 12;
+ // Data appended to the trace post-processing (e.g. symbol information). When
+ // the AppendedData contents refer to interned data, they must share the same
+ // |trusted_packet_sequence_id|.
+ optional AppendedData appended_data = 61;
+
enum SequenceFlags {
SEQ_UNSPECIFIED = 0;
diff --git a/protos/perfetto/trace_processor/proto_files.gni b/protos/perfetto/trace_processor/proto_files.gni
index 20d1529..2b7d53e 100644
--- a/protos/perfetto/trace_processor/proto_files.gni
+++ b/protos/perfetto/trace_processor/proto_files.gni
@@ -15,7 +15,6 @@
# This variable is used both by ./BUILD.gn (for the C++ proto codegen) and by
# //ui/BUIlD.gn (for the TypeScript/JS proto codegen).
trace_processor_protos = [
- "sched",
"raw_query",
"trace_processor",
]
diff --git a/protos/perfetto/trace_processor/sched.proto b/src/android_internal/empty_file.cc
similarity index 67%
rename from protos/perfetto/trace_processor/sched.proto
rename to src/android_internal/empty_file.cc
index ba59999..22ffa8f 100644
--- a/protos/perfetto/trace_processor/sched.proto
+++ b/src/android_internal/empty_file.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,12 +14,8 @@
* limitations under the License.
*/
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
+// TODO(primiano): this file is here only to have one translation unit for the
+// temporary perfetto_src_tracing_ipc target.
-package perfetto.protos;
-
-message Sched {
- // TODO(primiano): fill in next CLs.
- optional string test = 1;
-}
+__attribute__((visibility("default"))) void PerfettoNoOp();
+void PerfettoNoOp() {}
diff --git a/src/base/string_utils.cc b/src/base/string_utils.cc
index e5b7c4e..c042290 100644
--- a/src/base/string_utils.cc
+++ b/src/base/string_utils.cc
@@ -16,6 +16,8 @@
#include "perfetto/ext/base/string_utils.h"
+#include <string.h>
+
#include <algorithm>
#include "perfetto/base/logging.h"
@@ -39,8 +41,9 @@
bool CaseInsensitiveEqual(const std::string& first, const std::string& second) {
return first.size() == second.size() &&
- std::equal(first.begin(), first.end(), second.begin(),
- [](char a, char b) { return tolower(a) == tolower(b); });
+ std::equal(
+ first.begin(), first.end(), second.begin(),
+ [](char a, char b) { return Lowercase(a) == Lowercase(b); });
}
std::string Join(const std::vector<std::string>& parts,
@@ -64,7 +67,8 @@
size_t next;
for (;;) {
next = std::min(text.find(delimiter, start), text.size());
- output.emplace_back(&text[start], next - start);
+ if (next > start)
+ output.emplace_back(&text[start], next - start);
start = next + delimiter.size();
if (start >= text.size())
break;
@@ -72,5 +76,47 @@
return output;
}
+std::string StripPrefix(const std::string& str, const std::string& prefix) {
+ return StartsWith(str, prefix) ? str.substr(prefix.size()) : str;
+}
+
+std::string StripSuffix(const std::string& str, const std::string& suffix) {
+ return EndsWith(str, suffix) ? str.substr(0, str.size() - suffix.size())
+ : str;
+}
+
+std::string ToUpper(const std::string& str) {
+ // Don't use toupper(), it depends on the locale.
+ std::string res(str);
+ auto end = res.end();
+ for (auto c = res.begin(); c != end; ++c)
+ *c = ('a' <= *c && *c <= 'z') ? (*c += 'A' - 'a') : *c;
+ return res;
+}
+
+std::string ToHex(const char* data, size_t size) {
+ std::string hex(2 * size + 1, 'x');
+ for (size_t i = 0; i < size; ++i) {
+ // snprintf prints 3 characters, the two hex digits and a null byte. As we
+ // write left to write, we keep overwriting the nullbytes, except for the
+ // last call to snprintf.
+ snprintf(&(hex[2 * i]), 3, "%02hhx", data[i]);
+ }
+ // Remove the trailing nullbyte produced by the last snprintf.
+ hex.resize(2 * size);
+ return hex;
+}
+
+std::string StripChars(const std::string& str,
+ const std::string& chars,
+ char replacement) {
+ std::string res(str);
+ const char* start = res.c_str();
+ const char* remove = chars.c_str();
+ for (const char* c = strpbrk(start, remove); c; c = strpbrk(c + 1, remove))
+ res[static_cast<uintptr_t>(c - start)] = replacement;
+ return res;
+}
+
} // namespace base
} // namespace perfetto
diff --git a/src/base/string_utils_unittest.cc b/src/base/string_utils_unittest.cc
index 58d0262..c14415c 100644
--- a/src/base/string_utils_unittest.cc
+++ b/src/base/string_utils_unittest.cc
@@ -23,6 +23,22 @@
using testing::ElementsAre;
+TEST(StringUtilsTest, Lowercase) {
+ EXPECT_EQ(Lowercase('A'), 'a');
+ EXPECT_EQ(Lowercase('a'), 'a');
+ EXPECT_EQ(Lowercase('Z'), 'z');
+ EXPECT_EQ(Lowercase('z'), 'z');
+ EXPECT_EQ(Lowercase('!'), '!');
+}
+
+TEST(StringUtilsTest, Uppercase) {
+ EXPECT_EQ(Uppercase('A'), 'A');
+ EXPECT_EQ(Uppercase('a'), 'A');
+ EXPECT_EQ(Uppercase('Z'), 'Z');
+ EXPECT_EQ(Uppercase('z'), 'Z');
+ EXPECT_EQ(Uppercase('!'), '!');
+}
+
TEST(StringUtilsTest, StartsWith) {
EXPECT_TRUE(StartsWith("", ""));
EXPECT_TRUE(StartsWith("abc", ""));
@@ -45,6 +61,11 @@
EXPECT_FALSE(EndsWith("", "c"));
}
+TEST(StringUtilsTest, ToHex) {
+ EXPECT_EQ(ToHex(""), "");
+ EXPECT_EQ(ToHex("abc123"), "616263313233");
+}
+
TEST(StringUtilsTest, CaseInsensitiveEqual) {
EXPECT_TRUE(CaseInsensitiveEqual("", ""));
EXPECT_TRUE(CaseInsensitiveEqual("abc", "abc"));
@@ -55,15 +76,38 @@
}
TEST(StringUtilsTest, SplitString) {
- EXPECT_THAT(SplitString("", ":"), ElementsAre(""));
+ EXPECT_THAT(SplitString("", ":"), ElementsAre());
EXPECT_THAT(SplitString("a:b:c", ":"), ElementsAre("a", "b", "c"));
EXPECT_THAT(SplitString("a::b::c", "::"), ElementsAre("a", "b", "c"));
+ EXPECT_THAT(SplitString("::::a::b::::c::", "::"), ElementsAre("a", "b", "c"));
EXPECT_THAT(SplitString("abc", ":"), ElementsAre("abc"));
EXPECT_THAT(SplitString("abc", "::"), ElementsAre("abc"));
EXPECT_THAT(SplitString("abc", ":"), ElementsAre("abc"));
EXPECT_THAT(SplitString("abc", "::"), ElementsAre("abc"));
}
+TEST(StringUtilsTest, Strip) {
+ EXPECT_EQ(StripPrefix("abc", ""), "abc");
+ EXPECT_EQ(StripPrefix("abc", "a"), "bc");
+ EXPECT_EQ(StripPrefix("abc", "ab"), "c");
+ EXPECT_EQ(StripPrefix("abc", "abc"), "");
+ EXPECT_EQ(StripPrefix("abc", "abcd"), "abc");
+
+ EXPECT_EQ(StripSuffix("abc", ""), "abc");
+ EXPECT_EQ(StripSuffix("abc", "c"), "ab");
+ EXPECT_EQ(StripSuffix("abc", "bc"), "a");
+ EXPECT_EQ(StripSuffix("abc", "abc"), "");
+ EXPECT_EQ(StripSuffix("abc", "ebcd"), "abc");
+
+ EXPECT_EQ(StripChars("foobar", "", '_'), "foobar");
+ EXPECT_EQ(StripChars("foobar", "x", '_'), "foobar");
+ EXPECT_EQ(StripChars("foobar", "f", '_'), "_oobar");
+ EXPECT_EQ(StripChars("foobar", "o", '_'), "f__bar");
+ EXPECT_EQ(StripChars("foobar", "oa", '_'), "f__b_r");
+ EXPECT_EQ(StripChars("foobar", "fbr", '_'), "_oo_a_");
+ EXPECT_EQ(StripChars("foobar", "froab", '_'), "______");
+}
+
} // namespace
} // namespace base
} // namespace perfetto
diff --git a/src/ipc/BUILD.gn b/src/ipc/BUILD.gn
index e476e1c..12353de 100644
--- a/src/ipc/BUILD.gn
+++ b/src/ipc/BUILD.gn
@@ -29,8 +29,8 @@
"../base:unix_socket",
]
deps = [
- ":wire_protocol",
"../../gn:default_deps",
+ "../../protos/perfetto/ipc:wire_protocol",
"../base",
]
sources = [
@@ -52,8 +52,8 @@
]
deps = [
":ipc",
- ":wire_protocol",
"../../gn:default_deps",
+ "../../protos/perfetto/ipc:wire_protocol",
]
}
@@ -62,9 +62,9 @@
deps = [
":ipc",
":test_messages",
- ":wire_protocol",
"../../gn:default_deps",
"../../gn:gtest_and_gmock",
+ "../../protos/perfetto/ipc:wire_protocol",
"../base",
"../base:test_support",
]
@@ -77,14 +77,6 @@
]
}
-perfetto_proto_library("wire_protocol") {
- proto_generators = [ "lite" ]
- sources = [
- "wire_protocol.proto",
- ]
- proto_path = perfetto_root_path
-}
-
ipc_library("test_messages") {
sources = [
"test/client_unittest_messages.proto",
diff --git a/src/ipc/buffered_frame_deserializer.cc b/src/ipc/buffered_frame_deserializer.cc
index 290db65..dc107f7 100644
--- a/src/ipc/buffered_frame_deserializer.cc
+++ b/src/ipc/buffered_frame_deserializer.cc
@@ -22,11 +22,10 @@
#include <type_traits>
#include <utility>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/utils.h"
-#include "src/ipc/wire_protocol.pb.h"
+#include "protos/perfetto/ipc/wire_protocol.pb.h"
namespace perfetto {
namespace ipc {
@@ -167,9 +166,7 @@
if (size == 0)
return;
std::unique_ptr<Frame> frame(new Frame);
- const int sz = static_cast<int>(size);
- ::google::protobuf::io::ArrayInputStream stream(data, sz);
- if (frame->ParseFromBoundedZeroCopyStream(&stream, sz))
+ if (frame->ParseFromArray(data, static_cast<int>(size)))
decoded_frames_.push_back(std::move(frame));
}
diff --git a/src/ipc/buffered_frame_deserializer_fuzzer.cc b/src/ipc/buffered_frame_deserializer_fuzzer.cc
index c3b22bb..61a818d 100644
--- a/src/ipc/buffered_frame_deserializer_fuzzer.cc
+++ b/src/ipc/buffered_frame_deserializer_fuzzer.cc
@@ -19,7 +19,8 @@
#include "perfetto/ext/base/utils.h"
#include "src/ipc/buffered_frame_deserializer.h"
-#include "src/ipc/wire_protocol.pb.h"
+
+#include "protos/perfetto/ipc/wire_protocol.pb.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
diff --git a/src/ipc/buffered_frame_deserializer_unittest.cc b/src/ipc/buffered_frame_deserializer_unittest.cc
index 727ee7e..792365b 100644
--- a/src/ipc/buffered_frame_deserializer_unittest.cc
+++ b/src/ipc/buffered_frame_deserializer_unittest.cc
@@ -23,7 +23,7 @@
#include "perfetto/ext/base/utils.h"
#include "test/gtest_and_gmock.h"
-#include "src/ipc/wire_protocol.pb.h"
+#include "protos/perfetto/ipc/wire_protocol.pb.h"
namespace perfetto {
namespace ipc {
diff --git a/src/ipc/client_impl.cc b/src/ipc/client_impl.cc
index ff0dca2..c3bd830 100644
--- a/src/ipc/client_impl.cc
+++ b/src/ipc/client_impl.cc
@@ -43,7 +43,6 @@
ClientImpl::ClientImpl(const char* socket_name, base::TaskRunner* task_runner)
: task_runner_(task_runner), weak_ptr_factory_(this) {
- GOOGLE_PROTOBUF_VERIFY_VERSION;
sock_ = base::UnixSocket::Connect(socket_name, this, task_runner);
}
diff --git a/src/ipc/client_impl.h b/src/ipc/client_impl.h
index db65f02..71c211f 100644
--- a/src/ipc/client_impl.h
+++ b/src/ipc/client_impl.h
@@ -23,7 +23,7 @@
#include "perfetto/ext/ipc/client.h"
#include "src/ipc/buffered_frame_deserializer.h"
-#include "src/ipc/wire_protocol.pb.h"
+#include "protos/perfetto/ipc/wire_protocol.pb.h"
#include <list>
#include <map>
diff --git a/src/ipc/deferred.cc b/src/ipc/deferred.cc
index 2bc12ec..c16604a 100644
--- a/src/ipc/deferred.cc
+++ b/src/ipc/deferred.cc
@@ -16,8 +16,6 @@
#include "perfetto/ext/ipc/deferred.h"
-#include <google/protobuf/message_lite.h>
-
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/utils.h"
diff --git a/src/ipc/host_impl.cc b/src/ipc/host_impl.cc
index 6895424..662e6e6 100644
--- a/src/ipc/host_impl.cc
+++ b/src/ipc/host_impl.cc
@@ -26,7 +26,7 @@
#include "perfetto/ext/ipc/service.h"
#include "perfetto/ext/ipc/service_descriptor.h"
-#include "src/ipc/wire_protocol.pb.h"
+#include "protos/perfetto/ipc/wire_protocol.pb.h"
// TODO(primiano): put limits on #connections/uid and req. queue (b/69093705).
@@ -54,14 +54,12 @@
HostImpl::HostImpl(base::ScopedFile socket_fd, base::TaskRunner* task_runner)
: task_runner_(task_runner), weak_ptr_factory_(this) {
- GOOGLE_PROTOBUF_VERIFY_VERSION;
PERFETTO_DCHECK_THREAD(thread_checker_);
sock_ = base::UnixSocket::Listen(std::move(socket_fd), this, task_runner_);
}
HostImpl::HostImpl(const char* socket_name, base::TaskRunner* task_runner)
: task_runner_(task_runner), weak_ptr_factory_(this) {
- GOOGLE_PROTOBUF_VERIFY_VERSION;
PERFETTO_DCHECK_THREAD(thread_checker_);
sock_ = base::UnixSocket::Listen(socket_name, this, task_runner_);
}
diff --git a/src/ipc/host_impl_unittest.cc b/src/ipc/host_impl_unittest.cc
index 025d4c1..70215ff 100644
--- a/src/ipc/host_impl_unittest.cc
+++ b/src/ipc/host_impl_unittest.cc
@@ -30,8 +30,8 @@
#include "src/ipc/test/test_socket.h"
#include "test/gtest_and_gmock.h"
+#include "protos/perfetto/ipc/wire_protocol.pb.h"
#include "src/ipc/test/client_unittest_messages.pb.h"
-#include "src/ipc/wire_protocol.pb.h"
namespace perfetto {
namespace ipc {
diff --git a/src/ipc/protoc_plugin/BUILD.gn b/src/ipc/protoc_plugin/BUILD.gn
index 4478f60..535f53a 100644
--- a/src/ipc/protoc_plugin/BUILD.gn
+++ b/src/ipc/protoc_plugin/BUILD.gn
@@ -21,5 +21,6 @@
deps = [
"../../../gn:default_deps",
"../../../gn:protoc_lib",
+ "../../../src/base",
]
}
diff --git a/src/ipc/protoc_plugin/ipc_plugin.cc b/src/ipc/protoc_plugin/ipc_plugin.cc
index 064e4cd..f3a4372 100644
--- a/src/ipc/protoc_plugin/ipc_plugin.cc
+++ b/src/ipc/protoc_plugin/ipc_plugin.cc
@@ -20,13 +20,13 @@
#include <string>
#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/cpp/cpp_options.h>
#include <google/protobuf/compiler/plugin.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/stubs/strutil.h>
+
+#include "perfetto/ext/base/string_utils.h"
namespace perfetto {
namespace ipc {
@@ -35,13 +35,13 @@
using google::protobuf::FileDescriptor;
using google::protobuf::MethodDescriptor;
using google::protobuf::ServiceDescriptor;
-using google::protobuf::Split;
-using google::protobuf::StripString;
-using google::protobuf::StripSuffixString;
-using google::protobuf::UpperString;
using google::protobuf::compiler::GeneratorContext;
using google::protobuf::io::Printer;
using google::protobuf::io::ZeroCopyOutputStream;
+using perfetto::base::SplitString;
+using perfetto::base::StripChars;
+using perfetto::base::StripSuffix;
+using perfetto::base::ToUpper;
static const char kBanner[] = "// DO NOT EDIT. Autogenerated by Perfetto IPC\n";
@@ -113,7 +113,7 @@
)";
std::string StripName(const FileDescriptor& file) {
- return StripSuffixString(file.name(), ".proto");
+ return StripSuffix(file.name(), ".proto");
}
std::string GetStubName(const FileDescriptor& file) {
@@ -138,7 +138,7 @@
const ServiceDescriptor& svc,
Printer* printer) {
printer->Print("\n");
- std::vector<std::string> namespaces = Split(file.package(), ".");
+ std::vector<std::string> namespaces = SplitString(file.package(), ".");
for (const std::string& ns : namespaces)
printer->Print("namespace $ns$ {\n", "ns", ns);
@@ -185,7 +185,7 @@
Printer* printer) {
printer->Print("\n");
- std::vector<std::string> namespaces = Split(file.package(), ".");
+ std::vector<std::string> namespaces = SplitString(file.package(), ".");
for (const std::string& ns : namespaces)
printer->Print("namespace $ns$ {\n", "ns", ns);
@@ -251,9 +251,8 @@
Printer h_printer(h_fstream.get(), '$');
Printer cc_printer(cc_fstream.get(), '$');
- std::string guard = file->package() + "_" + file->name() + "_H_";
- UpperString(&guard);
- StripString(&guard, ".-/\\", '_');
+ std::string guard = ToUpper(file->package() + "_" + file->name() + "_H_");
+ guard = StripChars(guard, ".-/\\", '_');
h_printer.Print(kBanner);
h_printer.Print("#ifndef $guard$\n#define $guard$\n\n", "guard", guard);
diff --git a/src/ipc/service_proxy.cc b/src/ipc/service_proxy.cc
index 5edb857..e416f5f 100644
--- a/src/ipc/service_proxy.cc
+++ b/src/ipc/service_proxy.cc
@@ -18,7 +18,6 @@
#include <utility>
-#include <google/protobuf/message_lite.h>
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/weak_ptr.h"
#include "perfetto/ext/ipc/service_descriptor.h"
diff --git a/src/perfetto_cmd/pbtxt_to_pb.cc b/src/perfetto_cmd/pbtxt_to_pb.cc
index 038f1b8..101100d 100644
--- a/src/perfetto_cmd/pbtxt_to_pb.cc
+++ b/src/perfetto_cmd/pbtxt_to_pb.cc
@@ -21,8 +21,6 @@
#include "src/perfetto_cmd/pbtxt_to_pb.h"
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/string_view.h"
@@ -41,8 +39,6 @@
using protos::EnumValueDescriptorProto;
using protos::FieldDescriptorProto;
using protos::FileDescriptorSet;
-using ::google::protobuf::io::ZeroCopyInputStream;
-using ::google::protobuf::io::ArrayInputStream;
namespace {
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index 7bf529a..cdf6017 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -30,8 +30,6 @@
#include <iterator>
#include <sstream>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-
#include "perfetto/base/logging.h"
#include "perfetto/base/time.h"
#include "perfetto/ext/base/file_utils.h"
diff --git a/src/profiling/memory/CHANGELOG.md b/src/profiling/memory/CHANGELOG.md
index 199ceab..56f64b5 100644
--- a/src/profiling/memory/CHANGELOG.md
+++ b/src/profiling/memory/CHANGELOG.md
@@ -1,4 +1,4 @@
-# Changes from Android Q
+# Changes from Android 10
## New features
* Allow to specify whether profiling should only be done for existing processes
@@ -9,3 +9,4 @@
* Allow to dump the maximum, rather than at the time of the dump.
## Bugfixes
+* Fixed heapprofd on x86.
diff --git a/src/profiling/memory/bookkeeping.cc b/src/profiling/memory/bookkeeping.cc
index ae5ae71..bd6ee97 100644
--- a/src/profiling/memory/bookkeeping.cc
+++ b/src/profiling/memory/bookkeeping.cc
@@ -58,7 +58,7 @@
alloc.sample_size = sample_size;
alloc.alloc_size = alloc_size;
alloc.sequence_number = sequence_number;
- alloc.callstack_allocations = MaybeCreateCallstackAllocations(node);
+ alloc.SetCallstackAllocations(MaybeCreateCallstackAllocations(node));
}
} else {
GlobalCallstackTrie::Node* node = callsites_->CreateCallsite(callstack);
diff --git a/src/profiling/memory/bookkeeping.h b/src/profiling/memory/bookkeeping.h
index 3cfeff9..c157e07 100644
--- a/src/profiling/memory/bookkeeping.h
+++ b/src/profiling/memory/bookkeeping.h
@@ -290,7 +290,7 @@
for (const auto& addr_and_allocation : allocations_) {
const Allocation& alloc = addr_and_allocation.second;
fn(addr_and_allocation.first, alloc.sample_size, alloc.alloc_size,
- alloc.callstack_allocations->node->id());
+ alloc.callstack_allocations()->node->id());
}
}
@@ -313,11 +313,8 @@
uint64_t asize,
uint64_t seq,
CallstackAllocations* csa)
- : sample_size(size),
- alloc_size(asize),
- sequence_number(seq),
- callstack_allocations(csa) {
- callstack_allocations->allocs++;
+ : sample_size(size), alloc_size(asize), sequence_number(seq) {
+ SetCallstackAllocations(csa);
}
Allocation() = default;
@@ -326,19 +323,30 @@
sample_size = other.sample_size;
alloc_size = other.alloc_size;
sequence_number = other.sequence_number;
- callstack_allocations = other.callstack_allocations;
- other.callstack_allocations = nullptr;
+ callstack_allocations_ = other.callstack_allocations_;
+ other.callstack_allocations_ = nullptr;
}
- ~Allocation() {
- if (callstack_allocations)
- callstack_allocations->allocs--;
+ ~Allocation() { SetCallstackAllocations(nullptr); }
+
+ void SetCallstackAllocations(CallstackAllocations* callstack_allocations) {
+ if (callstack_allocations_)
+ callstack_allocations_->allocs--;
+ callstack_allocations_ = callstack_allocations;
+ if (callstack_allocations_)
+ callstack_allocations_->allocs++;
+ }
+
+ CallstackAllocations* callstack_allocations() const {
+ return callstack_allocations_;
}
uint64_t sample_size;
uint64_t alloc_size;
uint64_t sequence_number;
- CallstackAllocations* callstack_allocations;
+
+ private:
+ CallstackAllocations* callstack_allocations_ = nullptr;
};
struct PendingOperation {
@@ -374,19 +382,19 @@
const PendingOperation& operation);
void AddToCallstackAllocations(uint64_t ts, const Allocation& alloc) {
- alloc.callstack_allocations->allocation_count++;
+ alloc.callstack_allocations()->allocation_count++;
if (dump_at_max_mode_) {
current_unfreed_ += alloc.sample_size;
- alloc.callstack_allocations->value.retain_max.cur += alloc.sample_size;
+ alloc.callstack_allocations()->value.retain_max.cur += alloc.sample_size;
if (current_unfreed_ <= max_unfreed_)
return;
if (max_sequence_number_ == alloc.sequence_number - 1) {
- alloc.callstack_allocations->value.retain_max.max =
+ alloc.callstack_allocations()->value.retain_max.max =
// We know the only CallstackAllocation that has max != cur is the
// one we just updated.
- alloc.callstack_allocations->value.retain_max.cur;
+ alloc.callstack_allocations()->value.retain_max.cur;
} else {
for (auto& p : callstack_allocations_) {
// We need to reset max = cur for every CallstackAllocation, as we
@@ -400,17 +408,18 @@
max_unfreed_ = current_unfreed_;
max_timestamp_ = ts;
} else {
- alloc.callstack_allocations->value.totals.allocated += alloc.sample_size;
+ alloc.callstack_allocations()->value.totals.allocated +=
+ alloc.sample_size;
}
}
void SubtractFromCallstackAllocations(const Allocation& alloc) {
- alloc.callstack_allocations->free_count++;
+ alloc.callstack_allocations()->free_count++;
if (dump_at_max_mode_) {
current_unfreed_ -= alloc.sample_size;
- alloc.callstack_allocations->value.retain_max.cur -= alloc.sample_size;
+ alloc.callstack_allocations()->value.retain_max.cur -= alloc.sample_size;
} else {
- alloc.callstack_allocations->value.totals.freed += alloc.sample_size;
+ alloc.callstack_allocations()->value.totals.freed += alloc.sample_size;
}
}
diff --git a/src/profiling/memory/bookkeeping_dump.cc b/src/profiling/memory/bookkeeping_dump.cc
index 0020a7a..13e24bc 100644
--- a/src/profiling/memory/bookkeeping_dump.cc
+++ b/src/profiling/memory/bookkeeping_dump.cc
@@ -169,7 +169,7 @@
MakeProfilePacket();
}
-void DumpState::AddIdleBytes(uintptr_t callstack_id, uint64_t bytes) {
+void DumpState::AddIdleBytes(uint64_t callstack_id, uint64_t bytes) {
current_process_idle_allocs_[callstack_id] += bytes;
}
diff --git a/src/profiling/memory/bookkeeping_dump.h b/src/profiling/memory/bookkeeping_dump.h
index 1daa86b..bb09914 100644
--- a/src/profiling/memory/bookkeeping_dump.h
+++ b/src/profiling/memory/bookkeeping_dump.h
@@ -69,7 +69,7 @@
DumpState(DumpState&&) = delete;
DumpState& operator=(DumpState&&) = delete;
- void AddIdleBytes(uintptr_t callstack_id, uint64_t bytes);
+ void AddIdleBytes(uint64_t callstack_id, uint64_t bytes);
void WriteAllocation(const HeapTracker::CallstackAllocations& alloc,
bool dump_at_max_mode);
@@ -122,7 +122,7 @@
current_process_heap_samples_ = nullptr;
std::function<void(protos::pbzero::ProfilePacket::ProcessHeapSamples*)>
current_process_fill_header_;
- std::map<uintptr_t /* callstack_id */, uint64_t> current_process_idle_allocs_;
+ std::map<uint64_t /* callstack_id */, uint64_t> current_process_idle_allocs_;
uint64_t last_written_ = 0;
};
diff --git a/src/profiling/memory/bookkeeping_unittest.cc b/src/profiling/memory/bookkeeping_unittest.cc
index 064712c..940e23c 100644
--- a/src/profiling/memory/bookkeeping_unittest.cc
+++ b/src/profiling/memory/bookkeeping_unittest.cc
@@ -63,6 +63,20 @@
hd.GetCallstackAllocations([](const HeapTracker::CallstackAllocations&) {});
}
+TEST(BookkeepingTest, Replace) {
+ uint64_t sequence_number = 1;
+ GlobalCallstackTrie c;
+ HeapTracker hd(&c, false);
+
+ hd.RecordMalloc(stack(), 1, 5, 5, sequence_number, 100 * sequence_number);
+ sequence_number++;
+ hd.RecordMalloc(stack2(), 1, 2, 2, sequence_number, 100 * sequence_number);
+
+ // Call GetCallstackAllocations twice to force GC of old CallstackAllocations.
+ hd.GetCallstackAllocations([](const HeapTracker::CallstackAllocations&) {});
+ hd.GetCallstackAllocations([](const HeapTracker::CallstackAllocations&) {});
+}
+
TEST(BookkeepingTest, Basic) {
uint64_t sequence_number = 1;
GlobalCallstackTrie c;
diff --git a/src/profiling/memory/ext.h b/src/profiling/memory/ext.h
new file mode 100644
index 0000000..b353e98
--- /dev/null
+++ b/src/profiling/memory/ext.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_PROFILING_MEMORY_EXT_H_
+#define SRC_PROFILING_MEMORY_EXT_H_
+
+// Header only code that gets used in other projects.
+// This is currently used in
+// * ART
+// * Bionic
+// * Heapprofd
+//
+// DO NOT USE THE STL HERE. This gets used in parts of Bionic that do not
+// use the STL.
+
+#include <string.h>
+
+namespace perfetto {
+namespace profiling {
+
+// Normalize cmdline in place. Stores new beginning of string in *cmdline_ptr.
+// Returns new size of string (from new beginning).
+// Modifies string in *cmdline_ptr.
+static ssize_t NormalizeCmdLine(char** cmdline_ptr, size_t size) {
+ char* cmdline = *cmdline_ptr;
+ char* first_arg = static_cast<char*>(memchr(cmdline, '\0', size));
+ if (first_arg == nullptr) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ // For consistency with what we do with Java app cmdlines, trim everything
+ // after the @ sign of the first arg.
+ char* first_at = static_cast<char*>(memchr(cmdline, '@', size));
+ if (first_at != nullptr && first_at < first_arg) {
+ *first_at = '\0';
+ first_arg = first_at;
+ }
+ char* start = static_cast<char*>(
+ memrchr(cmdline, '/', static_cast<size_t>(first_arg - cmdline)));
+ if (start == nullptr) {
+ start = cmdline;
+ } else {
+ // Skip the /.
+ start++;
+ }
+ *cmdline_ptr = start;
+ return first_arg - start;
+}
+
+} // namespace profiling
+} // namespace perfetto
+
+#endif // SRC_PROFILING_MEMORY_EXT_H_
diff --git a/src/profiling/memory/heapprofd_end_to_end_test.cc b/src/profiling/memory/heapprofd_end_to_end_test.cc
index fb3b254..42e666f 100644
--- a/src/profiling/memory/heapprofd_end_to_end_test.cc
+++ b/src/profiling/memory/heapprofd_end_to_end_test.cc
@@ -738,8 +738,8 @@
}
TEST_P(HeapprofdEndToEnd, ReInit) {
- constexpr uint64_t kFirstIterationBytes = 5;
- constexpr uint64_t kSecondIterationBytes = 7;
+ constexpr size_t kFirstIterationBytes = 5;
+ constexpr size_t kSecondIterationBytes = 7;
base::Pipe signal_pipe = base::Pipe::Create(base::Pipe::kBothNonBlock);
base::Pipe ack_pipe = base::Pipe::Create(base::Pipe::kBothBlock);
@@ -750,7 +750,7 @@
case -1:
PERFETTO_FATAL("Failed to fork.");
case 0: {
- uint64_t bytes = kFirstIterationBytes;
+ size_t bytes = kFirstIterationBytes;
signal_pipe.wr.reset();
ack_pipe.rd.reset();
for (;;) {
@@ -819,7 +819,7 @@
PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
}
-TEST_P(HeapprofdEndToEnd, DISABLED_ConcurrentSession) {
+TEST_P(HeapprofdEndToEnd, ConcurrentSession) {
constexpr size_t kAllocSize = 1024;
pid_t pid = ForkContinuousMalloc(kAllocSize);
@@ -961,10 +961,8 @@
// This test only works when run on Android using an Android Q version of
// Bionic.
-// TODO(b/118428762): look into unwinding issues on x86.
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
- PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS) || defined(__i386__) || \
- defined(__x86_64__)
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
INSTANTIATE_TEST_CASE_P(DISABLED_Run, HeapprofdEndToEnd, Bool(), TestSuffix);
#else
INSTANTIATE_TEST_CASE_P(Run, HeapprofdEndToEnd, Bool(), TestSuffix);
diff --git a/src/profiling/memory/heapprofd_producer.cc b/src/profiling/memory/heapprofd_producer.cc
index 155dd77..c9c7767 100644
--- a/src/profiling/memory/heapprofd_producer.cc
+++ b/src/profiling/memory/heapprofd_producer.cc
@@ -577,18 +577,19 @@
if (process_state->page_idle_checker) {
PageIdleChecker& page_idle_checker = *process_state->page_idle_checker;
- heap_tracker.GetAllocations(
- [&dump_state, &page_idle_checker](uint64_t addr, uint64_t,
- uint64_t alloc_size,
- uintptr_t callstack_id) {
- int64_t idle = page_idle_checker.OnIdlePage(addr, alloc_size);
- if (idle < 0) {
- PERFETTO_PLOG("OnIdlePage.");
- return;
- }
- if (idle > 0)
- dump_state.AddIdleBytes(callstack_id, static_cast<uint64_t>(idle));
- });
+ heap_tracker.GetAllocations([&dump_state, &page_idle_checker](
+ uint64_t addr, uint64_t,
+ uint64_t alloc_size,
+ uint64_t callstack_id) {
+ int64_t idle =
+ page_idle_checker.OnIdlePage(addr, static_cast<size_t>(alloc_size));
+ if (idle < 0) {
+ PERFETTO_PLOG("OnIdlePage.");
+ return;
+ }
+ if (idle > 0)
+ dump_state.AddIdleBytes(callstack_id, static_cast<uint64_t>(idle));
+ });
}
heap_tracker.GetCallstackAllocations(
@@ -810,7 +811,7 @@
if (shmem_size > kMaxShmemSize)
shmem_size = kMaxShmemSize;
- auto shmem = SharedRingBuffer::Create(shmem_size);
+ auto shmem = SharedRingBuffer::Create(static_cast<size_t>(shmem_size));
if (!shmem || !shmem->is_valid()) {
PERFETTO_LOG("Failed to create shared memory.");
return;
diff --git a/src/profiling/memory/page_idle_checker.cc b/src/profiling/memory/page_idle_checker.cc
index e0f0ef3..7e639b5 100644
--- a/src/profiling/memory/page_idle_checker.cc
+++ b/src/profiling/memory/page_idle_checker.cc
@@ -34,7 +34,7 @@
if ((addr + size) % base::kPageSize != 0)
end_page_nr++;
- size_t pages = end_page_nr - page_nr;
+ size_t pages = static_cast<size_t>(end_page_nr - page_nr);
int64_t idle_mem = 0;
for (size_t i = 0; i < pages; ++i) {
diff --git a/src/profiling/memory/proc_utils.cc b/src/profiling/memory/proc_utils.cc
index ba5ee79..07f85cd 100644
--- a/src/profiling/memory/proc_utils.cc
+++ b/src/profiling/memory/proc_utils.cc
@@ -21,28 +21,12 @@
#include <unistd.h>
#include "perfetto/ext/base/file_utils.h"
+#include "src/profiling/memory/ext.h"
namespace perfetto {
namespace profiling {
namespace {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
-
-const char* FindChar(const char* s, char c, size_t n) {
- std::string str(s, n);
- auto idx = str.rfind(c);
- if (idx == std::string::npos)
- return nullptr;
- return s + n;
-}
-
-void* memrchr(const void* s, int c, size_t n) {
- return static_cast<void*>(const_cast<char*>(
- FindChar(static_cast<const char*>(s), static_cast<char>(c), n)));
-}
-
-#endif
-
bool GetProcFile(pid_t pid, const char* file, char* filename_buf, size_t size) {
ssize_t written = snprintf(filename_buf, size, "/proc/%d/%s", pid, file);
if (written < 0 || static_cast<size_t>(written) >= size) {
@@ -57,38 +41,6 @@
} // namespace
-bool NormalizeCmdLine(char* cmdline, size_t size, std::string* name) {
- char* first_arg = static_cast<char*>(memchr(cmdline, '\0', size));
- if (first_arg == nullptr) {
- PERFETTO_DLOG("Overflow reading cmdline");
- errno = EOVERFLOW;
- return false;
- }
- // For consistency with what we do with Java app cmdlines, trim everything
- // after the @ sign of the first arg.
- char* first_at = static_cast<char*>(memchr(cmdline, '@', size));
- if (first_at != nullptr && first_at < first_arg) {
- *first_at = '\0';
- first_arg = first_at;
- }
- char* start = static_cast<char*>(
- memrchr(cmdline, '/', static_cast<size_t>(first_arg - cmdline)));
- if (start == first_arg) {
- // The first argument ended in a slash.
- PERFETTO_DLOG("cmdline ends in /");
- errno = EINVAL;
- return false;
- } else if (start == nullptr) {
- start = cmdline;
- } else {
- // Skip the /.
- start++;
- }
- size_t name_size = static_cast<size_t>(first_arg - start);
- name->assign(start, name_size);
- return true;
-}
-
std::vector<std::string> NormalizeCmdlines(
const std::vector<std::string>& cmdlines) {
std::vector<std::string> normalized_cmdlines;
@@ -96,12 +48,15 @@
// Add nullbyte to make sure it's a C string.
cmdline.resize(cmdline.size() + 1, '\0');
std::string normalized;
- if (!NormalizeCmdLine(&(cmdline[0]), cmdline.size(), &normalized)) {
- PERFETTO_ELOG("Failed to normalize cmdline %s. Skipping.",
+ char* cmdline_cstr = &(cmdline[0]);
+ ssize_t size = NormalizeCmdLine(&cmdline_cstr, cmdline.size());
+ if (size == -1) {
+ PERFETTO_PLOG("Failed to normalize cmdline %s. Skipping.",
cmdline.c_str());
continue;
}
- normalized_cmdlines.emplace_back(std::move(normalized));
+ normalized_cmdlines.emplace_back(
+ std::string(cmdline_cstr, static_cast<size_t>(size)));
}
return normalized_cmdlines;
}
@@ -138,7 +93,12 @@
}
cmdline[rd] = '\0';
- return NormalizeCmdLine(cmdline, static_cast<size_t>(rd), name);
+ char* cmdline_start = cmdline;
+ ssize_t size = NormalizeCmdLine(&cmdline_start, static_cast<size_t>(rd));
+ if (size == -1)
+ return false;
+ name->assign(cmdline_start, static_cast<size_t>(size));
+ return true;
}
void FindAllProfilablePids(std::set<pid_t>* pids) {
diff --git a/src/profiling/memory/proc_utils.h b/src/profiling/memory/proc_utils.h
index d20d8ba..e123194 100644
--- a/src/profiling/memory/proc_utils.h
+++ b/src/profiling/memory/proc_utils.h
@@ -43,7 +43,6 @@
}
}
-bool NormalizeCmdLine(char* cmdline, size_t size, std::string* name);
std::vector<std::string> NormalizeCmdlines(
const std::vector<std::string>& cmdlines);
diff --git a/src/profiling/memory/proc_utils_unittest.cc b/src/profiling/memory/proc_utils_unittest.cc
index b011e4f..b1881bb 100644
--- a/src/profiling/memory/proc_utils_unittest.cc
+++ b/src/profiling/memory/proc_utils_unittest.cc
@@ -15,6 +15,7 @@
*/
#include "src/profiling/memory/proc_utils.h"
+#include "src/profiling/memory/ext.h"
#include "perfetto/ext/base/utils.h"
#include "test/gtest_and_gmock.h"
@@ -26,25 +27,77 @@
using ::testing::Contains;
using ::testing::Not;
+std::string NormalizeToString(char* cmdline, size_t size) {
+ ssize_t new_size = NormalizeCmdLine(&cmdline, size);
+ if (new_size == -1)
+ return "";
+ return std::string(cmdline, static_cast<size_t>(new_size));
+}
+
TEST(ProcUtilsTest, NormalizeNoop) {
- char kCmdline[] = "surfaceflinger\0";
- std::string name;
- ASSERT_TRUE(NormalizeCmdLine(kCmdline, sizeof(kCmdline), &name));
- EXPECT_EQ(name, "surfaceflinger");
+ char kCmdline[] = "surfaceflinger";
+ EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "surfaceflinger");
+}
+
+TEST(ProcUtilsTest, NormalizeTwoArgs) {
+ char kCmdline[] = "surfaceflinger\0--foo";
+ EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "surfaceflinger");
}
TEST(ProcUtilsTest, NormalizePath) {
- char kCmdline[] = "/system/bin/surfaceflinger\0";
- std::string name;
- ASSERT_TRUE(NormalizeCmdLine(kCmdline, sizeof(kCmdline), &name));
- EXPECT_EQ(name, "surfaceflinger");
+ char kCmdline[] = "/system/bin/surfaceflinger";
+ EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "surfaceflinger");
}
TEST(ProcUtilsTest, NormalizeAt) {
- char kCmdline[] = "some.app@2.0\0";
- std::string name;
- ASSERT_TRUE(NormalizeCmdLine(kCmdline, sizeof(kCmdline), &name));
- EXPECT_EQ(name, "some.app");
+ char kCmdline[] = "some.app@2.0";
+ EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "some.app");
+}
+
+TEST(ProcUtilsTest, NormalizeEmpty) {
+ char kCmdline[] = "";
+ EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "");
+}
+
+TEST(ProcUtilsTest, NormalizeTrailingAt) {
+ char kCmdline[] = "foo@";
+ EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "foo");
+}
+
+TEST(ProcUtilsTest, NormalizeOnlyTrailingAt) {
+ char kCmdline[] = "@";
+ EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "");
+}
+
+TEST(ProcUtilsTest, NormalizeTrailingSlash) {
+ char kCmdline[] = "foo/";
+ EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "");
+}
+
+TEST(ProcUtilsTest, NormalizeOnlySlash) {
+ char kCmdline[] = "/";
+ EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "");
+}
+
+TEST(ProcUtilsTest, NormalizeTwoArgsSlash) {
+ char kCmdline[] = "surfaceflinger/\0--foo";
+ EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "");
+}
+
+TEST(ProcUtilsTest, NormalizeEmptyFirstArg) {
+ char kCmdline[] = "\0--foo";
+ EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "");
+}
+
+TEST(ProcUtilsTest, NormalizeNoNullTerminated) {
+ char kCmdline[] = {'f'};
+ char* cmdline = kCmdline;
+ EXPECT_EQ(NormalizeCmdLine(&cmdline, sizeof(kCmdline)), -1);
+}
+
+TEST(ProcUtilsTest, NormalizeZeroLength) {
+ char* cmdline = nullptr;
+ EXPECT_EQ(NormalizeCmdLine(&cmdline, 0), -1);
}
TEST(ProcUtilsTest, FindProfilablePids) {
diff --git a/src/profiling/memory/sampler.h b/src/profiling/memory/sampler.h
index b46d4bf..6740d17 100644
--- a/src/profiling/memory/sampler.h
+++ b/src/profiling/memory/sampler.h
@@ -54,7 +54,7 @@
size_t SampleSize(size_t alloc_sz) {
if (PERFETTO_UNLIKELY(alloc_sz >= sampling_interval_))
return alloc_sz;
- return sampling_interval_ * NumberOfSamples(alloc_sz);
+ return static_cast<size_t>(sampling_interval_ * NumberOfSamples(alloc_sz));
}
private:
diff --git a/src/profiling/memory/unwinding.cc b/src/profiling/memory/unwinding.cc
index 91215ed..59a4dca 100644
--- a/src/profiling/memory/unwinding.cc
+++ b/src/profiling/memory/unwinding.cc
@@ -72,38 +72,49 @@
static std::vector<std::string> kSkipMaps{"heapprofd_client.so"};
#pragma GCC diagnostic pop
-std::unique_ptr<unwindstack::Regs> CreateFromRawData(unwindstack::ArchEnum arch,
- void* raw_data) {
- std::unique_ptr<unwindstack::Regs> ret;
- // unwindstack::RegsX::Read returns a raw ptr which we are expected to free.
- switch (arch) {
- case unwindstack::ARCH_X86:
- ret.reset(unwindstack::RegsX86::Read(raw_data));
- break;
- case unwindstack::ARCH_X86_64:
- ret.reset(unwindstack::RegsX86_64::Read(raw_data));
- break;
- case unwindstack::ARCH_ARM:
- ret.reset(unwindstack::RegsArm::Read(raw_data));
- break;
- case unwindstack::ARCH_ARM64:
- ret.reset(unwindstack::RegsArm64::Read(raw_data));
- break;
- case unwindstack::ARCH_MIPS:
- ret.reset(unwindstack::RegsMips::Read(raw_data));
- break;
- case unwindstack::ARCH_MIPS64:
- ret.reset(unwindstack::RegsMips64::Read(raw_data));
- break;
- case unwindstack::ARCH_UNKNOWN:
- ret.reset(nullptr);
- break;
- }
- return ret;
+size_t GetRegsSize(unwindstack::Regs* regs) {
+ if (regs->Is32Bit())
+ return sizeof(uint32_t) * regs->total_regs();
+ return sizeof(uint64_t) * regs->total_regs();
+}
+
+void ReadFromRawData(unwindstack::Regs* regs, void* raw_data) {
+ memcpy(regs->RawData(), raw_data, GetRegsSize(regs));
}
} // namespace
+std::unique_ptr<unwindstack::Regs> CreateRegsFromRawData(
+ unwindstack::ArchEnum arch,
+ void* raw_data) {
+ std::unique_ptr<unwindstack::Regs> ret;
+ switch (arch) {
+ case unwindstack::ARCH_X86:
+ ret.reset(new unwindstack::RegsX86());
+ break;
+ case unwindstack::ARCH_X86_64:
+ ret.reset(new unwindstack::RegsX86_64());
+ break;
+ case unwindstack::ARCH_ARM:
+ ret.reset(new unwindstack::RegsArm());
+ break;
+ case unwindstack::ARCH_ARM64:
+ ret.reset(new unwindstack::RegsArm64());
+ break;
+ case unwindstack::ARCH_MIPS:
+ ret.reset(new unwindstack::RegsMips());
+ break;
+ case unwindstack::ARCH_MIPS64:
+ ret.reset(new unwindstack::RegsMips64());
+ break;
+ case unwindstack::ARCH_UNKNOWN:
+ break;
+ }
+ if (ret)
+ ReadFromRawData(ret.get(), raw_data);
+ return ret;
+}
+
StackOverlayMemory::StackOverlayMemory(std::shared_ptr<unwindstack::Memory> mem,
uint64_t sp,
uint8_t* stack,
@@ -165,8 +176,8 @@
bool DoUnwind(WireMessage* msg, UnwindingMetadata* metadata, AllocRecord* out) {
AllocMetadata* alloc_metadata = msg->alloc_header;
- std::unique_ptr<unwindstack::Regs> regs(
- CreateFromRawData(alloc_metadata->arch, alloc_metadata->register_data));
+ std::unique_ptr<unwindstack::Regs> regs(CreateRegsFromRawData(
+ alloc_metadata->arch, alloc_metadata->register_data));
if (regs == nullptr) {
PERFETTO_DLOG("Unable to construct unwindstack::Regs");
unwindstack::FrameData frame_data{};
@@ -195,6 +206,9 @@
if (attempt > 0) {
PERFETTO_DLOG("Reparsing maps");
metadata->ReparseMaps();
+ // Regs got invalidated by libuwindstack's speculative jump.
+ // Reset.
+ ReadFromRawData(regs.get(), alloc_metadata->register_data);
out->reparsed_map = true;
#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
unwinder.SetJitDebug(metadata->jit_debug.get(), regs->Arch());
diff --git a/src/profiling/memory/unwinding.h b/src/profiling/memory/unwinding.h
index 9fab671..39216fe 100644
--- a/src/profiling/memory/unwinding.h
+++ b/src/profiling/memory/unwinding.h
@@ -37,6 +37,10 @@
namespace perfetto {
namespace profiling {
+std::unique_ptr<unwindstack::Regs> CreateRegsFromRawData(
+ unwindstack::ArchEnum arch,
+ void* raw_data);
+
// Read /proc/[pid]/maps from an open file descriptor.
// TODO(fmayer): Figure out deduplication to other maps.
class FileDescriptorMaps : public unwindstack::Maps {
@@ -106,7 +110,8 @@
new unwindstack::DexFiles(fd_mem)))
#endif
{
- PERFETTO_DCHECK(maps.Parse());
+ bool parsed = maps.Parse();
+ PERFETTO_DCHECK(parsed);
}
void ReparseMaps() {
reparses++;
diff --git a/src/profiling/memory/unwinding_unittest.cc b/src/profiling/memory/unwinding_unittest.cc
index a3c45db..b52a7ce 100644
--- a/src/profiling/memory/unwinding_unittest.cc
+++ b/src/profiling/memory/unwinding_unittest.cc
@@ -68,11 +68,27 @@
ASSERT_EQ(map_info->name, "[stack]");
}
+void __attribute__((noinline)) AssertFunctionOffset() {
+ constexpr auto kMaxFunctionSize = 1000u;
+ // Need to zero-initialize to make MSAN happy. MSAN does not see the writes
+ // from AsmGetRegs (as it is in assembly) and complains otherwise.
+ char reg_data[kMaxRegisterDataSize] = {};
+ unwindstack::AsmGetRegs(reg_data);
+ auto regs = CreateRegsFromRawData(unwindstack::Regs::CurrentArch(), reg_data);
+ ASSERT_GT(regs->pc(), reinterpret_cast<uint64_t>(&AssertFunctionOffset));
+ ASSERT_LT(regs->pc() - reinterpret_cast<uint64_t>(&AssertFunctionOffset),
+ kMaxFunctionSize);
+}
+
+TEST(UnwindingTest, TestFunctionOffset) {
+ AssertFunctionOffset();
+}
+
// This is needed because ASAN thinks copying the whole stack is a buffer
// underrun.
void __attribute__((noinline))
UnsafeMemcpy(void* dst, const void* src, size_t n)
- __attribute__((no_sanitize("address", "hwaddress"))) {
+ __attribute__((no_sanitize("address", "hwaddress", "memory"))) {
const uint8_t* from = reinterpret_cast<const uint8_t*>(src);
uint8_t* to = reinterpret_cast<uint8_t*>(dst);
for (size_t i = 0; i < n; ++i)
@@ -90,13 +106,16 @@
const char* stackbase = GetThreadStackBase();
const char* stacktop = reinterpret_cast<char*>(__builtin_frame_address(0));
+ // Need to zero-initialize to make MSAN happy. MSAN does not see the writes
+ // from AsmGetRegs (as it is in assembly) and complains otherwise.
+ memset(metadata->register_data, 0, sizeof(metadata->register_data));
unwindstack::AsmGetRegs(metadata->register_data);
if (stackbase < stacktop) {
PERFETTO_FATAL("Stacktop >= stackbase.");
return {nullptr, nullptr};
}
- uint64_t stack_size = static_cast<uint64_t>(stackbase - stacktop);
+ size_t stack_size = static_cast<size_t>(stackbase - stacktop);
metadata->alloc_size = 10;
metadata->alloc_address = 0x10;
@@ -115,14 +134,7 @@
return {std::move(payload), std::move(metadata)};
}
-// TODO(rsavitski): Investigate TSAN unwinding.
-#if defined(THREAD_SANITIZER)
-#define MAYBE_DoUnwind DISABLED_DoUnwind
-#else
-#define MAYBE_DoUnwind DoUnwind
-#endif
-
-TEST(UnwindingTest, MAYBE_DoUnwind) {
+TEST(UnwindingTest, DoUnwind) {
base::ScopedFile proc_maps(base::OpenFile("/proc/self/maps", O_RDONLY));
base::ScopedFile proc_mem(base::OpenFile("/proc/self/mem", O_RDONLY));
GlobalCallstackTrie callsites;
@@ -132,10 +144,35 @@
auto record = GetRecord(&msg);
AllocRecord out;
ASSERT_TRUE(DoUnwind(&msg, &metadata, &out));
+ ASSERT_GT(out.frames.size(), 0u);
int st;
std::unique_ptr<char, base::FreeDeleter> demangled(abi::__cxa_demangle(
out.frames[0].frame.function_name.c_str(), nullptr, nullptr, &st));
- ASSERT_EQ(st, 0);
+ ASSERT_EQ(st, 0) << "mangled: " << demangled.get()
+ << ", frames: " << out.frames.size();
+ ASSERT_STREQ(demangled.get(),
+ "perfetto::profiling::(anonymous "
+ "namespace)::GetRecord(perfetto::profiling::WireMessage*)");
+}
+
+TEST(UnwindingTest, DoUnwindReparse) {
+ base::ScopedFile proc_maps(base::OpenFile("/proc/self/maps", O_RDONLY));
+ base::ScopedFile proc_mem(base::OpenFile("/proc/self/mem", O_RDONLY));
+ GlobalCallstackTrie callsites;
+ UnwindingMetadata metadata(getpid(), std::move(proc_maps),
+ std::move(proc_mem));
+ // Force reparse in DoUnwind.
+ metadata.maps.Reset();
+ WireMessage msg;
+ auto record = GetRecord(&msg);
+ AllocRecord out;
+ ASSERT_TRUE(DoUnwind(&msg, &metadata, &out));
+ ASSERT_GT(out.frames.size(), 0u);
+ int st;
+ std::unique_ptr<char, base::FreeDeleter> demangled(abi::__cxa_demangle(
+ out.frames[0].frame.function_name.c_str(), nullptr, nullptr, &st));
+ ASSERT_EQ(st, 0) << "mangled: " << demangled.get()
+ << ", frames: " << out.frames.size();
ASSERT_STREQ(demangled.get(),
"perfetto::profiling::(anonymous "
"namespace)::GetRecord(perfetto::profiling::WireMessage*)");
diff --git a/src/profiling/memory/wire_protocol.cc b/src/profiling/memory/wire_protocol.cc
index 6209fc8..6d561c3 100644
--- a/src/profiling/memory/wire_protocol.cc
+++ b/src/profiling/memory/wire_protocol.cc
@@ -87,7 +87,7 @@
errno = EAGAIN;
return false;
}
- buf = shmem->BeginWrite(lock, total_size);
+ buf = shmem->BeginWrite(lock, static_cast<size_t>(total_size));
}
if (!buf) {
PERFETTO_DLOG("Buffer overflow.");
diff --git a/src/profiling/memory/wire_protocol.h b/src/profiling/memory/wire_protocol.h
index 898d2e7..3ca21d9 100644
--- a/src/profiling/memory/wire_protocol.h
+++ b/src/profiling/memory/wire_protocol.h
@@ -22,12 +22,12 @@
#include <inttypes.h>
#include <unwindstack/Elf.h>
-#include <unwindstack/UserArm.h>
-#include <unwindstack/UserArm64.h>
-#include <unwindstack/UserMips.h>
-#include <unwindstack/UserMips64.h>
-#include <unwindstack/UserX86.h>
-#include <unwindstack/UserX86_64.h>
+#include <unwindstack/MachineArm.h>
+#include <unwindstack/MachineArm64.h>
+#include <unwindstack/MachineMips.h>
+#include <unwindstack/MachineMips64.h>
+#include <unwindstack/MachineX86.h>
+#include <unwindstack/MachineX86_64.h>
#include "src/profiling/memory/shared_ring_buffer.h"
@@ -69,12 +69,12 @@
constexpr_max(
constexpr_max(
constexpr_max(
- sizeof(unwindstack::arm_user_regs),
- sizeof(unwindstack::arm64_user_regs)),
- sizeof(unwindstack::x86_user_regs)),
- sizeof(unwindstack::x86_64_user_regs)),
- sizeof(unwindstack::mips_user_regs)),
- sizeof(unwindstack::mips64_user_regs)
+ sizeof(uint32_t) * unwindstack::ARM_REG_LAST,
+ sizeof(uint64_t) * unwindstack::ARM64_REG_LAST),
+ sizeof(uint32_t) * unwindstack::X86_REG_LAST),
+ sizeof(uint64_t) * unwindstack::X86_64_REG_LAST),
+ sizeof(uint32_t) * unwindstack::MIPS_REG_LAST),
+ sizeof(uint64_t) * unwindstack::MIPS64_REG_LAST
);
// clang-format on
diff --git a/src/protozero/protoc_plugin/BUILD.gn b/src/protozero/protoc_plugin/BUILD.gn
index 9cec6b8..432abd8 100644
--- a/src/protozero/protoc_plugin/BUILD.gn
+++ b/src/protozero/protoc_plugin/BUILD.gn
@@ -21,5 +21,6 @@
deps = [
"../../../gn:default_deps",
"../../../gn:protoc_lib",
+ "../../../src/base",
]
}
diff --git a/src/protozero/protoc_plugin/protozero_plugin.cc b/src/protozero/protoc_plugin/protozero_plugin.cc
index 08d985f..c1285bd 100644
--- a/src/protozero/protoc_plugin/protozero_plugin.cc
+++ b/src/protozero/protoc_plugin/protozero_plugin.cc
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <limits>
#include <map>
#include <memory>
#include <set>
@@ -24,7 +25,8 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/stubs/strutil.h>
+
+#include "perfetto/ext/base/string_utils.h"
namespace protozero {
namespace {
@@ -34,14 +36,15 @@
using google::protobuf::EnumValueDescriptor;
using google::protobuf::FieldDescriptor;
using google::protobuf::FileDescriptor;
-using google::protobuf::Split;
-using google::protobuf::StripPrefixString;
-using google::protobuf::StripString;
-using google::protobuf::StripSuffixString;
-using google::protobuf::UpperString;
using google::protobuf::compiler::GeneratorContext;
using google::protobuf::io::Printer;
using google::protobuf::io::ZeroCopyOutputStream;
+using perfetto::base::SplitString;
+using perfetto::base::StripChars;
+using perfetto::base::StripPrefix;
+using perfetto::base::StripSuffix;
+using perfetto::base::ToUpper;
+using perfetto::base::Uppercase;
// Keep this value in sync with ProtoDecoder::kMaxDecoderFieldId. If they go out
// of sync pbzero.h files will stop compiling, hitting the at() static_assert.
@@ -78,7 +81,7 @@
};
inline std::string ProtoStubName(const FileDescriptor* proto) {
- return StripSuffixString(proto->name(), ".proto") + ".pbzero";
+ return StripSuffix(proto->name(), ".proto") + ".pbzero";
}
class GeneratorJob {
@@ -120,7 +123,7 @@
template <class T>
inline std::string GetDescriptorName(const T* descriptor) {
if (!package_.empty()) {
- return StripPrefixString(descriptor->full_name(), package_ + ".");
+ return StripPrefix(descriptor->full_name(), package_ + ".");
} else {
return descriptor->full_name();
}
@@ -131,8 +134,7 @@
// prohibited but not recommended in order to avoid name collisions.
template <class T>
inline std::string GetCppClassName(const T* descriptor, bool full = false) {
- std::string name = GetDescriptorName(descriptor);
- StripString(&name, ".", '_');
+ std::string name = StripChars(GetDescriptorName(descriptor), ".", '_');
if (full)
name = full_namespace_prefix_ + name;
return name;
@@ -141,7 +143,7 @@
inline std::string GetFieldNumberConstant(const FieldDescriptor* field) {
std::string name = field->camelcase_name();
if (!name.empty()) {
- name.at(0) = static_cast<char>(toupper(name.at(0)));
+ name.at(0) = Uppercase(name.at(0));
name = "k" + name + "FieldNumber";
} else {
// Protoc allows fields like 'bool _ = 1'.
@@ -322,7 +324,7 @@
void Preprocess() {
// Package name maps to a series of namespaces.
package_ = source_->package();
- namespaces_ = Split(package_, ".");
+ namespaces_ = SplitString(package_, ".");
if (!wrapper_namespace_.empty())
namespaces_.push_back(wrapper_namespace_);
@@ -339,8 +341,8 @@
std::string greeting =
"// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.\n";
std::string guard = package_ + "_" + source_->name() + "_H_";
- UpperString(&guard);
- StripString(&guard, ".-/\\", '_');
+ guard = ToUpper(guard);
+ guard = StripChars(guard, ".-/\\", '_');
stub_h_->Print(
"$greeting$\n"
@@ -827,8 +829,8 @@
stub_cc_printer.Print("// Intentionally empty (crbug.com/998165)\n");
// Parse additional options.
- for (const std::string& option : Split(options, ",")) {
- std::vector<std::string> option_pair = Split(option, "=");
+ for (const std::string& option : SplitString(options, ",")) {
+ std::vector<std::string> option_pair = SplitString(option, "=");
job.SetOption(option_pair[0], option_pair[1]);
}
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 78a6142..952dd65 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -14,6 +14,7 @@
import("../../gn/fuzzer.gni")
import("../../gn/perfetto.gni")
+import("../../gn/perfetto_host_executable.gni")
import("../../gn/test.gni")
import("../../gn/wasm.gni")
@@ -158,8 +159,6 @@
"trace_sorter.h",
"trace_storage.cc",
"trace_storage.h",
- "track_table.cc",
- "track_table.h",
"variadic.h",
"virtual_destructors.cc",
"virtual_track_tracker.cc",
@@ -230,12 +229,11 @@
]
}
-executable("trace_processor_shell") {
- testonly = true # We need this for proto full.
+perfetto_host_executable("trace_processor_shell") {
deps = [
":lib",
"../../gn:default_deps",
- "../../gn:protobuf_full",
+ "../../gn:protoc_lib",
"../base",
"metrics:lib",
]
diff --git a/src/trace_processor/db/column.cc b/src/trace_processor/db/column.cc
index 7fe09bf..1f77d3b 100644
--- a/src/trace_processor/db/column.cc
+++ b/src/trace_processor/db/column.cc
@@ -21,17 +21,34 @@
namespace perfetto {
namespace trace_processor {
+Column::Column(const Column& column,
+ Table* table,
+ uint32_t col_idx,
+ uint32_t row_map_idx)
+ : Column(column.name_,
+ column.type_,
+ table,
+ col_idx,
+ row_map_idx,
+ column.sparse_vector_) {}
+
Column::Column(const char* name,
ColumnType type,
Table* table,
uint32_t col_idx,
- uint32_t row_map_idx)
- : string_pool_(table->string_pool_),
- type_(type),
+ uint32_t row_map_idx,
+ void* sparse_vector)
+ : type_(type),
+ sparse_vector_(sparse_vector),
name_(name),
table_(table),
col_idx_(col_idx),
- row_map_idx_(row_map_idx) {}
+ row_map_idx_(row_map_idx),
+ string_pool_(table->string_pool_) {}
+
+Column Column::IdColumn(Table* table, uint32_t col_idx, uint32_t row_map_idx) {
+ return Column("id", ColumnType::kId, table, col_idx, row_map_idx, nullptr);
+}
void Column::FilterInto(FilterOp op, SqlValue value, RowMap* iv) const {
// Assume op == kEq.
diff --git a/src/trace_processor/db/column.h b/src/trace_processor/db/column.h
index 12ff23c..becab4e 100644
--- a/src/trace_processor/db/column.h
+++ b/src/trace_processor/db/column.h
@@ -59,62 +59,48 @@
// Represents a named, strongly typed list of data.
class Column {
public:
- // Create a nullable uint32 Column.
- // Note: |name| must be a long lived string.
+ template <typename T>
Column(const char* name,
- const SparseVector<uint32_t>* storage,
+ SparseVector<T>* storage,
Table* table,
uint32_t col_idx,
uint32_t row_map_idx)
- : Column(name, ColumnType::kUint32, table, col_idx, row_map_idx) {
- data_.uint32_sv = storage;
- }
-
- // Create a nullable int64 Column.
- // Note: |name| must be a long lived string.
- Column(const char* name,
- const SparseVector<int64_t>* storage,
- Table* table,
- uint32_t col_idx,
- uint32_t row_map_idx)
- : Column(name, ColumnType::kInt64, table, col_idx, row_map_idx) {
- data_.int64_sv = storage;
- }
-
- // Create an nullable string Column.
- // Note: |name| must be a long lived string.
- // TODO(lalitm): investigate changing this to a std::deque instead as
- // StringIds already have the concept of nullability in them.
- Column(const char* name,
- const SparseVector<StringPool::Id>* storage,
- Table* table,
- uint32_t col_idx,
- uint32_t row_map_idx)
- : Column(name, ColumnType::kString, table, col_idx, row_map_idx) {
- data_.string_sv = storage;
- }
+ : Column(name, ToColumnType<T>(), table, col_idx, row_map_idx, storage) {}
// Create a Column has the same name and is backed by the same data as
// |column| but is associated to a different table.
Column(const Column& column,
Table* table,
uint32_t col_idx,
- uint32_t row_map_idx)
- : Column(column.name_, column.type_, table, col_idx, row_map_idx) {
- data_ = column.data_;
- }
+ uint32_t row_map_idx);
+ // Columns are movable but not copyable.
Column(Column&&) noexcept = default;
Column& operator=(Column&&) = default;
// Creates a Column which returns the index as the value of the row.
- static Column IdColumn(Table* table, uint32_t col_idx, uint32_t row_map_idx) {
- return Column("id", ColumnType::kId, table, col_idx, row_map_idx);
- }
+ static Column IdColumn(Table* table, uint32_t col_idx, uint32_t row_map_idx);
// Gets the value of the Column at the given |row|.
- // See the bottom of this header for the definition of this function.
- SqlValue Get(uint32_t row) const;
+ SqlValue Get(uint32_t row) const {
+ switch (type_) {
+ case ColumnType::kUint32: {
+ auto opt_value = GetTyped<uint32_t>(row);
+ return opt_value ? SqlValue::Long(*opt_value) : SqlValue();
+ }
+ case ColumnType::kInt64: {
+ auto opt_value = GetTyped<int64_t>(row);
+ return opt_value ? SqlValue::Long(*opt_value) : SqlValue();
+ }
+ case ColumnType::kString: {
+ auto str = GetStringPoolString(row).c_str();
+ return str == nullptr ? SqlValue() : SqlValue::String(str);
+ }
+ case ColumnType::kId:
+ return SqlValue::Long(row_map().Get(row));
+ }
+ PERFETTO_FATAL("For GCC");
+ }
// Returns the row containing the given value in the Column.
base::Optional<uint32_t> IndexOf(SqlValue value) const {
@@ -144,6 +130,20 @@
// given filter constraint.
void FilterInto(FilterOp, SqlValue value, RowMap*) const;
+ const RowMap& row_map() const;
+ const char* name() const { return name_; }
+ SqlValue::Type type() const {
+ switch (type_) {
+ case ColumnType::kUint32:
+ case ColumnType::kInt64:
+ case ColumnType::kId:
+ return SqlValue::Type::kLong;
+ case ColumnType::kString:
+ return SqlValue::Type::kString;
+ }
+ PERFETTO_FATAL("For GCC");
+ }
+
// Returns a Constraint for each type of filter operation for this Column.
Constraint eq(SqlValue value) const {
return Constraint{col_idx_, FilterOp::kEq, value};
@@ -162,21 +162,6 @@
// Returns the JoinKey for this Column.
JoinKey join_key() const { return JoinKey{col_idx_}; }
- const RowMap& row_map() const;
- const char* name() const { return name_; }
-
- SqlValue::Type type() const {
- switch (type_) {
- case ColumnType::kUint32:
- case ColumnType::kInt64:
- case ColumnType::kId:
- return SqlValue::Type::kLong;
- case ColumnType::kString:
- return SqlValue::Type::kString;
- }
- PERFETTO_FATAL("For GCC");
- }
-
protected:
enum ColumnType {
// Standard primitive types.
@@ -188,25 +173,27 @@
kId,
};
- // See the bottom of this header file for the explicit instantiations of these
- // function.
template <typename T>
- base::Optional<T> GetTyped(uint32_t row) const;
- NullTermStringView GetString(uint32_t row) const;
+ base::Optional<T> GetTyped(uint32_t row) const {
+ PERFETTO_DCHECK(ToColumnType<T>() == type_);
+ auto idx = row_map().Get(row);
+ return static_cast<const SparseVector<T>*>(sparse_vector_)->Get(idx);
+ }
- const StringPool* string_pool_ = nullptr;
+ template <typename T>
+ void SetTyped(uint32_t row, T value) {
+ PERFETTO_DCHECK(ToColumnType<T>() == type_);
+ auto idx = row_map().Get(row);
+ return static_cast<SparseVector<T>*>(sparse_vector_)->Set(idx, value);
+ }
+ NullTermStringView GetStringPoolString(uint32_t row) const {
+ return string_pool_->Get(*GetTyped<StringPool::Id>(row));
+ }
+
+ // type_ is used to cast sparse_vector_ to the correct type.
ColumnType type_ = ColumnType::kInt64;
- union {
- // Valid when |type_| == ColumnType::kUint32.
- const SparseVector<uint32_t>* uint32_sv;
-
- // Valid when |type_| == ColumnType::kInt64.
- const SparseVector<int64_t>* int64_sv = nullptr;
-
- // Valid when |type_| == ColumnType::kString.
- const SparseVector<StringPool::Id>* string_sv;
- } data_;
+ void* sparse_vector_ = nullptr;
private:
friend class Table;
@@ -215,74 +202,32 @@
ColumnType type,
Table* table,
uint32_t col_idx,
- uint32_t row_map_idx);
+ uint32_t row_map_idx,
+ void* sparse_vector);
Column(const Column&) = delete;
Column& operator=(const Column&) = delete;
+ template <typename T>
+ static ColumnType ToColumnType() {
+ if (std::is_same<T, uint32_t>::value) {
+ return ColumnType::kUint32;
+ } else if (std::is_same<T, int64_t>::value) {
+ return ColumnType::kInt64;
+ } else if (std::is_same<T, StringPool::Id>::value) {
+ return ColumnType::kString;
+ } else {
+ PERFETTO_FATAL("Unsupported type of column");
+ }
+ }
+
const char* name_ = nullptr;
const Table* table_ = nullptr;
uint32_t col_idx_ = 0;
uint32_t row_map_idx_ = 0;
+ const StringPool* string_pool_ = nullptr;
};
-// The below Get* functions need to be defined out of line as GCC does not
-// allow explicit specialisation inside a class scope.
-template <>
-inline base::Optional<uint32_t> Column::GetTyped<uint32_t>(uint32_t row) const {
- PERFETTO_DCHECK(type_ == ColumnType::kUint32);
- auto idx = row_map().Get(row);
- return data_.uint32_sv->Get(idx);
-}
-
-template <>
-inline base::Optional<int64_t> Column::GetTyped<int64_t>(uint32_t row) const {
- PERFETTO_DCHECK(type_ == ColumnType::kInt64);
- auto idx = row_map().Get(row);
- return data_.int64_sv->Get(idx);
-}
-
-template <>
-inline base::Optional<StringPool::Id> Column::GetTyped<StringPool::Id>(
- uint32_t row) const {
- PERFETTO_DCHECK(type_ == ColumnType::kString);
- auto idx = row_map().Get(row);
- return data_.string_sv->Get(idx);
-}
-
-inline NullTermStringView Column::GetString(uint32_t row) const {
- auto opt_id = GetTyped<StringPool::Id>(row);
- // We DCHECK here because although we are using SparseVector, the null
- // info is handled by the StringPool rather than by the SparseVector.
- // The value returned by the SparseVector should always be non-null.
- // TODO(lalitm): investigate removing this check if/when we support
- // std::deque<StringId>.
- PERFETTO_DCHECK(opt_id.has_value());
- return string_pool_->Get(*opt_id);
-}
-
-// This function needs to be defined out of line as it relies on the explicit
-// specialisations defined above (which are themselves out of line).
-inline SqlValue Column::Get(uint32_t row) const {
- switch (type_) {
- case ColumnType::kUint32: {
- auto opt_value = GetTyped<uint32_t>(row);
- return opt_value ? SqlValue::Long(*opt_value) : SqlValue();
- }
- case ColumnType::kInt64: {
- auto opt_value = GetTyped<int64_t>(row);
- return opt_value ? SqlValue::Long(*opt_value) : SqlValue();
- }
- case ColumnType::kString: {
- auto str = GetString(row).c_str();
- return str == nullptr ? SqlValue() : SqlValue::String(str);
- }
- case ColumnType::kId:
- return SqlValue::Long(row_map().Get(row));
- }
- PERFETTO_FATAL("For GCC");
-}
-
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/db/table.cc b/src/trace_processor/db/table.cc
index beb73e5..1bafb4f 100644
--- a/src/trace_processor/db/table.cc
+++ b/src/trace_processor/db/table.cc
@@ -19,7 +19,7 @@
namespace perfetto {
namespace trace_processor {
-Table::Table(const StringPool* pool, const Table* parent) : string_pool_(pool) {
+Table::Table(StringPool* pool, const Table* parent) : string_pool_(pool) {
if (!parent)
return;
@@ -32,19 +32,23 @@
}
Table& Table::operator=(const Table& other) {
+ size_ = other.size_;
+ string_pool_ = other.string_pool_;
+
for (const RowMap& rm : other.row_maps_) {
row_maps_.emplace_back(rm.Copy());
}
- size_ = other.size_;
for (const Column& col : other.columns_)
columns_.emplace_back(col, this, columns_.size(), col.row_map_idx_);
return *this;
}
Table& Table::operator=(Table&& other) noexcept {
+ size_ = other.size_;
+ string_pool_ = other.string_pool_;
+
row_maps_ = std::move(other.row_maps_);
columns_ = std::move(other.columns_);
- size_ = other.size_;
for (Column& col : columns_) {
col.table_ = this;
}
diff --git a/src/trace_processor/db/table.h b/src/trace_processor/db/table.h
index 66eb856..51ad822 100644
--- a/src/trace_processor/db/table.h
+++ b/src/trace_processor/db/table.h
@@ -104,12 +104,14 @@
const std::vector<RowMap>& row_maps() const { return row_maps_; }
protected:
- Table(const StringPool* pool, const Table* parent);
+ Table(StringPool* pool, const Table* parent);
std::vector<RowMap> row_maps_;
std::vector<Column> columns_;
uint32_t size_ = 0;
+ StringPool* string_pool_ = nullptr;
+
private:
friend class Column;
@@ -117,8 +119,6 @@
// the Table pointer in each column to the Table being copied into.
Table(const Table& other) { *this = other; }
Table& operator=(const Table& other);
-
- const StringPool* string_pool_ = nullptr;
};
} // namespace trace_processor
diff --git a/src/trace_processor/db/typed_column.h b/src/trace_processor/db/typed_column.h
index 57b4995..d07d034 100644
--- a/src/trace_processor/db/typed_column.h
+++ b/src/trace_processor/db/typed_column.h
@@ -33,6 +33,7 @@
using StoredType = T;
T operator[](uint32_t row) const { return *GetTyped<T>(row); }
+ void Set(uint32_t row, T value) { SetTyped(row, value); }
};
template <typename T>
@@ -40,13 +41,20 @@
using StoredType = T;
base::Optional<T> operator[](uint32_t row) const { return GetTyped<T>(row); }
+ void Set(uint32_t row, T value) { SetTyped(row, value); }
};
template <>
struct TypedColumn<StringPool::Id> : public Column {
using StoredType = StringPool::Id;
- NullTermStringView operator[](uint32_t row) const { return GetString(row); }
+ StringPool::Id operator[](uint32_t row) const {
+ return *GetTyped<StringPool::Id>(row);
+ }
+ NullTermStringView GetString(uint32_t row) const {
+ return GetStringPoolString(row);
+ }
+ void Set(uint32_t row, StringPool::Id value) { SetTyped(row, value); }
};
} // namespace trace_processor
diff --git a/src/trace_processor/export_json.cc b/src/trace_processor/export_json.cc
index adb73f5..28dffb6 100644
--- a/src/trace_processor/export_json.cc
+++ b/src/trace_processor/export_json.cc
@@ -20,6 +20,7 @@
#include <json/writer.h>
#include <stdio.h>
#include <cstring>
+#include <vector>
#include "perfetto/ext/base/string_splitter.h"
#include "src/trace_processor/export_json.h"
@@ -599,6 +600,76 @@
return kResultOk;
}
+ResultCode ExportCpuProfileSamples(const TraceStorage* storage,
+ TraceFormatWriter* writer) {
+ const TraceStorage::CpuProfileStackSamples& samples =
+ storage->cpu_profile_stack_samples();
+ for (uint32_t i = 0; i < samples.size(); ++i) {
+ Json::Value event;
+ event["ts"] = Json::Int64(samples.timestamps()[i] / 1000);
+
+ UniqueTid utid = static_cast<UniqueTid>(samples.utids()[i]);
+ auto thread = storage->GetThread(utid);
+ event["tid"] = thread.tid;
+ if (thread.upid)
+ event["pid"] = storage->GetProcess(*thread.upid).pid;
+
+ event["ph"] = "I";
+ event["cat"] = "disabled_by_default-cpu_profiler";
+ event["name"] = "StackCpuSampling";
+ event["scope"] = "t";
+
+ std::vector<std::string> callstack;
+ const TraceStorage::StackProfileCallsites& callsites =
+ storage->stack_profile_callsites();
+ int64_t maybe_callsite_id = samples.callsite_ids()[i];
+ PERFETTO_DCHECK(maybe_callsite_id >= 0 &&
+ maybe_callsite_id < callsites.size());
+ while (maybe_callsite_id >= 0) {
+ size_t callsite_id = static_cast<size_t>(maybe_callsite_id);
+
+ const TraceStorage::StackProfileFrames& frames =
+ storage->stack_profile_frames();
+ PERFETTO_DCHECK(callsites.frame_ids()[callsite_id] >= 0 &&
+ callsites.frame_ids()[callsite_id] < frames.size());
+ size_t frame_id = static_cast<size_t>(callsites.frame_ids()[callsite_id]);
+
+ const TraceStorage::StackProfileMappings& mappings =
+ storage->stack_profile_mappings();
+ PERFETTO_DCHECK(frames.mappings()[frame_id] >= 0 &&
+ frames.mappings()[frame_id] < mappings.size());
+ size_t mapping_id = static_cast<size_t>(frames.mappings()[frame_id]);
+
+ NullTermStringView symbol_name =
+ storage->GetString(frames.names()[frame_id]);
+
+ char frame_entry[1024];
+ snprintf(
+ frame_entry, sizeof(frame_entry), "%s - %s [%s]\n",
+ (symbol_name.empty()
+ ? PrintUint64(static_cast<uint64_t>(frames.rel_pcs()[frame_id]))
+ .c_str()
+ : symbol_name.c_str()),
+ storage->GetString(mappings.names()[mapping_id]).c_str(),
+ storage->GetString(mappings.build_ids()[mapping_id]).c_str());
+
+ callstack.emplace_back(frame_entry);
+
+ maybe_callsite_id = callsites.parent_callsite_ids()[callsite_id];
+ }
+
+ std::string merged_callstack;
+ for (auto entry = callstack.rbegin(); entry != callstack.rend(); ++entry) {
+ merged_callstack += *entry;
+ }
+
+ event["args"]["frames"] = merged_callstack;
+ writer->WriteCommonEvent(event);
+ }
+
+ return kResultOk;
+}
+
ResultCode ExportMetadata(const TraceStorage* storage,
TraceFormatWriter* writer) {
const auto& trace_metadata = storage->metadata();
@@ -758,6 +829,10 @@
if (code != kResultOk)
return code;
+ code = ExportCpuProfileSamples(storage, &writer);
+ if (code != kResultOk)
+ return code;
+
code = ExportMetadata(storage, &writer);
if (code != kResultOk)
return code;
diff --git a/src/trace_processor/export_json_unittest.cc b/src/trace_processor/export_json_unittest.cc
index ea04091..c4cac83 100644
--- a/src/trace_processor/export_json_unittest.cc
+++ b/src/trace_processor/export_json_unittest.cc
@@ -637,7 +637,8 @@
UniquePid upid = storage.AddEmptyProcess(kProcessID);
StringId cat_id = storage.InternString(base::StringView(kCategory));
StringId name_id = storage.InternString(base::StringView(kName));
- TrackId track_id = storage.mutable_tracks()->AddTrack(name_id);
+ TrackId track_id =
+ storage.mutable_track_table()->Insert(tables::TrackTable::Row(name_id));
storage.mutable_virtual_tracks()->AddVirtualTrack(
track_id, VirtualTrackScope::kProcess, upid);
storage.mutable_nestable_slices()->AddSlice(kTimestamp, kDuration, track_id,
@@ -698,7 +699,8 @@
UniquePid upid = storage.AddEmptyProcess(kProcessID);
StringId cat_id = storage.InternString(base::StringView(kCategory));
StringId name_id = storage.InternString(base::StringView(kName));
- TrackId track_id = storage.mutable_tracks()->AddTrack(name_id);
+ TrackId track_id =
+ storage.mutable_track_table()->Insert(tables::TrackTable::Row(name_id));
storage.mutable_virtual_tracks()->AddVirtualTrack(
track_id, VirtualTrackScope::kProcess, upid);
auto slice_id = storage.mutable_nestable_slices()->AddSlice(
@@ -753,7 +755,8 @@
UniquePid upid = storage.AddEmptyProcess(kProcessID);
StringId cat_id = storage.InternString(base::StringView(kCategory));
StringId name_id = storage.InternString(base::StringView(kName));
- TrackId track_id = storage.mutable_tracks()->AddTrack(name_id);
+ TrackId track_id =
+ storage.mutable_track_table()->Insert(tables::TrackTable::Row(name_id));
storage.mutable_virtual_tracks()->AddVirtualTrack(
track_id, VirtualTrackScope::kProcess, upid);
auto slice_id = storage.mutable_nestable_slices()->AddSlice(
@@ -796,7 +799,8 @@
UniquePid upid = storage.AddEmptyProcess(kProcessID);
StringId cat_id = storage.InternString(base::StringView(kCategory));
StringId name_id = storage.InternString(base::StringView(kName));
- TrackId track_id = storage.mutable_tracks()->AddTrack(name_id);
+ TrackId track_id =
+ storage.mutable_track_table()->Insert(tables::TrackTable::Row(name_id));
storage.mutable_virtual_tracks()->AddVirtualTrack(
track_id, VirtualTrackScope::kProcess, upid);
storage.mutable_nestable_slices()->AddSlice(
@@ -967,6 +971,67 @@
EXPECT_EQ(result["systemTraceEvents"].asString(), kLegacyFtraceData);
}
+TEST(ExportJsonTest, CpuProfileEvent) {
+ const int64_t kProcessID = 100;
+ const int64_t kThreadID = 200;
+ const int64_t kTimestamp = 10000000;
+
+ TraceProcessorContext context;
+ context.storage.reset(new TraceStorage());
+ TraceStorage* storage = context.storage.get();
+
+ UniquePid upid = storage->AddEmptyProcess(kProcessID);
+ UniqueTid utid = storage->AddEmptyThread(kThreadID);
+ storage->GetMutableThread(utid)->upid = upid;
+
+ RowId module_row_id_1 = storage->mutable_stack_profile_mappings()->Insert(
+ {storage->InternString("foo_module_id"), 0, 0, 0, 0, 0,
+ storage->InternString("foo_module_name")});
+
+ RowId module_row_id_2 = storage->mutable_stack_profile_mappings()->Insert(
+ {storage->InternString("bar_module_id"), 0, 0, 0, 0, 0,
+ storage->InternString("bar_module_name")});
+
+ RowId frame_row_id_1 = storage->mutable_stack_profile_frames()->Insert(
+ {storage->InternString("foo_func"), module_row_id_1, 0x42});
+
+ RowId frame_row_id_2 = storage->mutable_stack_profile_frames()->Insert(
+ {storage->InternString("bar_func"), module_row_id_2, 0x4242});
+
+ RowId frame_callsite_id_1 =
+ storage->mutable_stack_profile_callsites()->Insert(
+ {0, -1, frame_row_id_1});
+
+ RowId frame_callsite_id_2 =
+ storage->mutable_stack_profile_callsites()->Insert(
+ {1, frame_callsite_id_1, frame_row_id_2});
+
+ storage->mutable_cpu_profile_stack_samples()->Insert(
+ {kTimestamp, frame_callsite_id_2, utid});
+
+ base::TempFile temp_file = base::TempFile::Create();
+ FILE* output = fopen(temp_file.path().c_str(), "w+");
+ int code = ExportJson(storage, output);
+
+ EXPECT_EQ(code, kResultOk);
+
+ Json::Reader reader;
+ Json::Value result;
+ EXPECT_TRUE(reader.parse(ReadFile(output), result));
+
+ EXPECT_EQ(result["traceEvents"].size(), 1u);
+ Json::Value event = result["traceEvents"][0];
+ EXPECT_EQ(event["ph"].asString(), "I");
+ EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
+ EXPECT_EQ(event["tid"].asUInt(), kThreadID);
+ EXPECT_EQ(event["cat"].asString(), "disabled_by_default-cpu_profiler");
+ EXPECT_EQ(event["name"].asString(), "StackCpuSampling");
+ EXPECT_EQ(event["scope"].asString(), "t");
+ EXPECT_EQ(event["args"]["frames"].asString(),
+ "foo_func - foo_module_name [foo_module_id]\nbar_func - "
+ "bar_module_name [bar_module_id]\n");
+}
+
} // namespace
} // namespace json
} // namespace trace_processor
diff --git a/src/trace_processor/filtered_row_index.h b/src/trace_processor/filtered_row_index.h
index d8dcaeb..c17fc56 100644
--- a/src/trace_processor/filtered_row_index.h
+++ b/src/trace_processor/filtered_row_index.h
@@ -122,16 +122,14 @@
template <typename Predicate>
void FilterRowVector(Predicate fn) {
- size_t rows_size = rows_.size();
- for (size_t i = 0; i < rows_size;) {
- if (fn(rows_[i])) {
- i++;
- } else {
- std::swap(rows_[i], rows_[rows_size - 1]);
- rows_size--;
+ size_t write_idx = 0;
+ for (size_t read_idx = 0; read_idx < rows_.size(); ++read_idx) {
+ uint32_t row = rows_[read_idx];
+ if (fn(row)) {
+ rows_[write_idx++] = row;
}
}
- rows_.resize(rows_size);
+ rows_.resize(write_idx);
}
void ConvertBitVectorToRowVector();
diff --git a/src/trace_processor/ftrace_descriptors.cc b/src/trace_processor/ftrace_descriptors.cc
index bad9305..4540df1 100644
--- a/src/trace_processor/ftrace_descriptors.cc
+++ b/src/trace_processor/ftrace_descriptors.cc
@@ -8,7 +8,7 @@
namespace trace_processor {
namespace {
-std::array<MessageDescriptor, 336> descriptors{{
+std::array<MessageDescriptor, 333> descriptors{{
{nullptr, 0, {}},
{nullptr, 0, {}},
{nullptr, 0, {}},
@@ -3537,41 +3537,6 @@
{"state", ProtoSchemaType::kUint32},
},
},
- {
- "gpu_sched_enqueue",
- 4,
- {
- {},
- {"ctx_id", ProtoSchemaType::kUint32},
- {"job_id", ProtoSchemaType::kUint32},
- {"priority", ProtoSchemaType::kUint32},
- {"submission_id", ProtoSchemaType::kUint32},
- },
- },
- {
- "gpu_sched_submit",
- 5,
- {
- {},
- {"ctx_id", ProtoSchemaType::kUint32},
- {"hwqueue_id", ProtoSchemaType::kUint32},
- {"job_id", ProtoSchemaType::kUint32},
- {"priority", ProtoSchemaType::kUint32},
- {"submission_id", ProtoSchemaType::kUint32},
- },
- },
- {
- "gpu_sched_complete",
- 5,
- {
- {},
- {"ctx_id", ProtoSchemaType::kUint32},
- {"job_id", ProtoSchemaType::kUint32},
- {"msg", ProtoSchemaType::kString},
- {"priority", ProtoSchemaType::kUint32},
- {"submission_id", ProtoSchemaType::kUint32},
- },
- },
}};
} // namespace
diff --git a/src/trace_processor/graphics_frame_event_parser.cc b/src/trace_processor/graphics_frame_event_parser.cc
index e5f0649..6913771 100644
--- a/src/trace_processor/graphics_frame_event_parser.cc
+++ b/src/trace_processor/graphics_frame_event_parser.cc
@@ -127,7 +127,7 @@
track_name_id);
context_->storage->mutable_gpu_track_table()->Insert(
- track_id, graphics_event_scope_id_, base::nullopt /* context */);
+ tables::GpuTrackTable::Row(track_id, graphics_event_scope_id_));
const auto slice_id = context_->slice_tracker->Scoped(
timestamp, track_id, RefType::kRefTrack, 0 /* cat */, event_name_id,
@@ -137,10 +137,10 @@
});
if (slice_id) {
- context_->storage->mutable_gpu_slice_table()->Insert(
- slice_id.value(), base::nullopt /* context_id */,
- base::nullopt /* render_target */, frame_number,
- base::nullopt /* job_id */, base::nullopt /* hw_queue_id */);
+ tables::GpuSliceTable::Row row;
+ row.slice_id = slice_id.value();
+ row.frame_id = frame_number;
+ context_->storage->mutable_gpu_slice_table()->Insert(row);
}
}
diff --git a/src/trace_processor/metrics/android/android_cpu.sql b/src/trace_processor/metrics/android/android_cpu.sql
index 91f754c..ef6dc82 100644
--- a/src/trace_processor/metrics/android/android_cpu.sql
+++ b/src/trace_processor/metrics/android/android_cpu.sql
@@ -20,6 +20,7 @@
CREATE VIEW cpu_breakdown_per_utid AS
SELECT
utid,
+ CAST(SUM(dur * freq / 1000000) AS INT) AS normalized_cpu_cycles,
AndroidCpuMetric_CpuFrequencyData(
'id', cpu,
'avg_freq_khz', CAST((SUM(dur * freq) / SUM(dur)) AS INT),
@@ -38,6 +39,7 @@
upid,
thread.name AS thread_name,
process.name AS process_name,
+ CAST(SUM(normalized_cpu_cycles) AS INT) AS normalized_cpu_cycles,
RepeatedField(cpu_freq_proto) AS thread_proto_cpu
FROM thread
JOIN process USING (upid)
@@ -50,10 +52,12 @@
SELECT
upid,
process_name,
+ CAST(SUM(normalized_cpu_cycles) AS INT) AS normalized_cpu_cycles,
RepeatedField(
AndroidCpuMetric_Thread(
'name', CAST(thread_name as TEXT),
- 'cpu', thread_proto_cpu
+ 'cpu', thread_proto_cpu,
+ 'normalized_cpu_cycles', CAST(normalized_cpu_cycles as INT)
)
) AS thread_proto
FROM agg_by_thread
@@ -64,7 +68,8 @@
SELECT
AndroidCpuMetric_Process(
'name', process_name,
- 'threads', thread_proto
+ 'threads', thread_proto,
+ 'normalized_cpu_cycles', CAST(normalized_cpu_cycles AS INT)
) AS cpu_info_process
FROM agg_by_process
GROUP BY upid;
diff --git a/src/trace_processor/metrics/metrics.descriptor.h b/src/trace_processor/metrics/metrics.descriptor.h
index 8a5334e..bc84af0 100644
--- a/src/trace_processor/metrics/metrics.descriptor.h
+++ b/src/trace_processor/metrics/metrics.descriptor.h
@@ -19,7 +19,7 @@
namespace perfetto {
-constexpr std::array<uint8_t, 9039> kMetricsDescriptor{
+constexpr std::array<uint8_t, 9145> kMetricsDescriptor{
{0x0a, 0x98, 0x03, 0x0a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
@@ -54,13 +54,13 @@
0x0e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x76, 0x67,
0x5f, 0x75, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x63,
0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x41, 0x76, 0x67, 0x55, 0x61, 0x42,
- 0x02, 0x48, 0x03, 0x0a, 0x9d, 0x04, 0x0a, 0x30, 0x70, 0x72, 0x6f, 0x74,
+ 0x02, 0x48, 0x03, 0x0a, 0x87, 0x05, 0x0a, 0x30, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
0x6f, 0x69, 0x64, 0x2f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x74, 0x72,
0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65,
0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x22, 0xd3, 0x03, 0x0a, 0x10, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x73, 0x22, 0xbd, 0x04, 0x0a, 0x10, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x4c,
0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x6e,
0x66, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70,
@@ -82,698 +82,707 @@
0x0a, 0x61, 0x76, 0x67, 0x46, 0x72, 0x65, 0x71, 0x4b, 0x68, 0x7a, 0x12,
0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75,
- 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x73, 0x1a, 0x62, 0x0a, 0x06,
- 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x12, 0x44, 0x0a, 0x03, 0x63, 0x70, 0x75, 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, 0x41, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x2e, 0x43, 0x70, 0x75, 0x46, 0x72, 0x65, 0x71, 0x75, 0x65,
- 0x6e, 0x63, 0x79, 0x44, 0x61, 0x74, 0x61, 0x52, 0x03, 0x63, 0x70, 0x75,
- 0x1a, 0x61, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12,
- 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x42, 0x0a, 0x07, 0x74,
- 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
- 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x52, 0x07, 0x74, 0x68, 0x72, 0x65,
- 0x61, 0x64, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x93, 0x08, 0x0a, 0x30,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
- 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f,
- 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xc9, 0x07, 0x0a, 0x13, 0x41, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x5c, 0x0a, 0x0f, 0x70, 0x72, 0x6f,
- 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x65, 0x72,
+ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x73, 0x1a, 0x96, 0x01, 0x0a,
+ 0x06, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e,
+ 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
+ 0x61, 0x6d, 0x65, 0x12, 0x44, 0x0a, 0x03, 0x63, 0x70, 0x75, 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, 0x41,
+ 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x2e, 0x43, 0x70, 0x75, 0x46, 0x72, 0x65, 0x71, 0x75,
+ 0x65, 0x6e, 0x63, 0x79, 0x44, 0x61, 0x74, 0x61, 0x52, 0x03, 0x63, 0x70,
+ 0x75, 0x12, 0x32, 0x0a, 0x15, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69,
+ 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x63, 0x79, 0x63, 0x6c,
+ 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x6e, 0x6f,
+ 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x70, 0x75, 0x43,
+ 0x79, 0x63, 0x6c, 0x65, 0x73, 0x1a, 0x95, 0x01, 0x0a, 0x07, 0x50, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x12, 0x42, 0x0a, 0x07, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73,
+ 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72,
0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f,
- 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f,
- 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52,
- 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x1a, 0xfd, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x63,
- 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x21,
- 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61,
- 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72,
- 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x61, 0x0a,
- 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
- 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e,
+ 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64,
+ 0x52, 0x07, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x12, 0x32, 0x0a,
+ 0x15, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f,
+ 0x63, 0x70, 0x75, 0x5f, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c,
+ 0x69, 0x7a, 0x65, 0x64, 0x43, 0x70, 0x75, 0x43, 0x79, 0x63, 0x6c, 0x65,
+ 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x93, 0x08, 0x0a, 0x30, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d,
- 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
- 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72,
- 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0d, 0x74,
- 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73,
- 0x12, 0x65, 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79,
- 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x03,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x6f, 0x73, 0x22, 0xc9, 0x07, 0x0a, 0x13, 0x41, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x12, 0x5c, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65,
+ 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x01,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
- 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x69, 0x6f, 0x72,
- 0x69, 0x74, 0x79, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e,
- 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x72,
- 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x1a, 0x87, 0x01, 0x0a, 0x11,
- 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x72, 0x65, 0x61,
- 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69,
- 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x56, 0x0a,
- 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
- 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74,
- 0x65, 0x72, 0x73, 0x52, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
- 0x73, 0x1a, 0x88, 0x03, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
- 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74,
- 0x65, 0x72, 0x73, 0x12, 0x47, 0x0a, 0x08, 0x61, 0x6e, 0x6f, 0x6e, 0x5f,
- 0x72, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e,
- 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d,
- 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
- 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x61, 0x6e, 0x6f,
- 0x6e, 0x52, 0x73, 0x73, 0x12, 0x47, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65,
- 0x5f, 0x72, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c,
- 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69,
- 0x6c, 0x65, 0x52, 0x73, 0x73, 0x12, 0x40, 0x0a, 0x04, 0x73, 0x77, 0x61,
- 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65,
+ 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65,
+ 0x73, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x0e, 0x70,
+ 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x1a, 0xfd, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
+ 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x21, 0x0a, 0x0c,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63,
+ 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x61, 0x0a, 0x0e, 0x74,
+ 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
+ 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d,
+ 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43,
+ 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0d, 0x74, 0x6f, 0x74,
+ 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x65,
+ 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x62,
+ 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x03, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74,
+ 0x79, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x11,
+ 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x72, 0x65, 0x61,
+ 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x1a, 0x87, 0x01, 0x0a, 0x11, 0x50, 0x72,
+ 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64,
+ 0x6f, 0x77, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72,
+ 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70,
+ 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x56, 0x0a, 0x08, 0x63,
+ 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d,
+ 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
+ 0x73, 0x52, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x1a,
+ 0x88, 0x03, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d,
+ 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
+ 0x73, 0x12, 0x47, 0x0a, 0x08, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x72, 0x73,
+ 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65,
0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d,
0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f,
- 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x04, 0x73, 0x77, 0x61, 0x70, 0x12,
- 0x50, 0x0a, 0x0d, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f,
- 0x73, 0x77, 0x61, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c,
- 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x0b, 0x61, 0x6e,
- 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x53, 0x77, 0x61, 0x70, 0x12, 0x49, 0x0a,
- 0x09, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x18, 0x05,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
- 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74,
- 0x65, 0x72, 0x52, 0x08, 0x6a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70,
- 0x1a, 0x3f, 0x0a, 0x07, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12,
- 0x10, 0x0a, 0x03, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01,
- 0x52, 0x03, 0x6d, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x78,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x6d, 0x61, 0x78, 0x12,
- 0x10, 0x0a, 0x03, 0x61, 0x76, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01,
- 0x52, 0x03, 0x61, 0x76, 0x67, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xa4, 0x06,
- 0x0a, 0x36, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65,
- 0x6d, 0x5f, 0x75, 0x6e, 0x61, 0x67, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x22, 0xd4, 0x05, 0x0a, 0x1f, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x61, 0x6e, 0x6f, 0x6e, 0x52,
+ 0x73, 0x73, 0x12, 0x47, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x72,
+ 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65,
+ 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43,
+ 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x65,
+ 0x52, 0x73, 0x73, 0x12, 0x40, 0x0a, 0x04, 0x73, 0x77, 0x61, 0x70, 0x18,
+ 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72,
+ 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x6e,
+ 0x74, 0x65, 0x72, 0x52, 0x04, 0x73, 0x77, 0x61, 0x70, 0x12, 0x50, 0x0a,
+ 0x0d, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77,
+ 0x61, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65,
+ 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43,
+ 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x0b, 0x61, 0x6e, 0x6f, 0x6e,
+ 0x41, 0x6e, 0x64, 0x53, 0x77, 0x61, 0x70, 0x12, 0x49, 0x0a, 0x09, 0x6a,
+ 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
+ 0x52, 0x08, 0x6a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x1a, 0x3f,
+ 0x0a, 0x07, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x10, 0x0a,
+ 0x03, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03,
+ 0x6d, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x78, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x6d, 0x61, 0x78, 0x12, 0x10, 0x0a,
+ 0x03, 0x61, 0x76, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03,
+ 0x61, 0x76, 0x67, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xa4, 0x06, 0x0a, 0x36,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
+ 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f,
+ 0x75, 0x6e, 0x61, 0x67, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22,
+ 0xd4, 0x05, 0x0a, 0x1f, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d,
+ 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65,
+ 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12,
+ 0x65, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x76,
+ 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x3e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67,
0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x12, 0x65, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
- 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x3e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61,
- 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x56,
- 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x63, 0x65,
- 0x73, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a, 0x97, 0x01, 0x0a,
- 0x0d, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x56, 0x61, 0x6c, 0x75,
- 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
- 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d,
- 0x65, 0x12, 0x63, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x5f, 0x76, 0x61, 0x6c,
- 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x44, 0x2e,
+ 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x56, 0x61, 0x6c,
+ 0x75, 0x65, 0x73, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a, 0x97, 0x01, 0x0a, 0x0d, 0x50,
+ 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73,
+ 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
+ 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12,
+ 0x63, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
+ 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d,
+ 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61,
+ 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x56,
+ 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x09, 0x6d, 0x65, 0x6d, 0x56, 0x61,
+ 0x6c, 0x75, 0x65, 0x73, 0x1a, 0xe3, 0x02, 0x0a, 0x13, 0x50, 0x72, 0x6f,
+ 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x56, 0x61,
+ 0x6c, 0x75, 0x65, 0x73, 0x12, 0x51, 0x0a, 0x08, 0x61, 0x6e, 0x6f, 0x6e,
+ 0x5f, 0x72, 0x73, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36,
+ 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72,
+ 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x61, 0x6e, 0x6f, 0x6e,
+ 0x52, 0x73, 0x73, 0x12, 0x51, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x5f,
+ 0x72, 0x73, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e,
0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d,
0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65,
0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
- 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72,
- 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x09, 0x6d, 0x65, 0x6d,
- 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a, 0xe3, 0x02, 0x0a, 0x13, 0x50,
- 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
- 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x51, 0x0a, 0x08, 0x61, 0x6e,
- 0x6f, 0x6e, 0x5f, 0x72, 0x73, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67,
- 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x61, 0x6e,
- 0x6f, 0x6e, 0x52, 0x73, 0x73, 0x12, 0x51, 0x0a, 0x08, 0x66, 0x69, 0x6c,
- 0x65, 0x5f, 0x72, 0x73, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67,
- 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x66, 0x69, 0x6c,
- 0x65, 0x52, 0x73, 0x73, 0x12, 0x4a, 0x0a, 0x04, 0x73, 0x77, 0x61, 0x70,
- 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f,
- 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74,
- 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x56, 0x61, 0x6c,
- 0x75, 0x65, 0x52, 0x04, 0x73, 0x77, 0x61, 0x70, 0x12, 0x5a, 0x0a, 0x0d,
- 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61,
- 0x70, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d,
- 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61,
- 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x56, 0x61,
- 0x6c, 0x75, 0x65, 0x52, 0x0b, 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e, 0x64,
- 0x53, 0x77, 0x61, 0x70, 0x1a, 0x4a, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75,
- 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x02, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x6f, 0x6d,
- 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
- 0x52, 0x08, 0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x14,
- 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x02, 0x48, 0x03,
- 0x0a, 0x90, 0x04, 0x0a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
- 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f,
- 0x77, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x22, 0xc2, 0x03, 0x0a, 0x14, 0x41, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f,
- 0x77, 0x74, 0x68, 0x12, 0x60, 0x0a, 0x10, 0x69, 0x6e, 0x73, 0x74, 0x61,
- 0x6e, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18,
- 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x65, 0x52,
+ 0x73, 0x73, 0x12, 0x4a, 0x0a, 0x04, 0x73, 0x77, 0x61, 0x70, 0x18, 0x03,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
+ 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
+ 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64,
+ 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65,
+ 0x52, 0x04, 0x73, 0x77, 0x61, 0x70, 0x12, 0x5a, 0x0a, 0x0d, 0x61, 0x6e,
+ 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x18,
+ 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66,
0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
- 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65,
- 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x73,
- 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x52, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x73, 0x1a, 0xc7, 0x02, 0x0a, 0x0f, 0x49, 0x6e,
- 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x0d, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70,
- 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65,
- 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x19, 0x61, 0x6e,
- 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f,
- 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
- 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x61, 0x6e, 0x6f, 0x6e, 0x41,
- 0x6e, 0x64, 0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x72, 0x74, 0x56,
- 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x61, 0x6e, 0x6f, 0x6e,
- 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x63, 0x68,
- 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e,
- 0x64, 0x53, 0x77, 0x61, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42,
- 0x79, 0x74, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x6d, 0x61, 0x6c, 0x6c,
- 0x6f, 0x63, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x63, 0x68,
- 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04,
- 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63,
- 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65,
- 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x23, 0x6d, 0x61, 0x6c,
- 0x6c, 0x6f, 0x63, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x74,
- 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74,
- 0x65, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x1f, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x4d, 0x65,
- 0x6d, 0x6f, 0x72, 0x79, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c,
- 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42,
- 0x02, 0x48, 0x03, 0x0a, 0xaf, 0x02, 0x0a, 0x30, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
- 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x2f, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x49, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x40,
- 0x0a, 0x06, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x2e, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x52, 0x06, 0x62, 0x75,
- 0x66, 0x66, 0x65, 0x72, 0x1a, 0x8e, 0x01, 0x0a, 0x06, 0x42, 0x75, 0x66,
- 0x66, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
- 0x24, 0x0a, 0x0e, 0x61, 0x76, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f,
- 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52,
- 0x0c, 0x61, 0x76, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65,
- 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x7a,
- 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x01, 0x52, 0x0c, 0x6d, 0x69, 0x6e, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79,
- 0x74, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x73,
- 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20,
- 0x01, 0x28, 0x01, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65,
- 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x95, 0x02,
- 0x0a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d,
- 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xcb, 0x01, 0x0a, 0x10,
- 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61,
- 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x05, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e,
- 0x74, 0x12, 0x4e, 0x0a, 0x0c, 0x62, 0x79, 0x5f, 0x6f, 0x6f, 0x6d, 0x5f,
- 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x42,
- 0x79, 0x4f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x0a, 0x62,
- 0x79, 0x4f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x46, 0x0a,
- 0x0a, 0x42, 0x79, 0x4f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12,
- 0x22, 0x0a, 0x0d, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65,
- 0x5f, 0x61, 0x64, 0x6a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b,
- 0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12,
- 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x02, 0x48,
- 0x03, 0x0a, 0xf4, 0x02, 0x0a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72,
+ 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65,
+ 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x56, 0x61, 0x6c, 0x75,
+ 0x65, 0x52, 0x0b, 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x53, 0x77,
+ 0x61, 0x70, 0x1a, 0x4a, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
+ 0x0e, 0x0a, 0x02, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x02, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x6f, 0x6d, 0x5f, 0x73,
+ 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08,
+ 0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52,
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x90,
+ 0x04, 0x0a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70,
+ 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x77, 0x74,
+ 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x22, 0xc2, 0x03, 0x0a, 0x14, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74,
+ 0x68, 0x12, 0x60, 0x0a, 0x10, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
+ 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x01, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+ 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61,
+ 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x0f,
+ 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x73, 0x1a, 0xc7, 0x02, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x74,
+ 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12,
+ 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
+ 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f,
+ 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+ 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x19, 0x61, 0x6e, 0x6f, 0x6e,
+ 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x73, 0x74,
+ 0x61, 0x72, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x15, 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e, 0x64,
+ 0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x72, 0x74, 0x56, 0x61, 0x6c,
+ 0x75, 0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x61,
+ 0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x63, 0x68, 0x61, 0x6e,
+ 0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x16, 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x53,
+ 0x77, 0x61, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x79, 0x74,
+ 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63,
+ 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x63, 0x68, 0x61, 0x6e,
+ 0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x17, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x4d, 0x65,
+ 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x79,
+ 0x74, 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x23, 0x6d, 0x61, 0x6c, 0x6c, 0x6f,
+ 0x63, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x74, 0x6f, 0x74,
+ 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64,
+ 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x1f, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x4d, 0x65, 0x6d, 0x6f,
+ 0x72, 0x79, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
+ 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x02, 0x48,
+ 0x03, 0x0a, 0xaf, 0x02, 0x0a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x2f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
- 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xa5, 0x02, 0x0a, 0x11, 0x41, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69,
- 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0b, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x5f,
- 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x64, 0x2f, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22,
+ 0xe5, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49,
+ 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x40, 0x0a, 0x06,
+ 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+ 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x52, 0x06, 0x62, 0x75, 0x66, 0x66,
+ 0x65, 0x72, 0x1a, 0x8e, 0x01, 0x0a, 0x06, 0x42, 0x75, 0x66, 0x66, 0x65,
+ 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a,
+ 0x0e, 0x61, 0x76, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79,
+ 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x61,
+ 0x76, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12,
+ 0x24, 0x0a, 0x0e, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f,
+ 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52,
+ 0x0c, 0x6d, 0x69, 0x6e, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65,
+ 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x69, 0x7a,
+ 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
+ 0x01, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79,
+ 0x74, 0x65, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x95, 0x02, 0x0a, 0x30,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
+ 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b, 0x5f,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xcb, 0x01, 0x0a, 0x10, 0x41, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
+ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
+ 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
+ 0x4e, 0x0a, 0x0c, 0x62, 0x79, 0x5f, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63,
+ 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c,
+ 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x42, 0x79, 0x4f,
+ 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x0a, 0x62, 0x79, 0x4f,
+ 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x0a, 0x42,
+ 0x79, 0x4f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x22, 0x0a,
+ 0x0d, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x61,
+ 0x64, 0x6a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6f,
+ 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12, 0x14, 0x0a,
+ 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
+ 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x02, 0x48, 0x03, 0x0a,
+ 0xf4, 0x02, 0x0a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+ 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x22, 0xa5, 0x02, 0x0a, 0x11, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73,
+ 0x12, 0x4e, 0x0a, 0x0b, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x72, 0x61,
+ 0x69, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
+ 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x50, 0x6f,
+ 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0a, 0x70, 0x6f,
+ 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x1a, 0x4e, 0x0a, 0x0a,
+ 0x45, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x21,
+ 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f,
+ 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69,
+ 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x73, 0x12, 0x1d, 0x0a,
+ 0x0a, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x5f, 0x75, 0x77, 0x73, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x65, 0x6e, 0x65, 0x72, 0x67,
+ 0x79, 0x55, 0x77, 0x73, 0x1a, 0x70, 0x0a, 0x0a, 0x50, 0x6f, 0x77, 0x65,
+ 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x0b, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79,
+ 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x2e,
- 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0a,
- 0x70, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x1a, 0x4e,
- 0x0a, 0x0a, 0x45, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61,
- 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
- 0x70, 0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b,
- 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x73, 0x12,
- 0x1d, 0x0a, 0x0a, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x5f, 0x75, 0x77,
- 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x65, 0x6e, 0x65,
- 0x72, 0x67, 0x79, 0x55, 0x77, 0x73, 0x1a, 0x70, 0x0a, 0x0a, 0x50, 0x6f,
- 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x12, 0x0a, 0x04,
- 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
- 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x0b, 0x65, 0x6e, 0x65, 0x72,
- 0x67, 0x79, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c,
- 0x73, 0x2e, 0x45, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61,
- 0x52, 0x0a, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61,
- 0x42, 0x02, 0x48, 0x03, 0x0a, 0xac, 0x0e, 0x0a, 0x34, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70,
- 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xde, 0x0d, 0x0a, 0x14, 0x41,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75,
- 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x47, 0x0a, 0x07, 0x73,
- 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x52,
- 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x1a, 0xe0, 0x01, 0x0a,
- 0x12, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x72,
- 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x72,
- 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e,
- 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x75, 0x6e,
- 0x6e, 0x69, 0x6e, 0x67, 0x44, 0x75, 0x72, 0x4e, 0x73, 0x12, 0x26, 0x0a,
- 0x0f, 0x72, 0x75, 0x6e, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x75,
- 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d,
- 0x72, 0x75, 0x6e, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x4e,
- 0x73, 0x12, 0x3f, 0x0a, 0x1c, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
- 0x72, 0x75, 0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x6c, 0x65,
- 0x65, 0x70, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x19, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
- 0x72, 0x75, 0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x53, 0x6c, 0x65, 0x65,
- 0x70, 0x44, 0x75, 0x72, 0x4e, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x69, 0x6e,
- 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x5f,
- 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73,
- 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x69, 0x6e, 0x74, 0x65,
- 0x72, 0x72, 0x75, 0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x53, 0x6c, 0x65,
- 0x65, 0x70, 0x44, 0x75, 0x72, 0x4e, 0x73, 0x1a, 0x1e, 0x0a, 0x05, 0x53,
- 0x6c, 0x69, 0x63, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x75, 0x72, 0x5f,
- 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x75,
- 0x72, 0x4e, 0x73, 0x1a, 0xbb, 0x08, 0x0a, 0x0c, 0x54, 0x6f, 0x46, 0x69,
- 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x15, 0x0a, 0x06,
- 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03,
- 0x52, 0x05, 0x64, 0x75, 0x72, 0x4e, 0x73, 0x12, 0x72, 0x0a, 0x19, 0x6d,
- 0x61, 0x69, 0x6e, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x62,
- 0x79, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72,
- 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54, 0x61,
- 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x72, 0x65, 0x61, 0x6b,
- 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x15, 0x6d, 0x61, 0x69, 0x6e, 0x54, 0x68,
- 0x72, 0x65, 0x61, 0x64, 0x42, 0x79, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x12, 0x41, 0x0a, 0x1d, 0x6f, 0x74, 0x68, 0x65, 0x72,
- 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x73,
- 0x70, 0x61, 0x77, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x1a, 0x6f, 0x74, 0x68, 0x65,
- 0x72, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x53, 0x70,
- 0x61, 0x77, 0x6e, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x5f,
- 0x0a, 0x15, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76,
- 0x69, 0x74, 0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x18,
- 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
- 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74,
- 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69,
- 0x63, 0x65, 0x52, 0x13, 0x74, 0x69, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69,
- 0x76, 0x69, 0x74, 0x79, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12,
- 0x66, 0x0a, 0x19, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69,
- 0x76, 0x69, 0x74, 0x79, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f,
- 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b,
+ 0x45, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0a,
+ 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x42, 0x02,
+ 0x48, 0x03, 0x0a, 0xac, 0x0e, 0x0a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x2f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+ 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xde, 0x0d, 0x0a, 0x14, 0x41, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x47, 0x0a, 0x07, 0x73, 0x74, 0x61,
+ 0x72, 0x74, 0x75, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d,
0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d,
- 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x68, 0x72,
- 0x65, 0x61, 0x64, 0x4d, 0x61, 0x69, 0x6e, 0x12, 0x5f, 0x0a, 0x15, 0x74,
- 0x69, 0x6d, 0x65, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x70, 0x70,
- 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52,
- 0x13, 0x74, 0x69, 0x6d, 0x65, 0x42, 0x69, 0x6e, 0x64, 0x41, 0x70, 0x70,
- 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x13,
+ 0x63, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x52, 0x07, 0x73,
+ 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x1a, 0xe0, 0x01, 0x0a, 0x12, 0x54,
+ 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x72, 0x65, 0x61,
+ 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x75, 0x6e,
+ 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x75, 0x6e, 0x6e, 0x69,
+ 0x6e, 0x67, 0x44, 0x75, 0x72, 0x4e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x72,
+ 0x75, 0x6e, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x5f,
+ 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x72, 0x75,
+ 0x6e, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x4e, 0x73, 0x12,
+ 0x3f, 0x0a, 0x1c, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75,
+ 0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x6c, 0x65, 0x65, 0x70,
+ 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x19, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75,
+ 0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x44,
+ 0x75, 0x72, 0x4e, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x72, 0x75, 0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x6c,
+ 0x65, 0x65, 0x70, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x04,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72,
+ 0x75, 0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x53, 0x6c, 0x65, 0x65, 0x70,
+ 0x44, 0x75, 0x72, 0x4e, 0x73, 0x1a, 0x1e, 0x0a, 0x05, 0x53, 0x6c, 0x69,
+ 0x63, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x75, 0x72, 0x4e,
+ 0x73, 0x1a, 0xbb, 0x08, 0x0a, 0x0c, 0x54, 0x6f, 0x46, 0x69, 0x72, 0x73,
+ 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x75,
+ 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05,
+ 0x64, 0x75, 0x72, 0x4e, 0x73, 0x12, 0x72, 0x0a, 0x19, 0x6d, 0x61, 0x69,
+ 0x6e, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x79, 0x5f,
+ 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
+ 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75,
+ 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54, 0x61, 0x73, 0x6b,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f,
+ 0x77, 0x6e, 0x52, 0x15, 0x6d, 0x61, 0x69, 0x6e, 0x54, 0x68, 0x72, 0x65,
+ 0x61, 0x64, 0x42, 0x79, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x12, 0x41, 0x0a, 0x1d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x70,
+ 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x73, 0x70, 0x61,
+ 0x77, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x0d, 0x52, 0x1a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x50,
+ 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x53, 0x70, 0x61, 0x77,
+ 0x6e, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x5f, 0x0a, 0x15,
0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74,
- 0x79, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x11,
- 0x74, 0x69, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79,
- 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x5d, 0x0a, 0x14, 0x74, 0x69, 0x6d,
- 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x72,
- 0x65, 0x73, 0x75, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x12, 0x74, 0x69,
- 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65,
- 0x73, 0x75, 0x6d, 0x65, 0x12, 0x5a, 0x0a, 0x12, 0x74, 0x69, 0x6d, 0x65,
- 0x5f, 0x63, 0x68, 0x6f, 0x72, 0x65, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68,
- 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70,
+ 0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70,
+ 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65,
+ 0x52, 0x13, 0x74, 0x69, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69,
+ 0x74, 0x79, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x66, 0x0a,
+ 0x19, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69,
+ 0x74, 0x79, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6d, 0x61,
+ 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70,
0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74,
0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
- 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x11, 0x74, 0x69, 0x6d, 0x65, 0x43,
- 0x68, 0x6f, 0x72, 0x65, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72,
- 0x12, 0x66, 0x0a, 0x19, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x62, 0x65, 0x66,
- 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x70, 0x72,
- 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x41,
+ 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x68, 0x72, 0x65, 0x61,
+ 0x64, 0x4d, 0x61, 0x69, 0x6e, 0x12, 0x5f, 0x0a, 0x15, 0x74, 0x69, 0x6d,
+ 0x65, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69,
+ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x13, 0x74,
+ 0x69, 0x6d, 0x65, 0x42, 0x69, 0x6e, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69,
+ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x13, 0x74, 0x69,
+ 0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f,
+ 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x16, 0x74, 0x69,
- 0x6d, 0x65, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x72,
- 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x66, 0x0a, 0x19,
- 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f,
- 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
- 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61,
- 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53,
- 0x6c, 0x69, 0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x75,
- 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x6f,
- 0x63, 0x65, 0x73, 0x73, 0x12, 0x4b, 0x0a, 0x23, 0x6f, 0x74, 0x68, 0x65,
- 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f,
- 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x70,
- 0x75, 0x5f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x0c, 0x20, 0x01, 0x28,
- 0x01, 0x52, 0x1e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x63,
- 0x65, 0x73, 0x73, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74,
- 0x79, 0x43, 0x70, 0x75, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x1a, 0xbb, 0x02,
- 0x0a, 0x07, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x1d, 0x0a,
- 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74,
- 0x75, 0x70, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b,
- 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e,
- 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65,
- 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61,
- 0x6d, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x7a, 0x79, 0x67, 0x6f, 0x74, 0x65,
- 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
- 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x7a, 0x79, 0x67, 0x6f,
- 0x74, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
- 0x12, 0x43, 0x0a, 0x1e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79,
- 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x72, 0x6f,
- 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06,
- 0x20, 0x01, 0x28, 0x0d, 0x52, 0x1b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69,
- 0x74, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f,
- 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x58, 0x0a,
- 0x0e, 0x74, 0x6f, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x66, 0x72,
- 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e,
+ 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x11, 0x74, 0x69,
+ 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x74,
+ 0x61, 0x72, 0x74, 0x12, 0x5d, 0x0a, 0x14, 0x74, 0x69, 0x6d, 0x65, 0x5f,
+ 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x73,
+ 0x75, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e,
0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x2e, 0x54, 0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x52, 0x0c, 0x74, 0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72,
- 0x61, 0x6d, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xf5, 0x05, 0x0a, 0x41,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
- 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70,
- 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c,
- 0x6c, 0x73, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x9a,
- 0x05, 0x0a, 0x18, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69,
- 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74,
- 0x61, 0x74, 0x73, 0x12, 0x5e, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61,
- 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65,
- 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c,
- 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x49,
- 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73,
- 0x52, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74,
- 0x61, 0x74, 0x73, 0x1a, 0x3e, 0x0a, 0x05, 0x46, 0x72, 0x61, 0x6d, 0x65,
- 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c,
- 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x70, 0x70,
- 0x69, 0x6e, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x51, 0x0a, 0x08, 0x43,
- 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x12, 0x45, 0x0a, 0x05, 0x66,
- 0x72, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f,
- 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f,
- 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
- 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
- 0x05, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x1a, 0xe3, 0x01, 0x0a, 0x0d, 0x43,
- 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73,
- 0x12, 0x4e, 0x0a, 0x08, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72,
+ 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x12, 0x74, 0x69, 0x6d, 0x65,
+ 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x75,
+ 0x6d, 0x65, 0x12, 0x5a, 0x0a, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x63,
+ 0x68, 0x6f, 0x72, 0x65, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72,
+ 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72,
0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
- 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74,
- 0x73, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x52, 0x08,
- 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b,
- 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c,
- 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74,
- 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74,
- 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f,
- 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
- 0x0a, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
- 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x62, 0x79, 0x74,
- 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65,
- 0x6c, 0x74, 0x61, 0x42, 0x79, 0x74, 0x65, 0x73, 0x1a, 0xa4, 0x01, 0x0a,
- 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61,
- 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x0d, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c,
- 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63,
- 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5e, 0x0a, 0x0e, 0x63,
- 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74,
- 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x70, 0x65,
+ 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72,
+ 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c,
+ 0x69, 0x63, 0x65, 0x52, 0x11, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x68, 0x6f,
+ 0x72, 0x65, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72, 0x12, 0x66,
+ 0x0a, 0x19, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72,
+ 0x65, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63,
+ 0x65, 0x73, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
+ 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65,
+ 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50,
+ 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x66, 0x0a, 0x19, 0x74, 0x69,
+ 0x6d, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74,
+ 0x61, 0x72, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18,
+ 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74,
+ 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69,
+ 0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x75, 0x72, 0x69,
+ 0x6e, 0x67, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65,
+ 0x73, 0x73, 0x12, 0x4b, 0x0a, 0x23, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x61,
+ 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x70, 0x75, 0x5f,
+ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52,
+ 0x1e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
+ 0x73, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x43,
+ 0x70, 0x75, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x1a, 0xbb, 0x02, 0x0a, 0x07,
+ 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x73,
+ 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70,
+ 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
+ 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d,
+ 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+ 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65,
+ 0x12, 0x2c, 0x0a, 0x12, 0x7a, 0x79, 0x67, 0x6f, 0x74, 0x65, 0x5f, 0x6e,
+ 0x65, 0x77, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x04,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x7a, 0x79, 0x67, 0x6f, 0x74, 0x65,
+ 0x4e, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x43,
+ 0x0a, 0x1e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x68,
+ 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65,
+ 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01,
+ 0x28, 0x0d, 0x52, 0x1b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79,
+ 0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65,
+ 0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x0e, 0x74,
+ 0x6f, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d,
+ 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65,
0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
- 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61,
- 0x74, 0x73, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53,
- 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69,
- 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a,
- 0x8c, 0x02, 0x0a, 0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
- 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22,
- 0xc0, 0x01, 0x0a, 0x12, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
- 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x47,
- 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67,
- 0x65, 0x4c, 0x69, 0x73, 0x74, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67,
- 0x65, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x1a,
- 0x61, 0x0a, 0x07, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x21,
- 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61,
- 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61,
- 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a,
- 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03,
- 0x75, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69,
- 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f,
- 0x64, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xca, 0x0e, 0x0a, 0x25, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x2f, 0x62, 0x61, 0x74, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x72,
+ 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61,
+ 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54,
+ 0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
+ 0x0c, 0x74, 0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xf5, 0x05, 0x0a, 0x41, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70,
+ 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73,
+ 0x69, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x9a, 0x05, 0x0a,
+ 0x18, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
+ 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74,
+ 0x73, 0x12, 0x5e, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
+ 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x37, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70,
+ 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
+ 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x49, 0x6e, 0x73,
+ 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d,
+ 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74,
+ 0x73, 0x1a, 0x3e, 0x0a, 0x05, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x12,
+ 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61,
+ 0x70, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e,
+ 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x51, 0x0a, 0x08, 0x43, 0x61, 0x6c,
+ 0x6c, 0x73, 0x69, 0x74, 0x65, 0x12, 0x45, 0x0a, 0x05, 0x66, 0x72, 0x61,
+ 0x6d, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69,
+ 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74,
+ 0x61, 0x74, 0x73, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x05, 0x66,
+ 0x72, 0x61, 0x6d, 0x65, 0x1a, 0xe3, 0x01, 0x0a, 0x0d, 0x43, 0x61, 0x6c,
+ 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x4e,
+ 0x0a, 0x08, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48,
+ 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61,
+ 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e,
+ 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x52, 0x08, 0x63, 0x61,
+ 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f,
+ 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f,
+ 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c,
+ 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73,
+ 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x63, 0x6f,
+ 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64,
+ 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a,
+ 0x0b, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73,
+ 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x74,
+ 0x61, 0x42, 0x79, 0x74, 0x65, 0x73, 0x1a, 0xa4, 0x01, 0x0a, 0x0d, 0x49,
+ 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73,
+ 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x0d, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
+ 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5e, 0x0a, 0x0e, 0x63, 0x61, 0x6c,
+ 0x6c, 0x73, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18,
+ 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43,
+ 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73,
+ 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61,
+ 0x74, 0x73, 0x52, 0x0d, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
+ 0x53, 0x74, 0x61, 0x74, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x8c, 0x02,
+ 0x0a, 0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x61,
+ 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xc0, 0x01,
+ 0x0a, 0x12, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63,
+ 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x08,
+ 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c,
+ 0x69, 0x73, 0x74, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52,
+ 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x1a, 0x61, 0x0a,
+ 0x07, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x21, 0x0a, 0x0c,
+ 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b,
+ 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75,
+ 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x75, 0x69,
+ 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+ 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65,
+ 0x42, 0x02, 0x48, 0x03, 0x0a, 0xca, 0x0e, 0x0a, 0x25, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x1a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x2f, 0x62, 0x61, 0x74, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x2f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x74, 0x72,
0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f,
- 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x1a, 0x36, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+ 0x75, 0x6e, 0x61, 0x67, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x34, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
+ 0x67, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65,
- 0x6d, 0x5f, 0x75, 0x6e, 0x61, 0x67, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x34, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
- 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f,
+ 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x69, 0x6f,
+ 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
- 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x6c, 0x6d, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x2f, 0x6c, 0x6d, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
- 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73,
- 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x1a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73,
- 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x41, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70, 0x72,
- 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69,
- 0x74, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x1a, 0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
- 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd2, 0x01, 0x0a, 0x0d, 0x54,
- 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
- 0x12, 0x50, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x73, 0x74,
- 0x61, 0x74, 0x73, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72,
- 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e,
- 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x65, 0x72, 0x72, 0x6f, 0x72,
- 0x53, 0x74, 0x61, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x2a,
- 0x0a, 0x11, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x0f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x44, 0x75, 0x72, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x73, 0x1a, 0x43, 0x0a, 0x05, 0x45, 0x6e,
- 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
- 0x10, 0x0a, 0x03, 0x69, 0x64, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d,
- 0x52, 0x03, 0x69, 0x64, 0x78, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
- 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61,
- 0x6c, 0x75, 0x65, 0x22, 0xe9, 0x07, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x63,
- 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x48, 0x0a, 0x0c,
- 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x62, 0x61, 0x74, 0x74,
- 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72,
+ 0x64, 0x2f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
+ 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x74, 0x61,
+ 0x72, 0x74, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x41, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66,
+ 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
+ 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x1a, 0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x61,
+ 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd2, 0x01, 0x0a, 0x0d, 0x54, 0x72, 0x61,
+ 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x50,
+ 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74,
+ 0x73, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63,
+ 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x45, 0x6e,
+ 0x74, 0x72, 0x79, 0x52, 0x0f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74,
+ 0x61, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x2a, 0x0a, 0x11,
+ 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x0f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x4e, 0x73, 0x1a, 0x43, 0x0a, 0x05, 0x45, 0x6e, 0x74, 0x72,
+ 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a,
+ 0x03, 0x69, 0x64, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03,
+ 0x69, 0x64, 0x78, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
+ 0x65, 0x22, 0xe9, 0x07, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x48, 0x0a, 0x0c, 0x61, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x62, 0x61, 0x74, 0x74, 0x18, 0x05,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
+ 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72,
+ 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0b, 0x61, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x12, 0x42, 0x0a, 0x0b,
+ 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x63, 0x70, 0x75, 0x18,
+ 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x43, 0x70, 0x75, 0x12, 0x45, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x4d, 0x65, 0x6d, 0x12, 0x5c, 0x0a, 0x11, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x75, 0x6e, 0x61, 0x67, 0x67,
+ 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72,
0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x42, 0x61, 0x74, 0x74,
- 0x65, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0b, 0x61,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x12, 0x42,
- 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x63, 0x70,
- 0x75, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65,
+ 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f,
+ 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74,
+ 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0f, 0x61, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x55, 0x6e, 0x61, 0x67,
+ 0x67, 0x12, 0x55, 0x0a, 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73,
+ 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65,
0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75,
- 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x12, 0x45, 0x0a, 0x0b, 0x61, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x12, 0x5c, 0x0a, 0x11, 0x61, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x75, 0x6e, 0x61,
- 0x67, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65,
- 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67,
- 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0f,
- 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x55, 0x6e,
- 0x61, 0x67, 0x67, 0x12, 0x55, 0x0a, 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c,
- 0x69, 0x73, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e,
- 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
- 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x12,
- 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61,
- 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x5b, 0x0a, 0x16, 0x61, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
- 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47,
- 0x72, 0x6f, 0x77, 0x74, 0x68, 0x52, 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f,
- 0x77, 0x74, 0x68, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x5f, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63,
+ 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x12, 0x61, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
+ 0x4c, 0x69, 0x73, 0x74, 0x12, 0x5b, 0x0a, 0x16, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
+ 0x67, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52,
- 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x12,
- 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c,
- 0x6d, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d,
- 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x12, 0x4d, 0x0a, 0x10, 0x61,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70, 0x6f, 0x77, 0x72, 0x61,
- 0x69, 0x6c, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e,
+ 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f,
+ 0x77, 0x74, 0x68, 0x52, 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74,
+ 0x68, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x5f, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21,
+ 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x49, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61,
+ 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x12, 0x42, 0x0a,
+ 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6d, 0x6b,
+ 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x12, 0x4d, 0x0a, 0x10, 0x61, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c,
+ 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77,
+ 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0f, 0x61, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73,
+ 0x12, 0x4e, 0x0a, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f,
+ 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x52, 0x0e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x68, 0x0a, 0x1b,
+ 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
+ 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x74,
+ 0x61, 0x74, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e,
0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
- 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0f, 0x61,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x72, 0x61, 0x69,
- 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70,
- 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0e, 0x61, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x68,
- 0x0a, 0x1b, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69,
- 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x5f,
- 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72,
+ 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66,
+ 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53,
+ 0x74, 0x61, 0x74, 0x73, 0x52, 0x18, 0x68, 0x65, 0x61, 0x70, 0x50, 0x72,
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74,
- 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x18, 0x68, 0x65, 0x61, 0x70,
- 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
- 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0e,
- 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
- 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61,
- 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x63, 0x65, 0x4d,
- 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2a, 0x06, 0x08, 0xc2, 0x03,
- 0x10, 0xf4, 0x03, 0x2a, 0x06, 0x08, 0xf4, 0x03, 0x10, 0xe9, 0x07, 0x4a,
- 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x42,
- 0x02, 0x48, 0x03}};
+ 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x72,
+ 0x61, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
+ 0x74, 0x61, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x2a, 0x06, 0x08, 0xc2, 0x03, 0x10, 0xf4,
+ 0x03, 0x2a, 0x06, 0x08, 0xf4, 0x03, 0x10, 0xe9, 0x07, 0x4a, 0x04, 0x08,
+ 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x42, 0x02, 0x48,
+ 0x03}};
} // namespace perfetto
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index 298c2ab..a530d6a 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -451,7 +451,7 @@
}
if (packet.has_chrome_events()) {
- ParseChromeEvents(packet.chrome_events());
+ ParseChromeEvents(ts, packet.chrome_events());
}
if (packet.has_perfetto_metatrace()) {
@@ -597,6 +597,11 @@
auto tid = static_cast<uint32_t>(thd.tid());
auto tgid = static_cast<uint32_t>(thd.tgid());
context_->process_tracker->UpdateThread(tid, tgid);
+
+ if (thd.has_name()) {
+ StringId threadNameId = context_->storage->InternString(thd.name());
+ context_->process_tracker->UpdateThreadName(tid, threadNameId);
+ }
}
}
@@ -2360,13 +2365,13 @@
}
}
-void ProtoTraceParser::ParseChromeEvents(ConstBytes blob) {
+void ProtoTraceParser::ParseChromeEvents(int64_t ts, ConstBytes blob) {
TraceStorage* storage = context_->storage.get();
protos::pbzero::ChromeEventBundle::Decoder bundle(blob.data, blob.size);
ArgsTracker args(context_);
if (bundle.has_metadata()) {
RowId row_id = storage->mutable_raw_events()->AddRawEvent(
- 0, raw_chrome_metadata_event_id_, 0, 0);
+ ts, raw_chrome_metadata_event_id_, 0, 0);
// Metadata is proxied via a special event in the raw table to JSON export.
for (auto it = bundle.metadata(); it; ++it) {
@@ -2392,7 +2397,7 @@
if (bundle.has_legacy_ftrace_output()) {
RowId row_id = storage->mutable_raw_events()->AddRawEvent(
- 0, raw_chrome_legacy_system_trace_event_id_, 0, 0);
+ ts, raw_chrome_legacy_system_trace_event_id_, 0, 0);
std::string data;
for (auto it = bundle.legacy_ftrace_output(); it; ++it) {
@@ -2412,7 +2417,7 @@
continue;
}
RowId row_id = storage->mutable_raw_events()->AddRawEvent(
- 0, raw_chrome_legacy_user_trace_event_id_, 0, 0);
+ ts, raw_chrome_legacy_user_trace_event_id_, 0, 0);
Variadic value =
Variadic::Json(storage->InternString(legacy_trace.data()));
args.AddArg(row_id, data_name_id_, data_name_id_, value);
diff --git a/src/trace_processor/proto_trace_parser.h b/src/trace_processor/proto_trace_parser.h
index f65ce10..35257a6 100644
--- a/src/trace_processor/proto_trace_parser.h
+++ b/src/trace_processor/proto_trace_parser.h
@@ -132,7 +132,7 @@
ArgsTracker* args_tracker,
RowId row);
void ParseChromeBenchmarkMetadata(ConstBytes);
- void ParseChromeEvents(ConstBytes);
+ void ParseChromeEvents(int64_t ts, ConstBytes);
void ParseMetatraceEvent(int64_t ts, ConstBytes);
void ParseGpuCounterEvent(int64_t ts, ConstBytes);
void ParseGpuRenderStageEvent(int64_t ts, ConstBytes);
diff --git a/src/trace_processor/proto_trace_parser_unittest.cc b/src/trace_processor/proto_trace_parser_unittest.cc
index d7578b8..c97ce84 100644
--- a/src/trace_processor/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/proto_trace_parser_unittest.cc
@@ -1124,9 +1124,9 @@
context_.sorter->ExtractEventsForced();
- EXPECT_EQ(storage_->tracks().track_count(), 2u);
- EXPECT_EQ(storage_->tracks().names()[0], 2u);
- EXPECT_EQ(storage_->tracks().names()[1], 4u);
+ EXPECT_EQ(storage_->track_table().size(), 2u);
+ EXPECT_EQ(storage_->track_table().name()[0], 2u);
+ EXPECT_EQ(storage_->track_table().name()[1], 4u);
EXPECT_EQ(storage_->virtual_tracks().virtual_track_count(), 2u);
EXPECT_EQ(storage_->virtual_tracks().track_ids()[0], 0u);
EXPECT_EQ(storage_->virtual_tracks().track_ids()[1], 1u);
diff --git a/src/trace_processor/proto_trace_tokenizer.cc b/src/trace_processor/proto_trace_tokenizer.cc
index 8e97017..e47ff6b 100644
--- a/src/trace_processor/proto_trace_tokenizer.cc
+++ b/src/trace_processor/proto_trace_tokenizer.cc
@@ -628,6 +628,8 @@
return;
}
+ latest_timestamp_ = std::max(timestamp, latest_timestamp_);
+
if (auto tt_delta_field =
event_decoder.FindField(kThreadTimeDeltaUsFieldNumber)) {
thread_timestamp = state->IncrementAndGetTrackEventThreadTimeNs(
diff --git a/src/trace_processor/raw_table.cc b/src/trace_processor/raw_table.cc
index a77c1c5..fa588bb 100644
--- a/src/trace_processor/raw_table.cc
+++ b/src/trace_processor/raw_table.cc
@@ -227,7 +227,11 @@
writer->AppendUnsignedInt(value.uint_value & ((1 << 20) - 1));
});
writer->AppendString(" ino ");
- write_value_at_index(MFA::kIInoFieldNumber - 1, write_value);
+ write_value_at_index(MFA::kIInoFieldNumber - 1,
+ [writer](const Variadic& value) {
+ PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
+ writer->AppendHexInt(value.uint_value);
+ });
writer->AppendString(" page=0000000000000000");
writer->AppendString(" pfn=");
write_value_at_index(MFA::kPfnFieldNumber - 1, write_value);
diff --git a/src/trace_processor/slice_table.cc b/src/trace_processor/slice_table.cc
index 95d8b7b..70a96f2 100644
--- a/src/trace_processor/slice_table.cc
+++ b/src/trace_processor/slice_table.cc
@@ -56,7 +56,7 @@
// Only the string columns are handled by SQLite
info->order_by_consumed = true;
size_t name_index = schema().ColumnIndexFromName("name");
- size_t cat_index = schema().ColumnIndexFromName("cat");
+ size_t cat_index = schema().ColumnIndexFromName("category");
size_t ref_type_index = schema().ColumnIndexFromName("ref_type");
for (size_t i = 0; i < qc.constraints().size(); i++) {
auto col = static_cast<size_t>(qc.constraints()[i].iColumn);
diff --git a/src/trace_processor/stack_profile_tracker.cc b/src/trace_processor/stack_profile_tracker.cc
index 77e29d3..35e77db 100644
--- a/src/trace_processor/stack_profile_tracker.cc
+++ b/src/trace_processor/stack_profile_tracker.cc
@@ -19,25 +19,10 @@
#include "src/trace_processor/trace_processor_context.h"
#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_utils.h"
namespace perfetto {
namespace trace_processor {
-namespace {
-
-std::string ToHex(const char* build_id, size_t size) {
- std::string hex_build_id(2 * size + 1, 'x');
- for (size_t i = 0; i < size; ++i) {
- // snprintf prints 3 characters, the two hex digits and a null byte. As we
- // write left to write, we keep overwriting the nullbytes, except for the
- // last call to snprintf.
- snprintf(&(hex_build_id[2 * i]), 3, "%02hhx", build_id[i]);
- }
- // Remove the trailing nullbyte produced by the last snprintf.
- hex_build_id.resize(2 * size);
- return hex_build_id;
-}
-
-} // namespace
StackProfileTracker::InternLookup::~InternLookup() = default;
@@ -73,7 +58,7 @@
StringId build_id = empty_;
if (raw_build_id_str.size() > 0) {
std::string hex_build_id =
- ToHex(raw_build_id_str.c_str(), raw_build_id_str.size());
+ base::ToHex(raw_build_id_str.c_str(), raw_build_id_str.size());
build_id = context_->storage->InternString(base::StringView(hex_build_id));
}
diff --git a/src/trace_processor/systrace_trace_parser.cc b/src/trace_processor/systrace_trace_parser.cc
index a766e6f..3d81e52 100644
--- a/src/trace_processor/systrace_trace_parser.cc
+++ b/src/trace_processor/systrace_trace_parser.cc
@@ -98,26 +98,34 @@
const std::string& buffer) {
// An example line from buffer looks something like the following:
// <idle>-0 (-----) [000] d..1 16500.715638: cpu_idle: state=0 cpu_id=0
+ //
+ // However, sometimes the tgid can be missing and buffer looks like this:
+ // <idle>-0 [000] ...2 0.002188: task_newtask: pid=1 ...
auto task_idx = 16u;
std::string task = SubstrTrim(buffer, 0, task_idx);
+ // Try and figure out whether tgid is present by searching for '(' but only
+ // if it occurs before the start of cpu (indiciated by '[') - this is because
+ // '(' can also occur in the args of an event.
auto tgid_idx = buffer.find('(', task_idx + 1);
- std::string pid_str = SubstrTrim(buffer, task_idx + 1, tgid_idx);
+ auto cpu_idx = buffer.find('[', task_idx + 1);
+ bool has_tgid = tgid_idx != std::string::npos && tgid_idx < cpu_idx;
+
+ auto pid_end = has_tgid ? cpu_idx : tgid_idx;
+ std::string pid_str = SubstrTrim(buffer, task_idx + 1, pid_end);
auto pid = static_cast<uint32_t>(std::stoi(pid_str));
context_->process_tracker->GetOrCreateThread(pid);
- auto tgid_end = buffer.find(')', tgid_idx + 1);
- std::string tgid_str = SubstrTrim(buffer, tgid_idx + 1, tgid_end);
- auto tgid = tgid_str == "-----"
- ? base::nullopt
- : base::Optional<uint32_t>(
- static_cast<uint32_t>(std::stoi(tgid_str)));
- if (tgid.has_value()) {
- context_->process_tracker->UpdateThread(pid, tgid.value());
+ if (has_tgid) {
+ auto tgid_end = buffer.find(')', tgid_idx + 1);
+ std::string tgid_str = SubstrTrim(buffer, tgid_idx + 1, tgid_end);
+ if (tgid_str != "-----") {
+ context_->process_tracker->UpdateThread(
+ pid, static_cast<uint32_t>(std::stoi(tgid_str)));
+ }
}
- auto cpu_idx = buffer.find('[', tgid_end + 1);
auto cpu_end = buffer.find(']', cpu_idx + 1);
std::string cpu_str = SubstrTrim(buffer, cpu_idx + 1, cpu_end);
auto cpu = static_cast<uint32_t>(std::stoi(cpu_str));
diff --git a/src/trace_processor/tables/macros.h b/src/trace_processor/tables/macros.h
index 0046502..86ded55 100644
--- a/src/trace_processor/tables/macros.h
+++ b/src/trace_processor/tables/macros.h
@@ -40,7 +40,7 @@
//
// Then we would invoke the macro as follows:
// #define PERFETTO_TP_EVENT_TABLE_DEF(NAME, PARENT, C)
-// NAME(EventTable)
+// NAME(EventTable, "event")
// PERFETTO_TP_ROOT_TABLE(PARENT, C)
// C(int64_t, ts)
// C(uint32_t, arg_set_id)
@@ -57,7 +57,7 @@
//
// Then, we would invoke the macro as follows:
// #define PERFETTO_TP_SLICE_TABLE_DEF(NAME, PARENT, C)
-// NAME(ChildTable)
+// NAME(SliceTable, "slice")
// PARENT(PERFETTO_TP_EVENT_TABLE_DEF, C)
// C(int64_t, dur)
// C(uint8_t, depth)
@@ -77,8 +77,8 @@
//
// This macro takes one argument: the full definition of the table; the
// definition is a function macro taking three arguments:
-// 1. NAME, a function macro taking one argument: the name of the new class
-// being defined.
+// 1. NAME, a function macro taking two argument: the name of the new class
+// being defined and the name of the table when exposed to SQLite.
// 2. PARENT, a function macro taking two arguments: a) the definition of
// the parent table if this table
// is a root table b) C, the third parameter of the macro definition (see
@@ -87,9 +87,9 @@
// 3. C, a function macro taking two parameters: a) the type of a column
// b) the name of a column. This macro should be invoked as many times as
// there are columns in the table with the information about them.
-#define PERFETTO_TP_TABLE(DEF) \
- PERFETTO_TP_TABLE_INTERNAL( \
- PERFETTO_TP_TABLE_CLASS(DEF), \
+#define PERFETTO_TP_TABLE(DEF) \
+ PERFETTO_TP_TABLE_INTERNAL( \
+ PERFETTO_TP_TABLE_NAME(DEF), PERFETTO_TP_TABLE_CLASS(DEF), \
PERFETTO_TP_TABLE_CLASS(PERFETTO_TP_PARENT_DEF(DEF)), DEF)
} // namespace trace_processor
diff --git a/src/trace_processor/tables/macros_internal.h b/src/trace_processor/tables/macros_internal.h
index 2591e0a..8db36c7 100644
--- a/src/trace_processor/tables/macros_internal.h
+++ b/src/trace_processor/tables/macros_internal.h
@@ -31,7 +31,16 @@
// pointer to this class will always be null.
class RootParentTable : public Table {
public:
- uint32_t Insert(std::nullptr_t) { PERFETTO_FATAL("Should not be called"); }
+ struct Row {
+ public:
+ Row(std::nullptr_t) {}
+
+ const char* type() const { return type_; }
+
+ protected:
+ const char* type_ = nullptr;
+ };
+ uint32_t Insert(const Row&) { PERFETTO_FATAL("Should not be called"); }
};
// The parent class for all macro generated tables.
@@ -39,16 +48,21 @@
// code size.
class MacroTable : public Table {
public:
- MacroTable(const StringPool* pool, Table* parent)
- : Table(pool, parent), parent_(parent) {
+ MacroTable(const char* name, StringPool* pool, Table* parent)
+ : Table(pool, parent), name_(name), parent_(parent) {
row_maps_.emplace_back(BitVector());
if (!parent) {
columns_.emplace_back(
Column::IdColumn(this, static_cast<uint32_t>(columns_.size()),
static_cast<uint32_t>(row_maps_.size()) - 1));
+ columns_.emplace_back(
+ Column("type", &type_, this, static_cast<uint32_t>(columns_.size()),
+ static_cast<uint32_t>(row_maps_.size()) - 1));
}
}
+ const char* table_name() const { return name_; }
+
protected:
void UpdateRowMapsAfterParentInsert() {
if (parent_ != nullptr) {
@@ -64,7 +78,20 @@
row_maps_.back().Add(size_++);
}
+ // Stores the most specific "derived" type of this row in the table.
+ //
+ // For example, suppose a row is inserted into the gpu_slice table. This will
+ // also cause a row to be inserted into the slice table. For users querying
+ // the slice table, they will want to know the "real" type of this slice (i.e.
+ // they will want to see that the type is gpu_slice). This sparse vector
+ // stores precisely the real type.
+ //
+ // Only relevant for parentless tables. Will be empty and unreferenced by
+ // tables with parents.
+ SparseVector<StringPool::Id> type_;
+
private:
+ const char* name_ = nullptr;
Table* parent_ = nullptr;
};
@@ -74,10 +101,15 @@
#define PERFETTO_TP_NOOP(...)
// Gets the class name from a table definition.
-#define PERFETTO_TP_EXTRACT_TABLE_CLASS(class_name) class_name
+#define PERFETTO_TP_EXTRACT_TABLE_CLASS(class_name, ...) class_name
#define PERFETTO_TP_TABLE_CLASS(DEF) \
DEF(PERFETTO_TP_EXTRACT_TABLE_CLASS, PERFETTO_TP_NOOP, PERFETTO_TP_NOOP)
+// Gets the table name from the table definition.
+#define PERFETTO_TP_EXTRACT_TABLE_NAME(_, table_name) table_name
+#define PERFETTO_TP_TABLE_NAME(DEF) \
+ DEF(PERFETTO_TP_EXTRACT_TABLE_NAME, PERFETTO_TP_NOOP, PERFETTO_TP_NOOP)
+
// Gets the parent definition from a table definition.
#define PERFETTO_TP_EXTRACT_PARENT_DEF(PARENT_DEF, _) PARENT_DEF
#define PERFETTO_TP_PARENT_DEF(DEF) \
@@ -108,10 +140,26 @@
PERFETTO_TP_ALL_COLUMNS(PERFETTO_TP_PARENT_DEF(DEF), FN)
// Basic macros for extracting column info from a schema.
-#define PERFETTO_TP_TYPE_COMMA(type, name) type,
#define PERFETTO_TP_NAME_COMMA(type, name) name,
#define PERFETTO_TP_TYPE_NAME_COMMA(type, name) type name,
+// Constructor parameters of Table::Row.
+// We name this name_c to avoid a clash with the field names of
+// Table::Row.
+#define PERFETTO_TP_ROW_CONSTRUCTOR(type, name) type name##_c = {},
+
+// Constructor parameters for parent of Row.
+#define PERFETTO_TP_PARENT_ROW_CONSTRUCTOR(type, name) name##_c,
+
+// Initializes the members of Table::Row.
+#define PERFETTO_TP_ROW_INITIALIZER(type, name) name = name##_c;
+
+// Defines the variable in Table::Row.
+#define PERFETTO_TP_ROW_DEFINITION(type, name) type name = {};
+
+// Defines the parent row field in Insert.
+#define PERFETTO_TP_PARENT_ROW_INSERT(type, name) row.name,
+
// Defines the member variable in the Table.
#define PERFETTO_TP_TABLE_MEMBER(type, name) \
SparseVector<TypedColumn<type>::StoredType> name##_;
@@ -121,8 +169,9 @@
columns_.emplace_back(#name, &name##_, this, columns_.size(), \
row_maps_.size() - 1);
-// Inserts the a value into the corresponding column
-#define PERFETTO_TP_COLUMN_APPEND(type, name) name##_.Append(std::move(name));
+// Inserts the value into the corresponding column
+#define PERFETTO_TP_COLUMN_APPEND(type, name) \
+ name##_.Append(std::move(row.name));
// Defines the accessor for a column.
#define PERFETTO_TP_TABLE_COL_ACCESSOR(type, name) \
@@ -133,14 +182,44 @@
// Definition used as the parent of root tables.
#define PERFETTO_TP_ROOT_TABLE_PARENT_DEF(NAME, PARENT, C) \
- NAME(macros_internal::RootParentTable)
+ NAME(macros_internal::RootParentTable, "root")
// For more general documentation, see PERFETTO_TP_TABLE in macros.h.
-#define PERFETTO_TP_TABLE_INTERNAL(class_name, parent_class_name, DEF) \
+#define PERFETTO_TP_TABLE_INTERNAL(table_name, class_name, parent_class_name, \
+ DEF) \
class class_name : public macros_internal::MacroTable { \
public: \
- class_name(const StringPool* pool, parent_class_name* parent) \
- : macros_internal::MacroTable(pool, parent), parent_(parent) { \
+ struct Row : parent_class_name::Row { \
+ /* \
+ * Expands to Row(col_type1 col1_c, base::Optional<col_type2> col2_c, \
+ * ...) \
+ */ \
+ Row(PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_ROW_CONSTRUCTOR) \
+ std::nullptr_t = nullptr) \
+ : parent_class_name::Row(PERFETTO_TP_PARENT_COLUMNS( \
+ DEF, \
+ PERFETTO_TP_PARENT_ROW_CONSTRUCTOR) nullptr) { \
+ type_ = table_name; \
+ \
+ /* Expands to \
+ * col1 = col1_c; \
+ * col2 = col2_c; \
+ * ... \
+ */ \
+ PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_ROW_INITIALIZER) \
+ } \
+ \
+ /* Expands to \
+ * col_type1 col1 = {}; \
+ * base::Optional<col_type2> col2 = {}; \
+ * ... \
+ */ \
+ PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_ROW_DEFINITION) \
+ }; \
+ \
+ class_name(StringPool* pool, parent_class_name* parent) \
+ : macros_internal::MacroTable(table_name, pool, parent), \
+ parent_(parent) { \
/* Expands to \
* columns_.emplace_back("col1", col1_, this, columns_.size(), \
* row_maps_.size() - 1); \
@@ -151,29 +230,30 @@
PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_TABLE_CONSTRUCTOR_COLUMN); \
} \
\
- /* Expands to Insert(col_type1 col1, base::Optional<col_type2> col2, ...) \
- */ \
- uint32_t Insert(PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_TYPE_NAME_COMMA) \
- std::nullptr_t = nullptr) { \
+ uint32_t Insert(const Row& row) { \
uint32_t id; \
if (parent_ == nullptr) { \
id = size(); \
+ type_.Append(string_pool_->InternString(row.type())); \
} else { \
- /* Expands to parent_->Insert(parent_col_1, parent_col_2, ...) */ \
- id = parent_->Insert( \
- PERFETTO_TP_PARENT_COLUMNS(DEF, PERFETTO_TP_NAME_COMMA) nullptr); \
+ id = parent_->Insert(row); \
} \
UpdateRowMapsAfterParentInsert(); \
\
/* Expands to \
- * col1_.Append(col1); \
- * col2_.Append(col2); \
+ * col1_.Append(row.col1); \
+ * col2_.Append(row.col2); \
* ... \
*/ \
PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_COLUMN_APPEND); \
return id; \
} \
\
+ const TypedColumn<StringPool::Id>& type() { \
+ return static_cast<const TypedColumn<StringPool::Id>&>( \
+ columns_[static_cast<uint32_t>(ColumnIndex::type)]); \
+ } \
+ \
/* Expands to \
* const SparseVector<col1_type>& col1() { return col1_; } \
* const SparseVector<col2_type>& col2() { return col2_; } \
@@ -183,11 +263,13 @@
\
private: \
enum class ColumnIndex : uint32_t { \
- id, /* Expands to col1, col2, ... */ \
+ id, \
+ type, /* Expands to col1, col2, ... */ \
PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_NAME_COMMA) kNumCols \
}; \
\
parent_class_name* parent_; \
+ \
/* Expands to \
* SparseVector<col1_type> col1_; \
* SparseVector<col2_type> col2_; \
diff --git a/src/trace_processor/tables/macros_unittest.cc b/src/trace_processor/tables/macros_unittest.cc
index 45f4119..c270aea 100644
--- a/src/trace_processor/tables/macros_unittest.cc
+++ b/src/trace_processor/tables/macros_unittest.cc
@@ -23,52 +23,68 @@
namespace {
#define PERFETTO_TP_TEST_EVENT_TABLE_DEF(NAME, PARENT, C) \
- NAME(TestEventTable) \
+ NAME(TestEventTable, "event") \
PARENT(PERFETTO_TP_ROOT_TABLE_PARENT_DEF, C) \
C(int64_t, ts) \
C(int64_t, arg_set_id)
PERFETTO_TP_TABLE(PERFETTO_TP_TEST_EVENT_TABLE_DEF);
#define PERFETTO_TP_TEST_SLICE_TABLE_DEF(NAME, PARENT, C) \
- NAME(TestSliceTable) \
+ NAME(TestSliceTable, "slice") \
PARENT(PERFETTO_TP_TEST_EVENT_TABLE_DEF, C) \
C(base::Optional<int64_t>, dur) \
C(int64_t, depth)
PERFETTO_TP_TABLE(PERFETTO_TP_TEST_SLICE_TABLE_DEF);
#define PERFETTO_TP_TEST_CPU_SLICE_TABLE_DEF(NAME, PARENT, C) \
- NAME(TestCpuSliceTable) \
+ NAME(TestCpuSliceTable, "cpu_slice") \
PARENT(PERFETTO_TP_TEST_SLICE_TABLE_DEF, C) \
C(int64_t, cpu) \
C(int64_t, priority) \
C(StringPool::Id, end_state)
PERFETTO_TP_TABLE(PERFETTO_TP_TEST_CPU_SLICE_TABLE_DEF);
+TEST(TableMacrosUnittest, Name) {
+ StringPool pool;
+ TestEventTable event(&pool, nullptr);
+ TestSliceTable slice(&pool, &event);
+ TestCpuSliceTable cpu_slice(&pool, &slice);
+
+ ASSERT_EQ(event.table_name(), "event");
+ ASSERT_EQ(slice.table_name(), "slice");
+ ASSERT_EQ(cpu_slice.table_name(), "cpu_slice");
+}
+
TEST(TableMacrosUnittest, InsertParent) {
StringPool pool;
TestEventTable event(&pool, nullptr);
TestSliceTable slice(&pool, &event);
- uint32_t id = event.Insert(100, 0);
+ uint32_t id = event.Insert(TestEventTable::Row(100, 0));
ASSERT_EQ(id, 0u);
+ ASSERT_EQ(event.type().GetString(0), "event");
ASSERT_EQ(event.ts()[0], 100);
ASSERT_EQ(event.arg_set_id()[0], 0);
- id = slice.Insert(200, 123, 10, 0);
+ id = slice.Insert(TestSliceTable::Row(200, 123, 10, 0));
ASSERT_EQ(id, 1u);
+ ASSERT_EQ(event.type().GetString(1), "slice");
ASSERT_EQ(event.ts()[1], 200);
ASSERT_EQ(event.arg_set_id()[1], 123);
+ ASSERT_EQ(slice.type().GetString(0), "slice");
ASSERT_EQ(slice.ts()[0], 200);
ASSERT_EQ(slice.arg_set_id()[0], 123);
ASSERT_EQ(slice.dur()[0], 10);
ASSERT_EQ(slice.depth()[0], 0);
- id = slice.Insert(210, 456, base::nullopt, 0);
+ id = slice.Insert(TestSliceTable::Row(210, 456, base::nullopt, 0));
ASSERT_EQ(id, 2u);
+ ASSERT_EQ(event.type().GetString(2), "slice");
ASSERT_EQ(event.ts()[2], 210);
ASSERT_EQ(event.arg_set_id()[2], 456);
+ ASSERT_EQ(slice.type().GetString(1), "slice");
ASSERT_EQ(slice.ts()[1], 210);
ASSERT_EQ(slice.arg_set_id()[1], 456);
ASSERT_EQ(slice.dur()[1], base::nullopt);
@@ -81,27 +97,32 @@
TestSliceTable slice(&pool, &event);
TestCpuSliceTable cpu_slice(&pool, &slice);
- event.Insert(100, 0);
- slice.Insert(200, 123, 10, 0);
+ event.Insert(TestEventTable::Row(100, 0));
+ slice.Insert(TestSliceTable::Row(200, 123, 10, 0));
auto reason = pool.InternString("R");
- uint32_t id = cpu_slice.Insert(205, 456, 5, 1, 4, 1024, reason);
+ uint32_t id =
+ cpu_slice.Insert(TestCpuSliceTable::Row(205, 456, 5, 1, 4, 1024, reason));
ASSERT_EQ(id, 2u);
+ ASSERT_EQ(event.type().GetString(2), "cpu_slice");
ASSERT_EQ(event.ts()[2], 205);
ASSERT_EQ(event.arg_set_id()[2], 456);
+ ASSERT_EQ(slice.type().GetString(1), "cpu_slice");
ASSERT_EQ(slice.ts()[1], 205);
ASSERT_EQ(slice.arg_set_id()[1], 456);
ASSERT_EQ(slice.dur()[1], 5);
ASSERT_EQ(slice.depth()[1], 1);
+ ASSERT_EQ(cpu_slice.type().GetString(0), "cpu_slice");
ASSERT_EQ(cpu_slice.ts()[0], 205);
ASSERT_EQ(cpu_slice.arg_set_id()[0], 456);
ASSERT_EQ(cpu_slice.dur()[0], 5);
ASSERT_EQ(cpu_slice.depth()[0], 1);
ASSERT_EQ(cpu_slice.cpu()[0], 4);
ASSERT_EQ(cpu_slice.priority()[0], 1024);
- ASSERT_EQ(cpu_slice.end_state()[0], "R");
+ ASSERT_EQ(cpu_slice.end_state()[0], reason);
+ ASSERT_EQ(cpu_slice.end_state().GetString(0), "R");
}
} // namespace
diff --git a/src/trace_processor/tables/slice_tables.h b/src/trace_processor/tables/slice_tables.h
index 2f6c5b8..57dc822 100644
--- a/src/trace_processor/tables/slice_tables.h
+++ b/src/trace_processor/tables/slice_tables.h
@@ -24,7 +24,7 @@
namespace tables {
#define PERFETTO_TP_GPU_SLICES_DEF(NAME, PARENT, C) \
- NAME(GpuSliceTable) \
+ NAME(GpuSliceTable, "gpu_slice") \
PERFETTO_TP_ROOT_TABLE(PARENT, C) \
C(uint32_t, slice_id) \
C(base::Optional<int64_t>, context_id) \
diff --git a/src/trace_processor/tables/track_tables.h b/src/trace_processor/tables/track_tables.h
index 49469ba..16d398c 100644
--- a/src/trace_processor/tables/track_tables.h
+++ b/src/trace_processor/tables/track_tables.h
@@ -24,8 +24,15 @@
namespace trace_processor {
namespace tables {
+#define PERFETTO_TP_TRACK_TABLE_DEF(NAME, PARENT, C) \
+ NAME(TrackTable, "track") \
+ PERFETTO_TP_ROOT_TABLE(PARENT, C) \
+ C(StringPool::Id, name)
+
+PERFETTO_TP_TABLE(PERFETTO_TP_TRACK_TABLE_DEF);
+
#define PERFETTO_TP_GPU_TRACKS_DEF(NAME, PARENT, C) \
- NAME(GpuTrackTable) \
+ NAME(GpuTrackTable, "gpu_track") \
PERFETTO_TP_ROOT_TABLE(PARENT, C) \
C(uint32_t, track_id) \
C(StringPool::Id, scope) \
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 1d6a818..9f126ba 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -66,7 +66,6 @@
#include "src/trace_processor/thread_table.h"
#include "src/trace_processor/trace_blob_view.h"
#include "src/trace_processor/trace_sorter.h"
-#include "src/trace_processor/track_table.h"
#include "src/trace_processor/virtual_track_tracker.h"
#include "src/trace_processor/window_operator_table.h"
@@ -302,13 +301,15 @@
StackProfileFrameTable::RegisterTable(*db_, context_.storage.get());
StackProfileMappingTable::RegisterTable(*db_, context_.storage.get());
MetadataTable::RegisterTable(*db_, context_.storage.get());
- TrackTable::RegisterTable(*db_, context_.storage.get());
// New style db-backed tables.
- DbSqliteTable::RegisterTable(*db_, &context_.storage->gpu_slice_table(),
- "gpu_slice");
- DbSqliteTable::RegisterTable(*db_, &context_.storage->gpu_track_table(),
- "gpu_track");
+ const TraceStorage* storage = context_.storage.get();
+ DbSqliteTable::RegisterTable(*db_, &storage->track_table(),
+ storage->track_table().table_name());
+ DbSqliteTable::RegisterTable(*db_, &storage->gpu_slice_table(),
+ storage->gpu_slice_table().table_name());
+ DbSqliteTable::RegisterTable(*db_, &storage->gpu_track_table(),
+ storage->gpu_track_table().table_name());
}
TraceProcessorImpl::~TraceProcessorImpl() {
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 4c7515d..3a5455b 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -1172,8 +1172,8 @@
return std::make_pair(table_id, row);
}
- const Tracks& tracks() const { return tracks_; }
- Tracks* mutable_tracks() { return &tracks_; }
+ const tables::TrackTable& track_table() const { return track_table_; }
+ tables::TrackTable* mutable_track_table() { return &track_table_; }
const VirtualTracks& virtual_tracks() const { return virtual_tracks_; }
VirtualTracks* mutable_virtual_tracks() { return &virtual_tracks_; }
@@ -1308,7 +1308,7 @@
Metadata metadata_{};
// Metadata for tracks.
- Tracks tracks_;
+ tables::TrackTable track_table_{&string_pool_, nullptr};
// Metadata for virtual slice tracks.
VirtualTracks virtual_tracks_;
diff --git a/src/trace_processor/track_table.cc b/src/trace_processor/track_table.cc
deleted file mode 100644
index 57b8564..0000000
--- a/src/trace_processor/track_table.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/track_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-TrackTable::TrackTable(sqlite3*, const TraceStorage* storage)
- : storage_(storage) {}
-
-void TrackTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
- SqliteTable::Register<TrackTable>(db, storage, "track");
-}
-
-StorageSchema TrackTable::CreateStorageSchema() {
- const auto& tracks = storage_->tracks();
- return StorageSchema::Builder()
- .AddGenericNumericColumn("id", RowAccessor())
- .AddStringColumn("name", &tracks.names(), &storage_->string_pool())
- .Build({"id"});
-}
-
-uint32_t TrackTable::RowCount() {
- return storage_->tracks().track_count();
-}
-
-int TrackTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
- info->order_by_consumed = true;
- info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
- return SQLITE_OK;
-}
-
-} // namespace trace_processor
-} // namespace perfetto
diff --git a/src/trace_processor/track_table.h b/src/trace_processor/track_table.h
deleted file mode 100644
index 7e77ec0..0000000
--- a/src/trace_processor/track_table.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_TRACK_TABLE_H_
-#define SRC_TRACE_PROCESSOR_TRACK_TABLE_H_
-
-#include "src/trace_processor/storage_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TrackTable : public StorageTable {
- public:
- static void RegisterTable(sqlite3* db, const TraceStorage* storage);
-
- TrackTable(sqlite3*, const TraceStorage*);
-
- // StorageTable implementation.
- StorageSchema CreateStorageSchema() override;
- uint32_t RowCount() override;
- int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
-
- private:
- const TraceStorage* const storage_;
-};
-
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_TRACK_TABLE_H_
diff --git a/src/trace_processor/virtual_track_tracker.cc b/src/trace_processor/virtual_track_tracker.cc
index 909539f..0cb4e08 100644
--- a/src/trace_processor/virtual_track_tracker.cc
+++ b/src/trace_processor/virtual_track_tracker.cc
@@ -31,7 +31,8 @@
if (it != tracks_.end())
return it->second;
- TrackId track_id = context_->storage->mutable_tracks()->AddTrack(track_name);
+ TrackId track_id = context_->storage->mutable_track_table()->Insert(
+ tables::TrackTable::Row(track_name));
context_->storage->mutable_virtual_tracks()->AddVirtualTrack(
track_id, id_tuple.scope, id_tuple.upid);
tracks_[id_tuple] = track_id;
diff --git a/src/trace_processor/wasm_bridge.cc b/src/trace_processor/wasm_bridge.cc
index 5bb9b3f..b5a1e58 100644
--- a/src/trace_processor/wasm_bridge.cc
+++ b/src/trace_processor/wasm_bridge.cc
@@ -22,7 +22,6 @@
#include "perfetto/trace_processor/trace_processor.h"
#include "protos/perfetto/trace_processor/raw_query.pb.h"
-#include "protos/perfetto/trace_processor/sched.pb.h"
namespace perfetto {
namespace trace_processor {
@@ -35,8 +34,7 @@
// The function is generic and thankfully we need just one for all methods
// because the output is always a protobuf buffer.
// Args:
-// RequestID: the ID passed by the embedder when invoking the RPC method (e.g.,
-// the first argument passed to sched_getSchedEvents()).
+// RequestID: the ID passed by the embedder when invoking the RPC method.
using ReplyFunction = void (*)(RequestID,
bool success,
const char* /*proto_reply_data*/,
diff --git a/src/traced/probes/filesystem/file_scanner.cc b/src/traced/probes/filesystem/file_scanner.cc
index c71bbdf..17dd253 100644
--- a/src/traced/probes/filesystem/file_scanner.cc
+++ b/src/traced/probes/filesystem/file_scanner.cc
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <unistd.h>
+#include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"
#include "src/traced/probes/filesystem/inode_file_data_source.h"
namespace perfetto {
diff --git a/src/traced/probes/filesystem/file_scanner.h b/src/traced/probes/filesystem/file_scanner.h
index 5fac41d..aee07db 100644
--- a/src/traced/probes/filesystem/file_scanner.h
+++ b/src/traced/probes/filesystem/file_scanner.h
@@ -34,7 +34,7 @@
virtual bool OnInodeFound(BlockDeviceID,
Inode,
const std::string&,
- protos::pbzero::InodeFileMap_Entry_Type) = 0;
+ InodeFileMap_Entry_Type) = 0;
virtual void OnInodeScanDone() = 0;
virtual ~Delegate();
};
diff --git a/src/traced/probes/filesystem/file_scanner_unittest.cc b/src/traced/probes/filesystem/file_scanner_unittest.cc
index a035c56..59b2d95 100644
--- a/src/traced/probes/filesystem/file_scanner_unittest.cc
+++ b/src/traced/probes/filesystem/file_scanner_unittest.cc
@@ -21,6 +21,7 @@
#include <string>
#include "perfetto/base/logging.h"
+#include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"
#include "src/base/test/test_task_runner.h"
#include "test/gtest_and_gmock.h"
@@ -33,28 +34,25 @@
class TestDelegate : public FileScanner::Delegate {
public:
- TestDelegate(
- std::function<bool(BlockDeviceID,
- Inode,
- const std::string&,
- protos::pbzero::InodeFileMap_Entry_Type)> callback,
- std::function<void()> done_callback)
+ TestDelegate(std::function<bool(BlockDeviceID,
+ Inode,
+ const std::string&,
+ InodeFileMap_Entry_Type)> callback,
+ std::function<void()> done_callback)
: callback_(std::move(callback)),
done_callback_(std::move(done_callback)) {}
bool OnInodeFound(BlockDeviceID block_device_id,
Inode inode,
const std::string& path,
- protos::pbzero::InodeFileMap_Entry_Type type) override {
+ InodeFileMap_Entry_Type type) override {
return callback_(block_device_id, inode, path, type);
}
void OnInodeScanDone() { return done_callback_(); }
private:
- std::function<bool(BlockDeviceID,
- Inode,
- const std::string&,
- protos::pbzero::InodeFileMap_Entry_Type)>
+ std::function<
+ bool(BlockDeviceID, Inode, const std::string&, InodeFileMap_Entry_Type)>
callback_;
std::function<void()> done_callback_;
};
@@ -63,7 +61,7 @@
FileEntry(BlockDeviceID block_device_id,
Inode inode,
std::string path,
- protos::pbzero::InodeFileMap_Entry_Type type)
+ InodeFileMap_Entry_Type type)
: block_device_id_(block_device_id),
inode_(inode),
path_(std::move(path)),
@@ -78,7 +76,7 @@
BlockDeviceID block_device_id_;
Inode inode_;
std::string path_;
- protos::pbzero::InodeFileMap_Entry_Type type_;
+ InodeFileMap_Entry_Type type_;
};
struct stat CheckStat(const std::string& path) {
@@ -87,8 +85,7 @@
return buf;
}
-FileEntry StatFileEntry(const std::string& path,
- protos::pbzero::InodeFileMap_Entry_Type type) {
+FileEntry StatFileEntry(const std::string& path, InodeFileMap_Entry_Type type) {
struct stat buf = CheckStat(path);
return FileEntry(buf.st_dev, buf.st_ino, path, type);
}
@@ -98,7 +95,7 @@
bool done = false;
TestDelegate delegate(
[&seen](BlockDeviceID, Inode, const std::string&,
- protos::pbzero::InodeFileMap_Entry_Type) {
+ InodeFileMap_Entry_Type) {
++seen;
return false;
},
@@ -116,7 +113,7 @@
base::TestTaskRunner task_runner;
TestDelegate delegate(
[&seen](BlockDeviceID, Inode, const std::string&,
- protos::pbzero::InodeFileMap_Entry_Type) {
+ InodeFileMap_Entry_Type) {
++seen;
return false;
},
@@ -134,8 +131,7 @@
std::vector<FileEntry> file_entries;
TestDelegate delegate(
[&file_entries](BlockDeviceID block_device_id, Inode inode,
- const std::string& path,
- protos::pbzero::InodeFileMap_Entry_Type type) {
+ const std::string& path, InodeFileMap_Entry_Type type) {
file_entries.emplace_back(block_device_id, inode, path, type);
return true;
},
@@ -161,8 +157,7 @@
std::vector<FileEntry> file_entries;
TestDelegate delegate(
[&file_entries](BlockDeviceID block_device_id, Inode inode,
- const std::string& path,
- protos::pbzero::InodeFileMap_Entry_Type type) {
+ const std::string& path, InodeFileMap_Entry_Type type) {
file_entries.emplace_back(block_device_id, inode, path, type);
return true;
},
diff --git a/src/traced/probes/filesystem/inode_file_data_source.cc b/src/traced/probes/filesystem/inode_file_data_source.cc
index 9446c8c..d4643cb 100644
--- a/src/traced/probes/filesystem/inode_file_data_source.cc
+++ b/src/traced/probes/filesystem/inode_file_data_source.cc
@@ -29,6 +29,7 @@
#include "perfetto/ext/tracing/core/trace_writer.h"
#include "protos/perfetto/config/inode_file/inode_file_config.pbzero.h"
+#include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
#include "src/traced/probes/filesystem/file_scanner.h"
@@ -65,7 +66,7 @@
bool OnInodeFound(BlockDeviceID block_device_id,
Inode inode_number,
const std::string& path,
- protos::pbzero::InodeFileMap_Entry_Type type) {
+ InodeFileMap_Entry_Type type) {
std::unordered_map<Inode, InodeMapValue>& inode_map =
(*map_)[block_device_id];
inode_map[inode_number].SetType(type);
@@ -95,7 +96,8 @@
const InodeMapValue& inode_map_value) {
auto* entry = destination->add_entries();
entry->set_inode_number(inode_number);
- entry->set_type(inode_map_value.type());
+ entry->set_type(static_cast<protos::pbzero::InodeFileMap_Entry_Type>(
+ inode_map_value.type()));
for (const auto& path : inode_map_value.paths())
entry->add_paths(path.c_str());
}
@@ -293,11 +295,10 @@
it->second.erase(inode_number);
}
-bool InodeFileDataSource::OnInodeFound(
- BlockDeviceID block_device_id,
- Inode inode_number,
- const std::string& path,
- protos::pbzero::InodeFileMap_Entry_Type type) {
+bool InodeFileDataSource::OnInodeFound(BlockDeviceID block_device_id,
+ Inode inode_number,
+ const std::string& path,
+ InodeFileMap_Entry_Type type) {
auto it = missing_inodes_.find(block_device_id);
if (it == missing_inodes_.end())
return true;
diff --git a/src/traced/probes/filesystem/inode_file_data_source.h b/src/traced/probes/filesystem/inode_file_data_source.h
index 4b7d3fe..529fe2c 100644
--- a/src/traced/probes/filesystem/inode_file_data_source.h
+++ b/src/traced/probes/filesystem/inode_file_data_source.h
@@ -99,7 +99,7 @@
bool OnInodeFound(BlockDeviceID block_device_id,
Inode inode_number,
const std::string& path,
- protos::pbzero::InodeFileMap_Entry_Type type) override;
+ InodeFileMap_Entry_Type type) override;
void OnInodeScanDone() override;
void AddRootsForBlockDevice(BlockDeviceID block_device_id,
diff --git a/src/traced/probes/filesystem/lru_inode_cache_unittest.cc b/src/traced/probes/filesystem/lru_inode_cache_unittest.cc
index a71a584..86aed74 100644
--- a/src/traced/probes/filesystem/lru_inode_cache_unittest.cc
+++ b/src/traced/probes/filesystem/lru_inode_cache_unittest.cc
@@ -19,6 +19,7 @@
#include <string>
#include <tuple>
+#include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
diff --git a/src/traced/probes/ftrace/event_info.cc b/src/traced/probes/ftrace/event_info.cc
index 8e2e696..657a459 100644
--- a/src/traced/probes/ftrace/event_info.cc
+++ b/src/traced/probes/ftrace/event_info.cc
@@ -2481,48 +2481,6 @@
{
events.emplace_back(Event{});
Event* event = &events.back();
- event->name = "gpu_sched_enqueue";
- event->group = "gpu";
- event->proto_field_id = 333;
- event->fields.push_back(MakeField("ctx_id", 1, ProtoSchemaType::kUint32));
- event->fields.push_back(MakeField("job_id", 2, ProtoSchemaType::kUint32));
- event->fields.push_back(MakeField("priority", 3, ProtoSchemaType::kUint32));
- event->fields.push_back(
- MakeField("submission_id", 4, ProtoSchemaType::kUint32));
- }
-
- {
- events.emplace_back(Event{});
- Event* event = &events.back();
- event->name = "gpu_sched_submit";
- event->group = "gpu";
- event->proto_field_id = 334;
- event->fields.push_back(MakeField("ctx_id", 1, ProtoSchemaType::kUint32));
- event->fields.push_back(
- MakeField("hwqueue_id", 2, ProtoSchemaType::kUint32));
- event->fields.push_back(MakeField("job_id", 3, ProtoSchemaType::kUint32));
- event->fields.push_back(MakeField("priority", 4, ProtoSchemaType::kUint32));
- event->fields.push_back(
- MakeField("submission_id", 5, ProtoSchemaType::kUint32));
- }
-
- {
- events.emplace_back(Event{});
- Event* event = &events.back();
- event->name = "gpu_sched_complete";
- event->group = "gpu";
- event->proto_field_id = 335;
- event->fields.push_back(MakeField("ctx_id", 1, ProtoSchemaType::kUint32));
- event->fields.push_back(MakeField("job_id", 2, ProtoSchemaType::kUint32));
- event->fields.push_back(MakeField("msg", 3, ProtoSchemaType::kString));
- event->fields.push_back(MakeField("priority", 4, ProtoSchemaType::kUint32));
- event->fields.push_back(
- MakeField("submission_id", 5, ProtoSchemaType::kUint32));
- }
-
- {
- events.emplace_back(Event{});
- Event* event = &events.back();
event->name = "i2c_read";
event->group = "i2c";
event->proto_field_id = 27;
diff --git a/src/traced/probes/ftrace/test/data/synthetic/available_events b/src/traced/probes/ftrace/test/data/synthetic/available_events
index 94a6085..0a0ea6f 100644
--- a/src/traced/probes/ftrace/test/data/synthetic/available_events
+++ b/src/traced/probes/ftrace/test/data/synthetic/available_events
@@ -5,6 +5,3 @@
clk:clk_enable
clk:clk_disable
clk:clk_set_rate
-gpu:gpu_sched_enqueue
-gpu:gpu_sched_submit
-gpu:gpu_sched_complete
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/gpu/gpu_sched_complete/format b/src/traced/probes/ftrace/test/data/synthetic/events/gpu/gpu_sched_complete/format
deleted file mode 100644
index 0027729..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/gpu/gpu_sched_complete/format
+++ /dev/null
@@ -1,15 +0,0 @@
-name: gpu_sched_complete
-ID: 176
-format:
- field:unsigned short common_type; offset:0; size:2; signed:0;
- field:unsigned char common_flags; offset:2; size:1; signed:0;
- field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
- field:int common_pid; offset:4; size:4; signed:1;
-
- field:uint32_t ctx_id; offset:8; size:4; signed:0;
- field:uint32_t submission_id; offset:12; size:4; signed:0;
- field:uint32_t job_id; offset:16; size:4; signed:0;
- field:uint32_t priority; offset:20; size:4; signed:0;
- field:__data_loc char[] msg; offset:24; size:4; signed:0;
-
-print fmt: "ctx_id=%u submission_id=%u job_id=%u priority=%u, msg=%s", REC->ctx_id, REC->submission_id, REC->job_id, REC->priority, __get_str(msg)
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/gpu/gpu_sched_enqueue/format b/src/traced/probes/ftrace/test/data/synthetic/events/gpu/gpu_sched_enqueue/format
deleted file mode 100644
index b220569..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/gpu/gpu_sched_enqueue/format
+++ /dev/null
@@ -1,14 +0,0 @@
-name: gpu_sched_enqueue
-ID: 174
-format:
- field:unsigned short common_type; offset:0; size:2; signed:0;
- field:unsigned char common_flags; offset:2; size:1; signed:0;
- field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
- field:int common_pid; offset:4; size:4; signed:1;
-
- field:uint32_t ctx_id; offset:8; size:4; signed:0;
- field:uint32_t submission_id; offset:12; size:4; signed:0;
- field:uint32_t job_id; offset:16; size:4; signed:0;
- field:uint32_t priority; offset:20; size:4; signed:0;
-
-print fmt: "ctx_id=%u submission_id=%u job_id=%u priority=%u", REC->ctx_id, REC->submission_id, REC->job_id, REC->priority
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/gpu/gpu_sched_submit/format b/src/traced/probes/ftrace/test/data/synthetic/events/gpu/gpu_sched_submit/format
deleted file mode 100644
index 55a4e62..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/gpu/gpu_sched_submit/format
+++ /dev/null
@@ -1,15 +0,0 @@
-name: gpu_sched_submit
-ID: 175
-format:
- field:unsigned short common_type; offset:0; size:2; signed:0;
- field:unsigned char common_flags; offset:2; size:1; signed:0;
- field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
- field:int common_pid; offset:4; size:4; signed:1;
-
- field:uint32_t ctx_id; offset:8; size:4; signed:0;
- field:uint32_t submission_id; offset:12; size:4; signed:0;
- field:uint32_t job_id; offset:16; size:4; signed:0;
- field:uint32_t priority; offset:20; size:4; signed:0;
- field:uint32_t hwqueue_id; offset:24; size:4; signed:0;
-
-print fmt: "ctx_id=%u submission_id=%u job_id=%u priority=%u hwqueue_id=%u", REC->ctx_id, REC->submission_id, REC->job_id, REC->priority, REC->hwqueue_id
diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn
index a194748..4a13c32 100644
--- a/src/tracing/BUILD.gn
+++ b/src/tracing/BUILD.gn
@@ -55,7 +55,6 @@
"core/shared_memory_arbiter_impl.cc",
"core/shared_memory_arbiter_impl.h",
"core/sliced_protobuf_input_stream.cc",
- "core/sliced_protobuf_input_stream.h",
"core/startup_trace_writer.cc",
"core/startup_trace_writer_registry.cc",
"core/test_config.cc",
@@ -179,7 +178,7 @@
if (enable_perfetto_ipc) {
# Posix specialization of the tracing library for Linux / Android / Mac.
# Provides an IPC transport over a UNIX domain socket.
- static_library("ipc") {
+ source_set("ipc") {
public_deps = [
"../../include/perfetto/ext/tracing/core",
"../../include/perfetto/ext/tracing/ipc",
@@ -259,7 +258,7 @@
]
if (enable_perfetto_ipc) {
- deps += [ "../tracing:ipc" ]
+ deps += [ ":ipc" ]
sources += [
"internal/system_tracing_backend.cc",
"internal/system_tracing_backend.h",
@@ -287,3 +286,20 @@
]
}
}
+
+if (enable_perfetto_benchmarks) {
+ source_set("benchmarks") {
+ testonly = true
+ deps = [
+ ":tracing",
+ "../../../../gn:benchmark",
+ "../../../../gn:default_deps",
+ "../../protos/perfetto/trace:zero",
+ "../../protos/perfetto/trace/ftrace:zero",
+ "../protozero",
+ ]
+ sources = [
+ "core/packet_stream_validator_benchmark.cc",
+ ]
+ }
+}
diff --git a/src/tracing/core/packet_stream_validator.h b/src/tracing/core/packet_stream_validator.h
index 8494f4e..4b1bdf3 100644
--- a/src/tracing/core/packet_stream_validator.h
+++ b/src/tracing/core/packet_stream_validator.h
@@ -17,7 +17,7 @@
#ifndef SRC_TRACING_CORE_PACKET_STREAM_VALIDATOR_H_
#define SRC_TRACING_CORE_PACKET_STREAM_VALIDATOR_H_
-#include "src/tracing/core/sliced_protobuf_input_stream.h"
+#include "perfetto/ext/tracing/core/sliced_protobuf_input_stream.h"
namespace perfetto {
diff --git a/src/tracing/core/packet_stream_validator_benchmark.cc b/src/tracing/core/packet_stream_validator_benchmark.cc
new file mode 100644
index 0000000..9813b61
--- /dev/null
+++ b/src/tracing/core/packet_stream_validator_benchmark.cc
@@ -0,0 +1,73 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <benchmark/benchmark.h>
+
+#include "src/tracing/core/packet_stream_validator.h"
+
+#include "perfetto/ext/tracing/core/slice.h"
+#include "perfetto/protozero/scattered_heap_buffer.h"
+
+#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
+#include "protos/perfetto/trace/test_event.pbzero.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace {
+
+static void BM_PacketStreamValidator(benchmark::State& state) {
+ using namespace perfetto;
+
+ // Create a packet that resembles a ftrace sched bundle. A ftrace page is
+ // 4KB and typically contains ~64 sched events of 64 bytes each.
+ protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
+ auto* bundle = packet->set_ftrace_events();
+ bundle->set_cpu(1);
+ for (size_t events = 0; events < 64; events++) {
+ auto* ftrace_evt = bundle->add_event();
+ ftrace_evt->set_pid(12345);
+ ftrace_evt->set_timestamp(1000ull * 1000 * 1000 * 3600 * 24 * 365);
+ auto* sched_switch = ftrace_evt->set_sched_switch();
+ sched_switch->set_prev_comm("thread_name_1");
+ sched_switch->set_prev_pid(12345);
+ sched_switch->set_prev_state(42);
+ sched_switch->set_next_comm("thread_name_2");
+ sched_switch->set_next_pid(67890);
+ }
+ std::vector<uint8_t> buf = packet.SerializeAsArray();
+
+ // Append 10 packets like the one above, splitting each packet into slices
+ // of 512B each.
+ Slices slices;
+ static constexpr size_t kSliceSize = 512;
+ for (size_t num_packets = 0; num_packets < 10; num_packets++) {
+ for (size_t pos = 0; pos < buf.size(); pos += kSliceSize) {
+ size_t slice_size = std::min(kSliceSize, buf.size() - pos);
+ Slice slice = Slice::Allocate(slice_size);
+ memcpy(slice.own_data(), &buf[pos], slice_size);
+ slices.emplace_back(std::move(slice));
+ }
+ }
+
+ bool res = true;
+ while (state.KeepRunning()) {
+ res &= PacketStreamValidator::Validate(slices);
+ }
+ PERFETTO_CHECK(res);
+}
+
+} // namespace
+
+BENCHMARK(BM_PacketStreamValidator);
diff --git a/src/tracing/core/sliced_protobuf_input_stream.cc b/src/tracing/core/sliced_protobuf_input_stream.cc
index 65b0bb1..3301e63 100644
--- a/src/tracing/core/sliced_protobuf_input_stream.cc
+++ b/src/tracing/core/sliced_protobuf_input_stream.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "src/tracing/core/sliced_protobuf_input_stream.h"
+#include "perfetto/ext/tracing/core/sliced_protobuf_input_stream.h"
#include <algorithm>
@@ -86,17 +86,17 @@
return true;
}
-google::protobuf::int64 SlicedProtobufInputStream::ByteCount() const {
+SlicedProtobufInputStream::int64 SlicedProtobufInputStream::ByteCount() const {
PERFETTO_DCHECK(Validate());
- google::protobuf::int64 count = 0;
+ int64_t count = 0;
for (auto it = slices_->begin(); it != slices_->end(); it++) {
if (it == cur_slice_) {
- count += static_cast<google::protobuf::int64>(pos_in_cur_slice_);
+ count += static_cast<int64_t>(pos_in_cur_slice_);
break;
}
- count += static_cast<google::protobuf::int64>(it->size);
+ count += static_cast<int64_t>(it->size);
}
- return count;
+ return static_cast<SlicedProtobufInputStream::int64>(count);
}
bool SlicedProtobufInputStream::Validate() const {
diff --git a/src/tracing/core/sliced_protobuf_input_stream.h b/src/tracing/core/sliced_protobuf_input_stream.h
deleted file mode 100644
index 9e80966..0000000
--- a/src/tracing/core/sliced_protobuf_input_stream.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACING_CORE_SLICED_PROTOBUF_INPUT_STREAM_H_
-#define SRC_TRACING_CORE_SLICED_PROTOBUF_INPUT_STREAM_H_
-
-#include "perfetto/ext/tracing/core/slice.h"
-
-#include <stdint.h>
-
-#include <google/protobuf/io/zero_copy_stream.h>
-
-namespace perfetto {
-
-// Wraps a sequence of Slice(s) in a protobuf ZeroCopyInputStream that can be
-// passed to protobuf::Message::ParseFromZeroCopyStream().
-class SlicedProtobufInputStream
- : public google::protobuf::io::ZeroCopyInputStream {
- public:
- explicit SlicedProtobufInputStream(const Slices*);
- ~SlicedProtobufInputStream() override;
-
- // ZeroCopyInputStream implementation. See zero_copy_stream.h for the API
- // contract of the methods below.
- bool Next(const void** data, int* size) override;
- void BackUp(int count) override;
- bool Skip(int count) override;
- google::protobuf::int64 ByteCount() const override;
-
- private:
- bool Validate() const;
-
- const Slices* const slices_;
- Slices::const_iterator cur_slice_;
- size_t pos_in_cur_slice_ = 0;
-};
-
-} // namespace perfetto
-
-#endif // SRC_TRACING_CORE_SLICED_PROTOBUF_INPUT_STREAM_H_
diff --git a/src/tracing/core/sliced_protobuf_input_stream_unittest.cc b/src/tracing/core/sliced_protobuf_input_stream_unittest.cc
index 59f52f2..fc0c075 100644
--- a/src/tracing/core/sliced_protobuf_input_stream_unittest.cc
+++ b/src/tracing/core/sliced_protobuf_input_stream_unittest.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "src/tracing/core/sliced_protobuf_input_stream.h"
+#include "perfetto/ext/tracing/core/sliced_protobuf_input_stream.h"
#include "perfetto/ext/base/utils.h"
#include "test/gtest_and_gmock.h"
diff --git a/src/tracing/core/startup_trace_writer_unittest.cc b/src/tracing/core/startup_trace_writer_unittest.cc
index 139456e..a7cd419 100644
--- a/src/tracing/core/startup_trace_writer_unittest.cc
+++ b/src/tracing/core/startup_trace_writer_unittest.cc
@@ -23,7 +23,6 @@
#include "src/base/test/test_task_runner.h"
#include "src/tracing/core/patch_list.h"
#include "src/tracing/core/shared_memory_arbiter_impl.h"
-#include "src/tracing/core/sliced_protobuf_input_stream.h"
#include "src/tracing/core/trace_buffer.h"
#include "src/tracing/test/aligned_buffer_test.h"
#include "src/tracing/test/fake_producer_endpoint.h"
@@ -147,15 +146,10 @@
EXPECT_EQ(static_cast<uid_t>(1),
sequence_properties.producer_uid_trusted);
- SlicedProtobufInputStream stream(&packet.slices());
- size_t size = 0;
- for (const Slice& slice : packet.slices())
- size += slice.size;
protos::TracePacket parsed_packet;
- bool success = parsed_packet.ParseFromBoundedZeroCopyStream(
- &stream, static_cast<int>(size));
- EXPECT_TRUE(success);
- if (!success)
+ bool res = parsed_packet.ParseFromString(packet.GetRawBytesForTesting());
+ EXPECT_TRUE(res);
+ if (!res)
break;
// If the buffer size was exceeded, the data loss packet should be the
diff --git a/src/tracing/core/trace_packet.cc b/src/tracing/core/trace_packet.cc
index c3891c5..0dea150 100644
--- a/src/tracing/core/trace_packet.cc
+++ b/src/tracing/core/trace_packet.cc
@@ -18,7 +18,6 @@
#include "perfetto/base/logging.h"
#include "perfetto/protozero/proto_utils.h"
-#include "src/tracing/core/sliced_protobuf_input_stream.h"
namespace perfetto {
@@ -63,10 +62,16 @@
return std::make_tuple(&preamble_[0], preamble_size);
}
-std::unique_ptr<TracePacket::ZeroCopyInputStream>
-TracePacket::CreateSlicedInputStream() const {
- return std::unique_ptr<ZeroCopyInputStream>(
- new SlicedProtobufInputStream(&slices_));
+std::string TracePacket::GetRawBytesForTesting() {
+ std::string data;
+ data.resize(size());
+ size_t pos = 0;
+ for (const Slice& slice : slices()) {
+ PERFETTO_CHECK(pos + slice.size <= data.size());
+ memcpy(&data[pos], slice.start, slice.size);
+ pos += slice.size;
+ }
+ return data;
}
} // namespace perfetto
diff --git a/src/tracing/core/trace_packet_unittest.cc b/src/tracing/core/trace_packet_unittest.cc
index f2aaa45..0469ae8 100644
--- a/src/tracing/core/trace_packet_unittest.cc
+++ b/src/tracing/core/trace_packet_unittest.cc
@@ -63,7 +63,7 @@
ASSERT_EQ(tp.slices().end(), ++slice);
protos::TracePacket decoded_packet;
- ASSERT_TRUE(tp.Decode(&decoded_packet));
+ ASSERT_TRUE(decoded_packet.ParseFromString(tp.GetRawBytesForTesting()));
ASSERT_EQ(proto.for_testing().str(), decoded_packet.for_testing().str());
}
@@ -94,7 +94,7 @@
ASSERT_EQ(tp.slices().end(), ++slice);
protos::TracePacket decoded_packet;
- ASSERT_TRUE(tp.Decode(&decoded_packet));
+ ASSERT_TRUE(decoded_packet.ParseFromString(tp.GetRawBytesForTesting()));
ASSERT_EQ(proto.for_testing().str(), decoded_packet.for_testing().str());
}
@@ -105,7 +105,7 @@
TracePacket tp;
tp.AddSlice({ser_buf.data(), ser_buf.size() - 2}); // corrupted.
protos::TracePacket decoded_packet;
- ASSERT_FALSE(tp.Decode(&decoded_packet));
+ ASSERT_FALSE(decoded_packet.ParseFromString(tp.GetRawBytesForTesting()));
}
// Tests that the GetProtoPreamble() logic returns a valid preamble that allows
diff --git a/src/tracing/test/mock_consumer.cc b/src/tracing/test/mock_consumer.cc
index 867d98c..17a983d 100644
--- a/src/tracing/test/mock_consumer.cc
+++ b/src/tracing/test/mock_consumer.cc
@@ -109,7 +109,7 @@
for (TracePacket& packet : *packets) {
decoded_packets.emplace_back();
protos::TracePacket* decoded_packet = &decoded_packets.back();
- packet.Decode(decoded_packet);
+ decoded_packet->ParseFromString(packet.GetRawBytesForTesting());
}
if (!has_more)
on_read_buffers();
diff --git a/src/tracing/test/tracing_integration_test.cc b/src/tracing/test/tracing_integration_test.cc
index 56cc2c9..799b614 100644
--- a/src/tracing/test/tracing_integration_test.cc
+++ b/src/tracing/test/tracing_integration_test.cc
@@ -308,7 +308,8 @@
for (auto& encoded_packet : *packets) {
protos::TracePacket packet;
- ASSERT_TRUE(encoded_packet.Decode(&packet));
+ ASSERT_TRUE(packet.ParseFromString(
+ encoded_packet.GetRawBytesForTesting()));
if (packet.has_for_testing()) {
char buf[8];
sprintf(buf, "evt_%zu", num_pack_rx++);
@@ -516,7 +517,8 @@
std::vector<TracePacket>* packets, bool has_more) {
for (auto& encoded_packet : *packets) {
protos::TracePacket packet;
- ASSERT_TRUE(encoded_packet.Decode(&packet));
+ ASSERT_TRUE(packet.ParseFromString(
+ encoded_packet.GetRawBytesForTesting()));
if (packet.has_for_testing()) {
num_test_pack_rx++;
}
diff --git a/test/cts/Android.bp b/test/cts/Android.bp
index c7cee36..69fe21a 100644
--- a/test/cts/Android.bp
+++ b/test/cts/Android.bp
@@ -8,7 +8,7 @@
static_libs: [
"libgmock",
"libprotobuf-cpp-lite",
- "perfetto_src_tracing_ipc",
+ "libperfetto_client_experimental",
"perfetto_trace_protos",
],
shared_libs: [
diff --git a/test/cts/producer/jni/Android.bp b/test/cts/producer/jni/Android.bp
index 939a37b..b97ecdb 100644
--- a/test/cts/producer/jni/Android.bp
+++ b/test/cts/producer/jni/Android.bp
@@ -7,7 +7,7 @@
"libgtest",
"libprotobuf-cpp-lite",
"perfetto_cts_jni_deps",
- "perfetto_src_tracing_ipc",
+ "libperfetto_client_experimental",
],
shared_libs: [
"libandroid",
diff --git a/test/metrics/android_startup_cpu.out b/test/metrics/android_startup_cpu.out
index 0f7b080..2654ba5 100644
--- a/test/metrics/android_startup_cpu.out
+++ b/test/metrics/android_startup_cpu.out
@@ -5,22 +5,25 @@
name : "Process1"
cpu {
id: 0
- max_freq_khz: 5
- min_freq_khz: 5
- avg_freq_khz: 5
+ max_freq_khz: 500000
+ min_freq_khz: 500000
+ avg_freq_khz: 500000
duration_ns: 2
}
+ normalized_cpu_cycles: 1
}
threads {
name: "p1-t2"
cpu {
id: 0
- max_freq_khz: 14
- min_freq_khz: 14
- avg_freq_khz: 14
+ max_freq_khz: 1400000
+ min_freq_khz: 1400000
+ avg_freq_khz: 1400000
duration_ns: 1
}
+ normalized_cpu_cycles: 1
}
+ normalized_cpu_cycles: 2
}
process_info {
name: "Process2"
@@ -28,32 +31,36 @@
name: "p2-t2"
cpu {
id: 1
- max_freq_khz: 20
- min_freq_khz: 20
- avg_freq_khz: 20
+ max_freq_khz: 2000000
+ min_freq_khz: 2000000
+ avg_freq_khz: 2000000
duration_ns: 2
}
+ normalized_cpu_cycles: 4
}
threads {
name: "p2-t3"
cpu {
id: 1
- max_freq_khz: 80
- min_freq_khz: 20
- avg_freq_khz: 40
+ max_freq_khz: 8000000
+ min_freq_khz: 2000000
+ avg_freq_khz: 4000000
duration_ns: 3
}
+ normalized_cpu_cycles: 12
}
threads {
name: "Process2"
cpu {
id: 0
- max_freq_khz: 25
- min_freq_khz: 25
- avg_freq_khz: 25
+ max_freq_khz: 2500000
+ min_freq_khz: 2500000
+ avg_freq_khz: 2500000
duration_ns: 2
}
+ normalized_cpu_cycles: 5
}
+ normalized_cpu_cycles: 21
}
process_info {
name: "Process3"
@@ -61,18 +68,20 @@
name: "Process3"
cpu {
id: 0
- max_freq_khz: 14
- min_freq_khz: 5
- avg_freq_khz: 7
+ max_freq_khz: 1400000
+ min_freq_khz: 500000
+ avg_freq_khz: 725000
duration_ns: 4
}
cpu {
id: 1
- max_freq_khz: 80
- min_freq_khz: 80
- avg_freq_khz: 80
+ max_freq_khz: 8000000
+ min_freq_khz: 8000000
+ avg_freq_khz: 8000000
duration_ns: 2
}
+ normalized_cpu_cycles: 18
}
+ normalized_cpu_cycles: 18
}
-}
\ No newline at end of file
+}
diff --git a/test/metrics/android_startup_cpu.py b/test/metrics/android_startup_cpu.py
index 044df5f..e450767 100644
--- a/test/metrics/android_startup_cpu.py
+++ b/test/metrics/android_startup_cpu.py
@@ -22,13 +22,13 @@
trace.add_ftrace_packet(cpu=0)
# CPU counters for CPU 0.
-trace.add_cpufreq(ts=9, freq=5, cpu=0)
-trace.add_cpufreq(ts=15, freq=14, cpu=0)
-trace.add_cpufreq(ts=17, freq=25, cpu=0)
+trace.add_cpufreq(ts=9, freq=500000, cpu=0)
+trace.add_cpufreq(ts=15, freq=1400000, cpu=0)
+trace.add_cpufreq(ts=17, freq=2500000, cpu=0)
# CPU counters for CPU 1.
-trace.add_cpufreq(ts=11, freq=20, cpu=1)
-trace.add_cpufreq(ts=15, freq=80, cpu=1)
+trace.add_cpufreq(ts=11, freq=2000000, cpu=1)
+trace.add_cpufreq(ts=15, freq=8000000, cpu=1)
# Add 3 processes. This also adds one main thread per process.
trace.add_process_tree_packet()
diff --git a/test/test_helper.cc b/test/test_helper.cc
index e4af816..57e8b10 100644
--- a/test/test_helper.cc
+++ b/test/test_helper.cc
@@ -61,7 +61,8 @@
void TestHelper::OnTraceData(std::vector<TracePacket> packets, bool has_more) {
for (auto& encoded_packet : packets) {
protos::TracePacket packet;
- PERFETTO_CHECK(encoded_packet.Decode(&packet));
+ PERFETTO_CHECK(
+ packet.ParseFromString(encoded_packet.GetRawBytesForTesting()));
if (packet.has_clock_snapshot() || packet.has_trace_config() ||
packet.has_trace_stats() || !packet.synchronization_marker().empty() ||
packet.has_system_info()) {
diff --git a/test/trace_processor/filter_row_vector.sql b/test/trace_processor/filter_row_vector.sql
new file mode 100644
index 0000000..d793cde
--- /dev/null
+++ b/test/trace_processor/filter_row_vector.sql
@@ -0,0 +1,6 @@
+SELECT ts FROM counter_values
+WHERE
+ ts > 72563651549 AND
+ counter_id = 7 AND
+ value != 17952.000000
+LIMIT 20
diff --git a/test/trace_processor/filter_row_vector_example_android_trace_30s.out b/test/trace_processor/filter_row_vector_example_android_trace_30s.out
new file mode 100644
index 0000000..937091d
--- /dev/null
+++ b/test/trace_processor/filter_row_vector_example_android_trace_30s.out
@@ -0,0 +1,21 @@
+"ts"
+72688754739
+72688833280
+72688842812
+72688849478
+72688854530
+72688862499
+72688866770
+72688871301
+72706000522
+72706468074
+72706827293
+72706865678
+72706939220
+72707490886
+72707510418
+72707557814
+72707569480
+72707698647
+72707767501
+72722626305
diff --git a/test/trace_processor/index b/test/trace_processor/index
index da0f0cc..41ef5c2 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -99,6 +99,7 @@
counters_where_cpu.py counters_where_cpu.sql counters_where_cpu_counters_where_cpu.out
counters_group_by_freq.py counters_group_by_freq.sql counters_group_by_freq_counters_group_by_freq.out
counters_order_ref.py counters_order_ref.sql counters_order_ref_counters_order_ref.out
+../data/example_android_trace_30s.pb filter_row_vector.sql filter_row_vector_example_android_trace_30s.out
# Null printing
synth_1.py nulls.sql nulls.out
diff --git a/tools/ftrace_proto_gen/event_whitelist b/tools/ftrace_proto_gen/event_whitelist
index f0d5505..e0662ce 100644
--- a/tools/ftrace_proto_gen/event_whitelist
+++ b/tools/ftrace_proto_gen/event_whitelist
@@ -327,6 +327,3 @@
raw_syscalls/sys_exit
systrace/0
power/gpu_frequency
-gpu/gpu_sched_enqueue
-gpu/gpu_sched_submit
-gpu/gpu_sched_complete
diff --git a/tools/ftrace_proto_gen/proto_gen_utils.cc b/tools/ftrace_proto_gen/proto_gen_utils.cc
index 79f0ea8..6fa9e3f 100644
--- a/tools/ftrace_proto_gen/proto_gen_utils.cc
+++ b/tools/ftrace_proto_gen/proto_gen_utils.cc
@@ -91,9 +91,10 @@
} // namespace
+using base::Contains;
using base::EndsWith;
using base::StartsWith;
-using base::Contains;
+using base::Uppercase;
VerifyStream::VerifyStream(std::string filename)
: filename_(std::move(filename)) {
@@ -146,7 +147,7 @@
}
if (upperCaseNextChar) {
upperCaseNextChar = false;
- c = static_cast<char>(toupper(c));
+ c = Uppercase(c);
}
result.push_back(c);
}
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index 0d6b01a..05a7d50 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -61,11 +61,6 @@
'//tools/trace_to_text:trace_to_text',
]
-# Targets which are testonly but should still be a cc_binary.
-non_test_binaries = [
- '//src/trace_processor:trace_processor_shell',
-]
-
# Defines a custom init_rc argument to be applied to the corresponding output
# blueprint target.
target_initrc = {
@@ -75,11 +70,11 @@
target_host_supported = [
'//protos/perfetto/trace:perfetto_trace_protos',
- '//src/trace_processor:trace_processor_shell',
]
target_host_only = [
'//tools/trace_to_text:trace_to_text',
+ '//src/trace_processor:trace_processor_shell',
]
# All module names are prefixed with this string to avoid collisions.
@@ -141,23 +136,12 @@
def enable_gmock(module):
module.static_libs.append('libgmock')
-
-def enable_gtest_prod(module):
- module.static_libs.append('libgtest_prod')
-
-
-def enable_gtest(module):
- assert module.type == 'cc_test'
-
-
def enable_protobuf_full(module):
module.shared_libs.append('libprotobuf-cpp-full')
-
def enable_protobuf_lite(module):
module.shared_libs.append('libprotobuf-cpp-lite')
-
def enable_protoc_lib(module):
module.shared_libs.append('libprotoc')
@@ -187,16 +171,14 @@
# Android equivalents for third-party libraries that the upstream project
# depends on.
builtin_deps = {
- '//buildtools:gmock': enable_gmock,
- '//buildtools:gtest': enable_gtest,
- '//buildtools:gtest_main': enable_gtest,
- '//buildtools:libunwind': enable_libunwind,
- '//buildtools:protobuf_full': enable_protobuf_full,
- '//buildtools:protobuf_lite': enable_protobuf_lite,
- '//buildtools:protoc_lib': enable_protoc_lib,
- '//buildtools:libunwindstack': enable_libunwindstack,
- '//buildtools:sqlite': enable_sqlite,
- '//buildtools:zlib': enable_zlib,
+ '//gn:gtest_and_gmock': enable_gmock,
+ '//gn:libunwind': enable_libunwind,
+ '//gn:protobuf_full': enable_protobuf_full,
+ '//gn:protobuf_lite': enable_protobuf_lite,
+ '//gn:protoc_lib': enable_protoc_lib,
+ '//gn:libunwindstack': enable_libunwindstack,
+ '//gn:sqlite': enable_sqlite,
+ '//gn:zlib': enable_zlib,
}
# ----------------------------------------------------------------------------
@@ -419,7 +401,10 @@
dep_name: GN target of the dependency.
"""
# If the dependency refers to a library which we can replace with an Android
- # equivalent, stop recursing and patch the dependency in.
+ # equivalent, stop recursing and patch the dependency in. Don't recurse into
+ # //buildtools, builtin_deps are intercepted at the //gn:xxx level.
+ if dep_name.startswith('//buildtools'):
+ return
if gn_utils.label_without_toolchain(dep_name) in builtin_deps:
builtin_deps[gn_utils.label_without_toolchain(dep_name)](module)
return
@@ -645,7 +630,7 @@
if target['type'] == 'executable':
if 'host' in target['toolchain'] or target_name in target_host_only:
module_type = 'cc_binary_host'
- elif target.get('testonly') and target_name not in non_test_binaries:
+ elif target.get('testonly'):
module_type = 'cc_test'
else:
module_type = 'cc_binary'
diff --git a/tools/gen_bazel b/tools/gen_bazel
index baabfc3..282bf84 100755
--- a/tools/gen_bazel
+++ b/tools/gen_bazel
@@ -385,10 +385,14 @@
else:
target.srcs.add(label)
- if target.type == 'cc_library' and ('//include/perfetto/base/build_config.h'
- in module_desc.get('sources', [])):
- target.hdrs.add(Label(os.path.join(buildflags_dir,
- 'perfetto_build_flags.h')))
+ if '//include/perfetto/base/build_config.h' in module_desc.get(
+ 'sources', []):
+ label = Label(os.path.join(buildflags_dir, 'perfetto_build_flags.h'))
+ if target.type == 'cc_library':
+ target.hdrs.add(label)
+ elif target.type == 'cc_binary':
+ target.srcs.add(label)
+
def apply_module_dependency(self, target, dep_name):
"""
diff --git a/tools/gen_merged_protos b/tools/gen_merged_protos
index 319b833..ad632fb 100755
--- a/tools/gen_merged_protos
+++ b/tools/gen_merged_protos
@@ -53,6 +53,7 @@
'protos/perfetto/trace/android/android_log.proto',
'protos/perfetto/trace/android/graphics_frame_event.proto',
'protos/perfetto/trace/android/packages_list.proto',
+ 'protos/perfetto/trace/appended_data/appended_data.proto',
'protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto',
"protos/perfetto/trace/chrome/chrome_metadata.proto",
'protos/perfetto/trace/clock_snapshot.proto',
@@ -68,7 +69,6 @@
'protos/perfetto/trace/ftrace/ftrace_event_bundle.proto',
'protos/perfetto/trace/ftrace/ftrace_stats.proto',
'protos/perfetto/trace/ftrace/generic.proto',
- 'protos/perfetto/trace/ftrace/gpu.proto',
'protos/perfetto/trace/ftrace/kmem.proto',
'protos/perfetto/trace/ftrace/lowmemorykiller.proto',
'protos/perfetto/trace/ftrace/mm_event.proto',
diff --git a/tools/proto_to_cpp/proto_to_cpp.cc b/tools/proto_to_cpp/proto_to_cpp.cc
index 8bb103c..5e995f2 100644
--- a/tools/proto_to_cpp/proto_to_cpp.cc
+++ b/tools/proto_to_cpp/proto_to_cpp.cc
@@ -18,7 +18,6 @@
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/util/field_comparator.h>
#include <google/protobuf/util/message_differencer.h>
@@ -28,10 +27,16 @@
#include <iostream>
#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_utils.h"
using namespace google::protobuf;
using namespace google::protobuf::compiler;
using namespace google::protobuf::io;
+using perfetto::base::SplitString;
+using perfetto::base::StripChars;
+using perfetto::base::StripSuffix;
+using perfetto::base::ToUpper;
+
static constexpr auto TYPE_MESSAGE = FieldDescriptor::TYPE_MESSAGE;
namespace {
@@ -81,7 +86,7 @@
};
std::string GetProtoHeader(const FileDescriptor* proto_file) {
- return StringReplace(proto_file->name(), ".proto", ".pb.h", false);
+ return StripSuffix(proto_file->name(), ".proto") + ".pb.h";
}
std::string GetFwdDeclType(const Descriptor* msg, bool with_namespace = false) {
@@ -92,7 +97,8 @@
full_type.insert(0, par->name() + "_");
}
if (with_namespace) {
- std::vector<std::string> namespaces = Split(msg->file()->package(), ".");
+ std::vector<std::string> namespaces =
+ SplitString(msg->file()->package(), ".");
for (auto it = namespaces.rbegin(); it != namespaces.rend(); it++) {
full_type.insert(0, *it + "::");
}
@@ -153,18 +159,18 @@
}
std::string ProtoToCpp::GetHeaderPath(const FileDescriptor* proto_file) {
- std::string basename = Split(proto_file->name(), "/").back();
- return header_dir_ + "/" + StringReplace(basename, ".proto", ".h", false);
+ std::string basename = SplitString(proto_file->name(), "/").back();
+ return header_dir_ + "/" + StripSuffix(basename, ".proto") + ".h";
}
std::string ProtoToCpp::GetCppPath(const FileDescriptor* proto_file) {
- std::string basename = Split(proto_file->name(), "/").back();
- return cpp_dir_ + "/" + StringReplace(basename, ".proto", ".cc", false);
+ std::string basename = SplitString(proto_file->name(), "/").back();
+ return cpp_dir_ + "/" + StripSuffix(basename, ".proto") + ".cc";
}
std::string ProtoToCpp::GetIncludePath(const FileDescriptor* proto_file) {
- std::string basename = Split(proto_file->name(), "/").back();
- return include_path_ + "/" + StringReplace(basename, ".proto", ".h", false);
+ std::string basename = SplitString(proto_file->name(), "/").back();
+ return include_path_ + "/" + StripSuffix(basename, ".proto") + ".h";
}
std::string ProtoToCpp::GetCppType(const FieldDescriptor* field,
@@ -228,8 +234,8 @@
Printer cpp_printer(&cpp_proto_ostr, '$');
std::string include_guard = dst_header + "_";
- UpperString(&include_guard);
- StripString(&include_guard, ".-/\\", '_');
+ include_guard = ToUpper(include_guard);
+ include_guard = StripChars(include_guard, ".-/\\", '_');
header_printer.Print(kHeader, "f", __FILE__, "p", src_proto);
header_printer.Print("#ifndef $g$\n#define $g$\n\n", "g", include_guard);
header_printer.Print("#include <stdint.h>\n");
@@ -278,7 +284,7 @@
// Generate forward declarations in the header for proto types.
header_printer.Print("// Forward declarations for protobuf types.\n");
- std::vector<std::string> namespaces = Split(proto_file->package(), ".");
+ std::vector<std::string> namespaces = SplitString(proto_file->package(), ".");
for (size_t i = 0; i < namespaces.size(); i++)
header_printer.Print("namespace $n$ {\n", "n", namespaces[i]);
for (int i = 0; i < proto_file->message_type_count(); i++)
diff --git a/tools/tmux b/tools/tmux
index 9f00b5f..7bc2734 100755
--- a/tools/tmux
+++ b/tools/tmux
@@ -39,25 +39,8 @@
test "$value" == "android"
}
-function is_gn_target_and_host_value_equal() {
- local out=$1
- local key=$2
- local host
- local target
- host=$(get_gn_value "$out" "host_$key")
- target=$(get_gn_value "$out" "target_$key")
- [ -z "$target" ] && target="$host"
- test "$target" == "$host"
-}
-
-function is_cross_compilation() {
- local out=$1
- if is_gn_target_and_host_value_equal "$out" cpu &&
- is_gn_target_and_host_value_equal "$out" os; then
- false
- else
- true
- fi
+function is_ssh_target() {
+ [[ -n "$SSH_TARGET" ]];
}
function is_mac() {
@@ -85,9 +68,9 @@
echo 0 > /sys/kernel/debug/tracing/tracing_on
'
- if is_cross_compilation "$OUT"; then
+ if is_ssh_target; then
# shellcheck disable=SC2029
- ssh "$TARGET" "sh -c '$script'"
+ ssh "$SSH_TARGET" "sh -c '$script'"
else
sh -c "$script"
fi
@@ -106,9 +89,9 @@
fi
echo adb push $maybe_sync "$1" "$DIR"
adb push $maybe_sync "$1" "$DIR"
- elif is_cross_compilation "$OUT"; then
- echo scp "$1" "$TARGET:$DIR"
- scp "$1" "$TARGET:$DIR"
+ elif is_ssh_target; then
+ echo scp "$1" "$SSH_TARGET:$DIR"
+ scp "$1" "$SSH_TARGET:$DIR"
else
echo cp "$1" "$DIR"
cp "$1" "$DIR"
@@ -119,9 +102,9 @@
if is_android "$OUT"; then
echo adb pull "$DIR/$1" "$2"
adb pull "$DIR/$1" "$2"
- elif is_cross_compilation "$OUT"; then
- echo scp "$TARGET:$DIR/$1" "$2"
- scp "$TARGET:$DIR/$1" "$2"
+ elif is_ssh_target; then
+ echo scp "$SSH_TARGET:$DIR/$1" "$2"
+ scp "$SSH_TARGET:$DIR/$1" "$2"
else
echo mv "$DIR/$1" "$2"
mv "$DIR/$1" "$2"
@@ -131,15 +114,17 @@
BACKGROUND=0
SKIP_CONVERTERS=0
TMUX_LAYOUT="even-vertical"
+CPU_MASK=""
-while getopts "bl:nt:c:C:" o; do
+while getopts "bl:nt:c:C:z:" o; do
case "$o" in
b) BACKGROUND=1 ;;
l) TMUX_LAYOUT=${OPTARG} ;;
n) SKIP_CONVERTERS=1 ;;
- t) TARGET=${OPTARG} ;;
+ t) SSH_TARGET=${OPTARG} ;;
c) CONFIG=${OPTARG} ;;
C) OUT=${OPTARG} ;;
+ z) CPU_MASK=${OPTARG} ;;
*)
echo "Invalid option $o"
exit
@@ -157,16 +142,17 @@
echo ""
echo "Options:"
echo " -b run in the background"
- echo " -l tmux pane layout"
+ echo " -l LAYOUT tmux pane layout"
echo " -n skip post-trace convertors"
echo " -t TARGET SSH device target"
echo " -c CONFIG trace configuration file"
echo " -C OUTPUT output directory"
+ echo " -z MASK constrain binaries to given cpu mask (taskset syntax)"
echo ""
echo "Environment variables:"
- echo " TARGET SSH device target"
+ echo " SSH_TARGET SSH device target"
echo " CONFIG trace configuration file"
- echo " OUTPUT output directory"
+ echo " OUT output directory"
exit 1
fi
@@ -179,10 +165,10 @@
fi
# If we are cross-compiling we need to know the SSH target
-if is_cross_compilation "$OUT" && ! ssh -q "$TARGET" exit; then
- echo "TARGET=$TARGET doesn't look like a valid SSH target."
+if is_ssh_target && ! ssh -q "$SSH_TARGET" exit; then
+ echo "SSH_TARGET=$SSH_TARGET doesn't look like a valid SSH target."
echo "Please specify a SSH cross-compilation target by doing:"
- echo " export TARGET=<user>@<host> $0"
+ echo " export SSH_TARGET=<user>@<host> $0"
exit 1
fi
@@ -192,8 +178,8 @@
if is_android "$OUT"; then
DIR=/data/local/tmp
-elif is_cross_compilation "$OUT"; then
- DIR=$(ssh "$TARGET" mktemp -d $TMPDIR/perfetto.XXXXXX)
+elif is_ssh_target; then
+ DIR=$(ssh "$SSH_TARGET" mktemp -d $TMPDIR/perfetto.XXXXXX)
elif is_mac; then
DIR=$(mktemp -d $TMPDIR/perfetto.XXXXXX)
else
@@ -245,6 +231,10 @@
POSTFIX=""
+if [[ -n "$CPU_MASK" ]]; then
+ PREFIX="$PREFIX taskset $CPU_MASK"
+fi
+
if [[ BACKGROUND -eq 1 ]]; then
PREFIX="$PREFIX nohup"
POSTFIX=" &> /dev/null &"
@@ -290,31 +280,31 @@
sleep 2
tmux select-pane -t 1
-if is_cross_compilation "$OUT"; then
- tmux send-keys "ssh $TARGET" Enter
+if is_ssh_target; then
+ tmux send-keys "ssh $SSH_TARGET" Enter
fi
tmux_ensure_bash
tmux send-keys "PS1='[traced]$ '" Enter
tmux send-keys "cd $DIR" Enter
-tmux send-keys "$PREFIX ./traced 2>&1 | tee traced.log $POSTFIX" Enter
+tmux send-keys "$PREFIX ./traced $POSTFIX" Enter
tmux select-pane -t 0
-if is_cross_compilation "$OUT"; then
- tmux send-keys "ssh $TARGET" Enter
+if is_ssh_target; then
+ tmux send-keys "ssh $SSH_TARGET" Enter
fi
tmux_ensure_bash
tmux send-keys "PS1='[traced_probes]$ '" Enter
tmux send-keys "cd $DIR" Enter
-tmux send-keys "$PREFIX ./traced_probes 2>&1 | tee traced_probes.log $POSTFIX" Enter
+tmux send-keys "$PREFIX ./traced_probes $POSTFIX" Enter
tmux select-pane -t 2
-if is_cross_compilation "$OUT"; then
- tmux send-keys "ssh $TARGET" Enter
+if is_ssh_target; then
+ tmux send-keys "ssh $SSH_TARGET" Enter
fi
tmux_ensure_bash
tmux send-keys "PS1='[consumer]$ '" Enter
tmux send-keys "cd $DIR" Enter
-tmux send-keys "$PREFIX ./perfetto $CMD_OPTS -c $CONFIG_DEVICE_PATH -o trace 2>&1 | tee perfetto.log $POSTFIX"
+tmux send-keys "$PREFIX ./perfetto $CMD_OPTS -c $CONFIG_DEVICE_PATH -o trace $POSTFIX"
# Select consumer pane.
tmux select-pane -t 2
diff --git a/tools/trace_processor b/tools/trace_processor
index 00ac9b0..c8fb203 100755
--- a/tools/trace_processor
+++ b/tools/trace_processor
@@ -31,8 +31,8 @@
import urllib
TRACE_PROCESSOR_SHELL_SHAS = {
- 'linux': 'a610c3f4a65f543a3d1ef8f3c7063b071435332d',
- 'mac': 'fe8d751086265c4da258fa2364e07c069a1e0427',
+ 'linux': '8e7ce3affdaa1d1f66a0bd58368782784bf6c9a6',
+ 'mac':'78709d06d30260119f31963143073dde24f03da0',
}
TRACE_PROCESSOR_SHELL_PATH = tempfile.gettempdir()
TRACE_PROCESSOR_SHELL_BASE_URL = (
diff --git a/tools/trace_to_text/local_symbolizer.cc b/tools/trace_to_text/local_symbolizer.cc
index 8b219a4..6ec1d96 100644
--- a/tools/trace_to_text/local_symbolizer.cc
+++ b/tools/trace_to_text/local_symbolizer.cc
@@ -18,6 +18,7 @@
#include "tools/trace_to_text/local_symbolizer.h"
#include "perfetto/ext/base/string_splitter.h"
+#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/utils.h"
#include <elf.h>
@@ -52,7 +53,8 @@
n = 0;
} while (rd > 1);
return lines;
-};
+}
+
struct Elf32 {
using Ehdr = Elf32_Ehdr;
@@ -165,6 +167,16 @@
return *endptr == '\0' && parsed_line_no >= 0;
}
+std::string SplitBuildID(const std::string& hex_build_id) {
+ if (hex_build_id.size() < 3) {
+ PERFETTO_DFATAL_OR_ELOG("Invalid build-id (< 3 char) %s",
+ hex_build_id.c_str());
+ return {};
+ }
+
+ return hex_build_id.substr(0, 2) + "/" + hex_build_id.substr(2);
+}
+
} // namespace
base::Optional<std::string> LocalBinaryFinder::FindBinary(
@@ -232,7 +244,9 @@
std::string dirname;
for (base::StringSplitter sp(abspath, '/'); sp.Next();) {
- dirname += "/" + filename;
+ if (!dirname.empty())
+ dirname += "/";
+ dirname += filename;
filename = sp.cur_token();
}
@@ -243,12 +257,18 @@
// * only filename of library file relative to root.
// * only filename of library file relative to root, but with base.apk!
// removed from filename.
+ // * in the subdirectory .build-id: the first two hex digits of the build-id
+ // as subdirectory, then the rest of the hex digits, with ".debug"appended.
+ // See
+ // https://fedoraproject.org/wiki/RolandMcGrath/BuildID#Find_files_by_build_ID
//
- // For example, "/system/lib/base.apk!foo.so" is looked for at
+ // For example, "/system/lib/base.apk!foo.so" with build id abcd1234,
+ // is looked for at
// * $ROOT/system/lib/base.apk!foo.so
// * $ROOT/system/lib/foo.so
// * $ROOT/base.apk!foo.so
// * $ROOT/foo.so
+ // * $ROOT/.build-id/ab/cd1234.debug
std::string symbol_file = root_str + "/" + dirname + "/" + filename;
if (access(symbol_file.c_str(), F_OK) == 0 &&
@@ -275,6 +295,16 @@
return {symbol_file};
}
+ std::string hex_build_id = base::ToHex(build_id.c_str(), build_id.size());
+ std::string split_hex_build_id = SplitBuildID(hex_build_id);
+ if (!split_hex_build_id.empty()) {
+ symbol_file =
+ root_str + "/" + ".build-id" + "/" + split_hex_build_id + ".debug";
+ if (access(symbol_file.c_str(), F_OK) == 0 &&
+ IsCorrectFile(symbol_file, build_id))
+ return {symbol_file};
+ }
+
return base::nullopt;
}
@@ -315,7 +345,7 @@
uint64_t address) {
std::vector<SymbolizedFrame> result;
- if (PERFETTO_EINTR(dprintf(subprocess_.write_fd(), "%s 0x%lx\n",
+ if (PERFETTO_EINTR(dprintf(subprocess_.write_fd(), "%s 0x%" PRIx64 "\n",
binary.c_str(), address)) < 0) {
PERFETTO_ELOG("Failed to write to llvm-symbolizer.");
return result;
diff --git a/tools/trace_to_text/pprof_builder.cc b/tools/trace_to_text/pprof_builder.cc
index 7a41663..f3f1fe1 100644
--- a/tools/trace_to_text/pprof_builder.cc
+++ b/tools/trace_to_text/pprof_builder.cc
@@ -31,6 +31,7 @@
#include "tools/trace_to_text/utils.h"
#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_utils.h"
#include "protos/perfetto/trace/profiling/profile_common.pb.h"
#include "protos/perfetto/trace/profiling/profile_packet.pb.h"
@@ -67,15 +68,6 @@
using GFunction = ::perfetto::third_party::perftools::profiles::Function;
using GSample = ::perfetto::third_party::perftools::profiles::Sample;
-std::string ToHex(const std::string& build_id) {
- std::string hex_build_id(2 * build_id.size() + 1, ' ');
- for (size_t i = 0; i < build_id.size(); ++i)
- snprintf(&(hex_build_id[2 * i]), 3, "%02hhx", build_id[i]);
- // Remove the trailing nullbyte.
- hex_build_id.resize(2 * build_id.size());
- return hex_build_id;
-}
-
enum Strings : int64_t {
kEmpty = 0,
kObjects,
@@ -163,7 +155,7 @@
auto str_it = string_lookup_.find(mapping.build_id());
if (str_it != string_lookup_.end()) {
const std::string& build_id = str_it->second;
- gmapping->set_build_id(InternInGProfile(ToHex(build_id)));
+ gmapping->set_build_id(InternInGProfile(base::ToHex(build_id)));
}
return true;
}
@@ -303,17 +295,17 @@
};
bool DumpProfilePacket(const std::vector<ProfilePacket>& packet_fragments,
- const std::vector<InternedData>& interned_data,
+ const SequencedBundle& bundle,
std::vector<SerializedProfile>* output,
Symbolizer* symbolizer) {
TraceSymbolTable symbol_table(symbolizer);
- if (!symbol_table.Visit(packet_fragments, interned_data))
+ if (!symbol_table.Visit(packet_fragments, bundle))
return false;
if (!symbol_table.Finalize())
return false;
GProfileWriter writer(&symbol_table);
- if (!writer.Visit(packet_fragments, interned_data))
+ if (!writer.Visit(packet_fragments, bundle))
return false;
if (!writer.Finalize())
@@ -344,9 +336,8 @@
return VisitCompletePacket(
input, [output, symbolizer](
uint32_t, const std::vector<ProfilePacket>& packet_fragments,
- const std::vector<InternedData>& interned_data) {
- return DumpProfilePacket(packet_fragments, interned_data, output,
- symbolizer);
+ const SequencedBundle& bundle) {
+ return DumpProfilePacket(packet_fragments, bundle, output, symbolizer);
});
}
diff --git a/tools/trace_to_text/profile_visitor.cc b/tools/trace_to_text/profile_visitor.cc
index 065222d..a2b729b 100644
--- a/tools/trace_to_text/profile_visitor.cc
+++ b/tools/trace_to_text/profile_visitor.cc
@@ -16,6 +16,7 @@
#include "tools/trace_to_text/profile_visitor.h"
+#include <unordered_map>
#include "protos/perfetto/trace/trace.pb.h"
#include "protos/perfetto/trace/trace_packet.pb.h"
@@ -32,16 +33,33 @@
using ::perfetto::protos::Mapping;
using ::perfetto::protos::ProfiledFrameSymbols;
using ::perfetto::protos::ProfilePacket;
+
+struct ProfilePackets {
+ uint32_t seq_id;
+ std::vector<protos::ProfilePacket> packets;
+};
+
+bool IsPacketIndexContiguous(
+ const std::vector<perfetto::protos::ProfilePacket>& packets) {
+ for (size_t i = 1; i < packets.size(); ++i) {
+ // Ensure we are not missing a chunk.
+ if (packets[i - 1].index() + 1 != packets[i].index()) {
+ return false;
+ }
+ }
+ return true;
+}
} // namespace
-bool ProfileVisitor::Visit(const std::vector<ProfilePacket>& packet_fragments,
- const std::vector<InternedData>& interned_data) {
+bool ProfileVisitor::Visit(
+ const std::vector<protos::ProfilePacket>& packet_fragments,
+ const SequencedBundle& bundle) {
for (const ProfilePacket& packet : packet_fragments) {
for (const InternedString& interned_string : packet.strings())
if (!AddInternedString(interned_string))
return false;
}
- for (const InternedData& data : interned_data) {
+ for (const InternedData& data : bundle.interned_data) {
for (const InternedString& interned_string : data.build_ids())
if (!AddInternedString(interned_string))
return false;
@@ -54,17 +72,21 @@
for (const InternedString& interned_string : data.source_paths())
if (!AddInternedString(interned_string))
return false;
+ // TODO (140860736): This should be outside the interned section.
for (const ProfiledFrameSymbols& pfs : data.profiled_frame_symbols())
if (!AddProfiledFrameSymbols(pfs))
return false;
}
+ for (const ProfiledFrameSymbols& pfs : bundle.symbols)
+ if (!AddProfiledFrameSymbols(pfs))
+ return false;
for (const ProfilePacket& packet : packet_fragments) {
for (const Callstack& callstack : packet.callstacks())
if (!AddCallstack(callstack))
return false;
}
- for (const InternedData& data : interned_data) {
+ for (const InternedData& data : bundle.interned_data) {
for (const Callstack& callstack : data.callstacks())
if (!AddCallstack(callstack))
return false;
@@ -75,7 +97,7 @@
if (!AddMapping(mapping))
return false;
}
- for (const InternedData& data : interned_data) {
+ for (const InternedData& data : bundle.interned_data) {
for (const Mapping& callstack : data.mappings()) {
if (!AddMapping(callstack))
return false;
@@ -88,7 +110,7 @@
return false;
}
}
- for (const InternedData& data : interned_data) {
+ for (const InternedData& data : bundle.interned_data) {
for (const Frame& frame : data.frames()) {
if (!AddFrame(frame))
return false;
@@ -99,5 +121,54 @@
ProfileVisitor::~ProfileVisitor() = default;
+bool VisitCompletePacket(
+ std::istream* input,
+ const std::function<bool(uint32_t,
+ const std::vector<protos::ProfilePacket>&,
+ const SequencedBundle&)>& fn) {
+ // Rolling profile packets per seq id. Cleared on finalization.
+ std::unordered_map<uint32_t, std::vector<protos::ProfilePacket>>
+ rolling_profile_packets_by_seq;
+ std::vector<ProfilePackets> complete_profile_packets;
+ // Append-only interned data and symbols by seq id
+ std::unordered_map<uint32_t, SequencedBundle> bundle_by_seq;
+ ForEachPacketInTrace(input, [&rolling_profile_packets_by_seq,
+ &complete_profile_packets, &bundle_by_seq](
+ const protos::TracePacket& packet) {
+ uint32_t seq_id = packet.trusted_packet_sequence_id();
+ if (packet.has_interned_data()) {
+ bundle_by_seq[seq_id].interned_data.emplace_back(packet.interned_data());
+ }
+ if (packet.has_appended_data()) {
+ std::copy(packet.appended_data().profiled_frame_symbols().cbegin(),
+ packet.appended_data().profiled_frame_symbols().cend(),
+ std::back_inserter(bundle_by_seq[seq_id].symbols));
+ }
+
+ if (packet.has_profile_packet()) {
+ std::vector<protos::ProfilePacket>& rolling_profile_packets =
+ rolling_profile_packets_by_seq[seq_id];
+ rolling_profile_packets.emplace_back(packet.profile_packet());
+
+ if (!packet.profile_packet().continued()) {
+ if (IsPacketIndexContiguous(rolling_profile_packets)) {
+ complete_profile_packets.push_back({seq_id, rolling_profile_packets});
+ rolling_profile_packets_by_seq.erase(seq_id);
+ }
+ }
+ }
+ });
+
+ bool success = true;
+ for (const auto& packets : complete_profile_packets) {
+ success &=
+ fn(packets.seq_id, packets.packets, bundle_by_seq[packets.seq_id]);
+ }
+ if (!rolling_profile_packets_by_seq.empty()) {
+ PERFETTO_ELOG("WARNING: Truncated heap dump.");
+ return false;
+ }
+ return success;
+}
} // namespace trace_to_text
} // namespace perfetto
diff --git a/tools/trace_to_text/profile_visitor.h b/tools/trace_to_text/profile_visitor.h
index 54c3ec2..4723f14 100644
--- a/tools/trace_to_text/profile_visitor.h
+++ b/tools/trace_to_text/profile_visitor.h
@@ -31,10 +31,14 @@
namespace perfetto {
namespace trace_to_text {
+struct SequencedBundle {
+ std::vector<protos::InternedData> interned_data;
+ std::vector<protos::ProfiledFrameSymbols> symbols;
+};
+
class ProfileVisitor {
public:
- bool Visit(const std::vector<protos::ProfilePacket>&,
- const std::vector<protos::InternedData>&);
+ bool Visit(const std::vector<protos::ProfilePacket>&, const SequencedBundle&);
virtual bool AddInternedString(
const protos::InternedString& interned_string) = 0;
virtual bool AddCallstack(const protos::Callstack& callstack) = 0;
@@ -45,54 +49,11 @@
virtual ~ProfileVisitor();
};
-template <typename F>
-bool VisitCompletePacket(std::istream* input, F fn) {
- std::map<uint32_t, std::vector<protos::ProfilePacket>>
- rolling_profile_packets_by_seq;
- std::map<uint32_t, std::vector<protos::InternedData>>
- rolling_interned_data_by_seq;
- bool success = true;
- ForEachPacketInTrace(input, [&rolling_profile_packets_by_seq,
- &rolling_interned_data_by_seq, &success,
- &fn](const protos::TracePacket& packet) {
- uint32_t seq_id = packet.trusted_packet_sequence_id();
- if (packet.has_interned_data())
- rolling_interned_data_by_seq[seq_id].emplace_back(packet.interned_data());
-
- if (!packet.has_profile_packet())
- return;
-
- rolling_profile_packets_by_seq[seq_id].emplace_back(
- packet.profile_packet());
-
- const std::vector<protos::InternedData>& rolling_interned_data =
- rolling_interned_data_by_seq[seq_id];
- const std::vector<protos::ProfilePacket>& rolling_profile_packets =
- rolling_profile_packets_by_seq[seq_id];
-
- if (!packet.profile_packet().continued()) {
- for (size_t i = 1; i < rolling_profile_packets.size(); ++i) {
- // Ensure we are not missing a chunk.
- if (rolling_profile_packets[i - 1].index() + 1 !=
- rolling_profile_packets[i].index()) {
- success = false;
- return;
- }
- }
- if (!fn(seq_id, rolling_profile_packets, rolling_interned_data))
- success = false;
-
- // We do not clear rolling_interned_data, as it is globally scoped.
- rolling_profile_packets_by_seq.erase(seq_id);
- }
- });
-
- if (!rolling_profile_packets_by_seq.empty()) {
- PERFETTO_ELOG("WARNING: Truncated heap dump.");
- return false;
- }
- return success;
-}
+bool VisitCompletePacket(
+ std::istream* input,
+ const std::function<bool(uint32_t,
+ const std::vector<protos::ProfilePacket>&,
+ const SequencedBundle&)>& fn);
} // namespace trace_to_text
} // namespace perfetto
diff --git a/tools/trace_to_text/symbolize_profile.cc b/tools/trace_to_text/symbolize_profile.cc
index 0902450..c7c64c2 100644
--- a/tools/trace_to_text/symbolize_profile.cc
+++ b/tools/trace_to_text/symbolize_profile.cc
@@ -54,9 +54,9 @@
input, [&output, &symbolizer](
uint32_t seq_id,
const std::vector<protos::ProfilePacket>& packet_fragments,
- const std::vector<protos::InternedData>& interned_data) {
+ const SequencedBundle& bundle) {
TraceSymbolTable symbol_table(symbolizer.get());
- if (!symbol_table.Visit(packet_fragments, interned_data))
+ if (!symbol_table.Visit(packet_fragments, bundle))
return false;
symbol_table.Finalize();
symbol_table.WriteResult(output, seq_id);
diff --git a/tools/trace_to_text/trace_symbol_table.cc b/tools/trace_to_text/trace_symbol_table.cc
index c171993..b345160 100644
--- a/tools/trace_to_text/trace_symbol_table.cc
+++ b/tools/trace_to_text/trace_symbol_table.cc
@@ -96,12 +96,13 @@
void TraceSymbolTable::WriteResult(std::ostream* output,
uint32_t seq_id) const {
- protos::TracePacket intern_packet;
- intern_packet.set_trusted_packet_sequence_id(seq_id);
- std::vector<protos::TracePacket> frame_symbol_packets;
+ protos::TracePacket appended_packet;
+ appended_packet.set_trusted_packet_sequence_id(seq_id);
+
auto max_string_intern_id = max_string_intern_id_;
std::map<std::string, uint64_t> new_interned_strings;
- protos::InternedData* interned_data = intern_packet.mutable_interned_data();
+ protos::InternedData* interned_data = appended_packet.mutable_interned_data();
+ protos::AppendedData* appended_data = appended_packet.mutable_appended_data();
for (const auto& p : symbols_for_frame_) {
uint64_t frame_iid = p.first;
const std::vector<SymbolizedFrame>& frames = p.second;
@@ -126,25 +127,16 @@
}
}
- protos::TracePacket symbol_packet;
- symbol_packet.set_trusted_packet_sequence_id(seq_id);
protos::ProfiledFrameSymbols* sym =
- symbol_packet.mutable_profiled_frame_symbols();
+ appended_data->add_profiled_frame_symbols();
sym->set_frame_iid(frame_iid);
for (const SymbolizedFrame& frame : frames) {
sym->add_function_name_id(new_interned_strings[frame.function_name]);
sym->add_line_number(frame.line);
sym->add_file_name_id(new_interned_strings[frame.file_name]);
}
- // TODO(138725313): Cleanup - this should be outside the interned section.
- *interned_data->add_profiled_frame_symbols() = *sym;
-
- frame_symbol_packets.push_back(std::move(symbol_packet));
}
- WriteTracePacket(intern_packet.SerializeAsString(), output);
- for (const auto& frame_symbol_packet : frame_symbol_packets) {
- WriteTracePacket(frame_symbol_packet.SerializeAsString(), output);
- }
+ WriteTracePacket(appended_packet.SerializeAsString(), output);
}
bool TraceSymbolTable::AddProfiledFrameSymbols(
diff --git a/tools/traceconv b/tools/traceconv
index 71675ed..fc5f213 100755
--- a/tools/traceconv
+++ b/tools/traceconv
@@ -33,8 +33,8 @@
# Keep this in sync with the SHAs in catapult file
# systrace/systrace/tracing_agents/atrace_from_file_agent.py.
TRACE_TO_TEXT_SHAS = {
- 'linux': 'd67f9f3e3beb93664578c8b0300ab98e828ecb29',
- 'mac': '62b27f343640d0778f1324fa90940381561bef99',
+ 'linux': 'bbd4849ccc18e216c827a9ae14361910f29307c4',
+ 'mac':'12467778e99769b8c37df037043cbb99475b3a0a',
}
TRACE_TO_TEXT_PATH = tempfile.gettempdir()
TRACE_TO_TEXT_BASE_URL = (
diff --git a/ui/src/assets/common.scss b/ui/src/assets/common.scss
index e142346..6182663 100644
--- a/ui/src/assets/common.scss
+++ b/ui/src/assets/common.scss
@@ -326,6 +326,10 @@
opacity: 0;
}
+ .track-button.show {
+ opacity: 1;
+ }
+
&:hover .track-button{
opacity: 1;
}
diff --git a/ui/src/assets/record.scss b/ui/src/assets/record.scss
index c5326b9..8c7a840 100644
--- a/ui/src/assets/record.scss
+++ b/ui/src/assets/record.scss
@@ -803,6 +803,39 @@
box-shadow: 0 0 6px #ccc;
}
}
+ // Stop/cancel buttons
+ .buttons {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: auto;
+ height: 70px;
+ >* {
+ @include transition(0.2s);
+ cursor: pointer;
+ border-radius: 10px;
+ text-align: center;
+ margin: 3px;
+ background-color: #eee;
+ font-family: 'Raleway', sans-serif;
+ flex-grow: 1;
+ font-size: 17px;
+ @media (max-width: 1280px) {
+ font-size: 1.6vw;
+ }
+ padding: 7px;
+
+ &:hover {
+ background-color: hsl(88, 50%, 84%);
+ box-shadow: 0 0 4px 0px #999;
+ }
+
+ &.selected {
+ background-color: hsl(88, 50%, 67%);
+ box-shadow: 0 0 4px 0px #999;
+ }
+ }
+ }
progress {
-webkit-appearance: none;
diff --git a/ui/src/base/string_utils.ts b/ui/src/base/string_utils.ts
new file mode 100644
index 0000000..0ad7dd3
--- /dev/null
+++ b/ui/src/base/string_utils.ts
@@ -0,0 +1,30 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+export function uint8ArrayToBase64(buffer: Uint8Array): string {
+ return btoa(uint8ArrayToString(buffer));
+}
+
+export function uint8ArrayToString(buffer: Uint8Array): string {
+ return String.fromCharCode.apply(null, Array.from(buffer));
+}
+
+export function stringToUint8Array(str: string): Uint8Array {
+ const bufView = new Uint8Array(new ArrayBuffer(str.length));
+ const strLen = str.length;
+ for (let i = 0; i < strLen; i++) {
+ bufView[i] = str.charCodeAt(i);
+ }
+ return bufView;
+}
\ No newline at end of file
diff --git a/ui/src/base/string_utils_jsdomtest.ts b/ui/src/base/string_utils_jsdomtest.ts
new file mode 100644
index 0000000..e8bae93
--- /dev/null
+++ b/ui/src/base/string_utils_jsdomtest.ts
@@ -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.
+
+import {
+ stringToUint8Array,
+ uint8ArrayToBase64,
+ uint8ArrayToString
+} from './string_utils';
+
+test('uint8ArrayToBase64', () => {
+ const bytes = [...'Hello, world'].map(c => c.charCodeAt(0));
+ const buffer = new Uint8Array(bytes);
+ expect(uint8ArrayToBase64(buffer)).toEqual('SGVsbG8sIHdvcmxk');
+});
+
+test('stringToBufferToString', () => {
+ const testString = 'Hello world!';
+ const buffer = stringToUint8Array(testString);
+ const convertedBack = uint8ArrayToString(buffer);
+ expect(testString).toEqual(convertedBack);
+});
+
+test('bufferToStringToBuffer', () => {
+ const bytes = [...'Hello, world'].map(c => c.charCodeAt(0));
+ const buffer = new Uint8Array(bytes);
+ const toString = uint8ArrayToString(buffer);
+ const convertedBack = stringToUint8Array(toString);
+ expect(convertedBack).toEqual(buffer);
+});
diff --git a/ui/src/chrome_extension/chrome_tracing_controller.ts b/ui/src/chrome_extension/chrome_tracing_controller.ts
index 512e633..d46f6b7 100644
--- a/ui/src/chrome_extension/chrome_tracing_controller.ts
+++ b/ui/src/chrome_extension/chrome_tracing_controller.ts
@@ -22,13 +22,15 @@
GetTraceStatsResponse,
ReadBuffersResponse
} from '../controller/consumer_port_types';
+import {extractTraceConfig} from '../controller/record_controller';
+import {RpcConsumerPort} from '../controller/record_controller_interfaces';
import {perfetto} from '../gen/protos';
import {DevToolsSocket} from './devtools_socket';
const CHUNK_SIZE: number = 1024 * 1024 * 64;
-export class ChromeTracingController {
+export class ChromeTracingController extends RpcConsumerPort {
private streamHandle: string|undefined = undefined;
private uiPort: chrome.runtime.Port;
private api: ProtocolProxyApi.ProtocolApi;
@@ -36,6 +38,16 @@
private lastBufferUsageEvent: Protocol.Tracing.BufferUsageEvent|undefined;
constructor(port: chrome.runtime.Port) {
+ super({
+ onConsumerPortResponse: (message: ConsumerPortResponse) =>
+ this.uiPort.postMessage(message),
+
+ onError: (error: string) =>
+ this.uiPort.postMessage({type: 'ChromeExtensionError', error}),
+
+ onStatus: (status) =>
+ this.uiPort.postMessage({type: 'ChromeExtensionStatus', status})
+ });
this.uiPort = port;
this.devtoolsSocket = new DevToolsSocket();
this.devtoolsSocket.on('close', () => this.resetState());
@@ -45,18 +57,10 @@
this.api.Tracing.on('bufferUsage', this.onBufferUsage.bind(this));
}
- sendMessage(message: ConsumerPortResponse) {
- this.uiPort.postMessage(message);
- }
-
- sendErrorMessage(error: string) {
- this.uiPort.postMessage({type: 'ErrorResponse', result: {error}});
- }
-
- onMessage(request: {method: string, traceConfig: Uint8Array}) {
- switch (request.method) {
+ handleCommand(methodName: string, requestData: Uint8Array) {
+ switch (methodName) {
case 'EnableTracing':
- this.enableTracing(request);
+ this.enableTracing(requestData);
break;
case 'FreeBuffers':
this.freeBuffers();
@@ -74,19 +78,25 @@
this.getCategories();
break;
default:
- this.sendErrorMessage('Action not recognised');
- console.log('Received not recognized message: ', request.method);
+ this.sendErrorMessage('Action not recognized');
+ console.log('Received not recognized message: ', methodName);
break;
}
}
- enableTracing(request: {method: string, traceConfig: Uint8Array}) {
+ enableTracing(enableTracingRequest: Uint8Array) {
this.resetState();
- const traceConfig = TraceConfig.decode(new Uint8Array(request.traceConfig));
+ const traceConfigProto = extractTraceConfig(enableTracingRequest);
+ if (!traceConfigProto) {
+ this.sendErrorMessage('Invalid trace config');
+ return;
+ }
+ const traceConfig = TraceConfig.decode(traceConfigProto);
const chromeConfig = this.extractChromeConfig(traceConfig);
this.handleStartTracing(chromeConfig);
}
+ // TODO(nicomazz): write unit test for this
extractChromeConfig(perfettoConfig: TraceConfig):
Protocol.Tracing.TraceConfig {
for (const ds of perfettoConfig.dataSources) {
@@ -106,7 +116,6 @@
}
async readBuffers(offset = 0) {
- // TODO(nicomazz): Add error handling also in the frontend.
if (!this.devtoolsSocket.isAttached() || this.streamHandle === undefined) {
this.sendErrorMessage('No tracing session to read from');
return;
diff --git a/ui/src/chrome_extension/index.ts b/ui/src/chrome_extension/index.ts
index 1bc5e36..5bce4ec 100644
--- a/ui/src/chrome_extension/index.ts
+++ b/ui/src/chrome_extension/index.ts
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {stringToUint8Array} from '../base/string_utils';
import {ChromeTracingController} from './chrome_tracing_controller';
let chromeTraceController: ChromeTracingController|undefined = undefined;
@@ -24,14 +25,19 @@
});
function onUIMessage(
- message: {method: string, traceConfig: Uint8Array},
- port: chrome.runtime.Port) {
+ message: {method: string, requestData: string}, port: chrome.runtime.Port) {
if (message.method === 'ExtensionVersion') {
port.postMessage({version: chrome.runtime.getManifest().version});
return;
}
- // In the future, more targets will be supported.
- if (chromeTraceController) chromeTraceController.onMessage(message);
+ console.assert(chromeTraceController !== undefined);
+ if (!chromeTraceController) return;
+ // ChromeExtensionConsumerPort sends the request data as string because
+ // chrome.runtime.port doesn't support ArrayBuffers.
+ const requestDataArray: Uint8Array = message.requestData ?
+ stringToUint8Array(message.requestData) :
+ new Uint8Array();
+ chromeTraceController.handleCommand(message.method, requestDataArray);
}
function enableOnlyOnPerfettoHost() {
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index 0850d3b..bd78842 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -153,6 +153,11 @@
state.visibleTracks = args.tracks;
},
+ updateTrackConfig(state: StateDraft, args: {id: string, config: {}}) {
+ if (state.tracks[args.id] === undefined) return;
+ state.tracks[args.id].config = args.config;
+ },
+
executeQuery(
state: StateDraft,
args: {queryId: string; engineId: string; query: string}): void {
@@ -359,6 +364,23 @@
};
},
+ selectCounter(
+ state: StateDraft, args: {leftTs: number, rightTs: number, id: number}):
+ void {
+ state.currentSelection = {
+ kind: 'COUNTER',
+ leftTs: args.leftTs,
+ rightTs: args.rightTs,
+ id: args.id
+ };
+ },
+
+ selectHeapDump(
+ state: StateDraft, args: {id: number, upid: number, ts: number}): void {
+ state.currentSelection =
+ {kind: 'HEAP_DUMP', id: args.id, upid: args.upid, ts: args.ts};
+ },
+
selectChromeSlice(state: StateDraft, args: {slice_id: number}): void {
state.currentSelection = {kind: 'CHROME_SLICE', id: args.slice_id};
},
@@ -398,12 +420,18 @@
startRecording(state: StateDraft): void {
state.recordingInProgress = true;
state.lastRecordingError = undefined;
+ state.recordingCancelled = false;
},
stopRecording(state: StateDraft): void {
state.recordingInProgress = false;
},
+ cancelRecording(state: StateDraft): void {
+ state.recordingInProgress = false;
+ state.recordingCancelled = true;
+ },
+
setExtensionAvailable(state: StateDraft, args: {available: boolean}): void {
state.extensionInstalled = args.available;
},
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index 7485ad5..6288dd1 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -23,7 +23,8 @@
[P in keyof T]: T[P];
}&{lastUpdate: number};
-export type OmniboxState = Timestamped<{omnibox: string;}>;
+export type OmniboxState =
+ Timestamped<{omnibox: string; mode: 'SEARCH' | 'COMMAND'}>;
export type VisibleState =
Timestamped<{startSec: number; endSec: number; resolution: number;}>;
@@ -101,6 +102,20 @@
id: number;
}
+export interface CounterSelection {
+ kind: 'COUNTER';
+ leftTs: number;
+ rightTs: number;
+ id: number;
+}
+
+export interface HeapDumpSelection {
+ kind: 'HEAP_DUMP';
+ id: number;
+ upid: number;
+ ts: number;
+}
+
export interface ChromeSliceSelection {
kind: 'CHROME_SLICE';
id: number;
@@ -121,8 +136,9 @@
cpu: number;
}
-type Selection = NoteSelection|SliceSelection|ChromeSliceSelection|
- TimeSpanSelection|ThreadStateSelection;
+type Selection =
+ NoteSelection|SliceSelection|CounterSelection|HeapDumpSelection|
+ ChromeSliceSelection|TimeSpanSelection|ThreadStateSelection;
export interface LogsPagination {
offset: number;
@@ -184,6 +200,7 @@
* Trace recording
*/
recordingInProgress: boolean;
+ recordingCancelled: boolean;
extensionInstalled: boolean;
androidDeviceConnected?: AdbRecordingTarget;
availableDevices: AdbRecordingTarget[];
@@ -237,7 +254,6 @@
screenRecord: boolean;
gpuFreq: boolean;
- gpuSched: boolean;
ftrace: boolean;
atrace: boolean;
@@ -287,7 +303,6 @@
screenRecord: false,
gpuFreq: false,
- gpuSched: false,
ftrace: false,
atrace: false,
@@ -347,6 +362,7 @@
omniboxState: {
lastUpdate: 0,
omnibox: '',
+ mode: 'SEARCH',
},
visibleState: {
@@ -371,6 +387,7 @@
scrubbingEnabled: false,
flagPauseEnabled: false,
recordingInProgress: false,
+ recordingCancelled: false,
extensionInstalled: false,
androidDeviceConnected: undefined,
availableDevices: [],
diff --git a/ui/src/controller/adb.ts b/ui/src/controller/adb.ts
index 15c9139..6ba9515 100644
--- a/ui/src/controller/adb.ts
+++ b/ui/src/controller/adb.ts
@@ -24,6 +24,8 @@
RSAPUBLICKEY = 3,
}
+const DEVICE_NOT_SET_ERROR = 'Device not set.';
+
// This class is a basic TypeScript implementation of adb that only supports
// shell commands. It is used to send the start tracing command to the connected
// android device, and to automatically pull the trace after the end of the
@@ -100,6 +102,15 @@
return new Promise<void>((resolve, _) => this.onConnected = resolve);
}
+ async disconnect(): Promise<void> {
+ if (!this.dev) {
+ console.error('adb disconnect() called with no device connected');
+ return;
+ }
+ this.dev.close();
+ this.dev = undefined;
+ }
+
async startAuthentication() {
// USB connected, now let's authenticate.
const VERSION =
@@ -109,7 +120,7 @@
}
findInterfaceAndEndpoint() {
- if (!this.dev) throw Error('Device not set');
+ if (!this.dev) throw Error(DEVICE_NOT_SET_ERROR);
for (const config of this.dev.configurations) {
for (const interface_ of config.interfaces) {
for (const alt of interface_.alternates) {
@@ -140,18 +151,18 @@
}
receiveDeviceMessages() {
- // TODO(nicomazz): find the best (and correct) way to stop this.
- try {
- this.recv().then(msg => {
- this.onMessage(msg);
- this.receiveDeviceMessages();
- });
- } catch (e) {
- // Then the usb connection is not available anymore, the recv will throw
- // an exception here.
- // TODO(nicomazz): Propagate this unconnected state to the UI.
- console.log('exception on recv: ', e);
- }
+ this.recv()
+ .then(msg => {
+ this.onMessage(msg);
+ this.receiveDeviceMessages();
+ })
+ .catch(e => {
+ // Ignore error with "DEVICE_NOT_SET_ERROR" message since it is always
+ // thrown after the device disconnects.
+ if (e.message !== DEVICE_NOT_SET_ERROR) {
+ console.error(`Exception in recv: ${e.name}. error: ${e.message}`);
+ }
+ });
}
async onMessage(msg: AdbMsg) {
@@ -244,6 +255,16 @@
});
}
+ async shellOutputAsString(cmd: string): Promise<string> {
+ const shell = await this.shell(cmd);
+
+ return new Promise<string>((resolve, _) => {
+ const output: string[] = [];
+ shell.onData = (str, _) => output.push(str);
+ shell.onClose = () => resolve(output.join());
+ });
+ }
+
async send(
cmd: CmdType, arg0: number, arg1: number, data?: Uint8Array|string) {
await this.sendMsg(AdbMsgImpl.create(
@@ -265,14 +286,10 @@
console.assert(res.status === 'ok');
const msg = AdbMsgImpl.decodeHeader(res.data!);
- let bytesLeft = msg.dataLen;
- let bytesReceived = 0;
- while (bytesLeft > 0) {
- const resp = await this.recvRaw(bytesLeft);
- for (let i = 0; i < resp.data!.byteLength; i++) {
- msg.data[bytesReceived++] = resp.data!.getUint8(i);
- }
- bytesLeft -= resp.data!.byteLength;
+ if (msg.dataLen > 0) {
+ const resp = await this.recvRaw(msg.dataLen);
+ msg.data = new Uint8Array(
+ resp.data!.buffer, resp.data!.byteOffset, resp.data!.byteLength);
}
if (this.useChecksum) {
console.assert(AdbOverWebUsb.checksum(msg.data) === msg.dataChecksum);
@@ -304,12 +321,12 @@
sendRaw(buf: Uint8Array): Promise<USBOutTransferResult> {
console.assert(buf.length <= this.maxPayload);
- if (!this.dev) throw Error('Device not set');
+ if (!this.dev) throw Error(DEVICE_NOT_SET_ERROR);
return this.dev.transferOut(this.usbWriteEpEndpoint, buf.buffer);
}
recvRaw(dataLen: number): Promise<USBInTransferResult> {
- if (!this.dev) throw Error('Device not set');
+ if (!this.dev) throw Error(DEVICE_NOT_SET_ERROR);
return this.dev.transferIn(this.usbReadEndpoint, dataLen);
}
}
@@ -363,7 +380,6 @@
}
this.adb.send('CLSE', this.localStreamId, this.remoteStreamId);
- this.doClose();
}
async write(msg: string|Uint8Array) {
diff --git a/ui/src/controller/adb_interfaces.ts b/ui/src/controller/adb_interfaces.ts
index 91dd653..2f22a2f 100644
--- a/ui/src/controller/adb_interfaces.ts
+++ b/ui/src/controller/adb_interfaces.ts
@@ -15,12 +15,16 @@
export interface Adb {
connect(device: USBDevice): Promise<void>;
+ disconnect(): Promise<void>;
shell(cmd: string): Promise<AdbStream>;
+ shellOutputAsString(cmd: string): Promise<string>;
}
export interface AdbStream {
onMessage(message: AdbMsg): void;
onData: (str: string, raw: Uint8Array) => void;
+ close(): void;
+
onConnect: VoidCallback;
onClose: VoidCallback;
}
@@ -29,9 +33,18 @@
connect(_: USBDevice): Promise<void> {
return Promise.resolve();
}
+
+ disconnect(): Promise<void> {
+ return Promise.resolve();
+ }
+
shell(_: string): Promise<AdbStream> {
return Promise.resolve(new MockAdbStream());
}
+
+ shellOutputAsString(_: string): Promise<string> {
+ return Promise.resolve('');
+ }
}
export class MockAdbStream implements AdbStream {
@@ -39,6 +52,7 @@
onConnect = () => {};
onClose = () => {};
onMessage = (_: AdbMsg) => {};
+ close() {}
}
export declare type CmdType =
diff --git a/ui/src/controller/adb_record_controller.ts b/ui/src/controller/adb_record_controller.ts
index f3d17cb..990053d 100644
--- a/ui/src/controller/adb_record_controller.ts
+++ b/ui/src/controller/adb_record_controller.ts
@@ -12,10 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {uint8ArrayToBase64} from '../base/string_utils';
+
import {Adb, AdbStream} from './adb_interfaces';
-import {ConsumerPortResponse, ReadBuffersResponse} from './consumer_port_types';
+import {ReadBuffersResponse} from './consumer_port_types';
import {globals} from './globals';
-import {RecordControllerMessage, uint8ArrayToBase64} from './record_controller';
+import {
+ extractDurationFromTraceConfig,
+ extractTraceConfig
+} from './record_controller';
+import {Consumer, RpcConsumerPort} from './record_controller_interfaces';
enum AdbState {
READY,
@@ -24,39 +30,20 @@
}
const DEFAULT_DESTINATION_FILE = '/data/misc/perfetto-traces/trace';
-export class AdbRecordController {
+export class AdbConsumerPort extends RpcConsumerPort {
// public for testing
traceDestFile = DEFAULT_DESTINATION_FILE;
private state = AdbState.READY;
private adb: Adb;
private device: USBDevice|undefined = undefined;
- private mainControllerCallback:
- (_: {data: ConsumerPortResponse|RecordControllerMessage}) => void;
+ private recordShell?: AdbStream;
- constructor(adb: Adb, mainControllerCallback: (_: {
- data: ConsumerPortResponse
- }) => void) {
- this.mainControllerCallback = mainControllerCallback;
+ constructor(adb: Adb, consumerPortListener: Consumer) {
+ super(consumerPortListener);
this.adb = adb;
}
- sendMessage(message: ConsumerPortResponse|RecordControllerMessage) {
- this.mainControllerCallback({data: message});
- }
-
- sendErrorMessage(message: string) {
- console.error('Error in adb record controller: ', message);
- this.sendMessage({type: 'RecordControllerError', message});
- }
-
- sendStatus(status: string) {
- this.sendMessage({type: 'RecordControllerStatus', status});
- }
-
handleCommand(method: string, params: Uint8Array) {
- // TODO(nicomazz): after having implemented the connection to the consumer
- // port socket through adb (on a real device), this class will be a simple
- // proxy.
switch (method) {
case 'EnableTracing':
this.enableTracing(params);
@@ -64,9 +51,11 @@
case 'ReadBuffers':
this.readBuffers();
break;
+ case 'DisableTracing':
+ this.disableTracing();
+ break;
case 'FreeBuffers': // no-op
case 'GetTraceStats':
- case 'DisableTracing':
break;
default:
this.sendErrorMessage(`Method not recognized: ${method}`);
@@ -74,12 +63,9 @@
}
}
- async enableTracing(configProto: Uint8Array) {
+ async enableTracing(enableTracingProto: Uint8Array) {
try {
- if (this.state !== AdbState.READY) {
- console.error('Current state of AdbRecordController is not READY');
- return;
- }
+ console.assert(this.state === AdbState.READY);
this.device = await this.findDevice();
if (this.device === undefined) {
@@ -89,9 +75,17 @@
this.sendStatus(
'Check the screen of your device and allow USB debugging.');
await this.adb.connect(this.device);
- await this.startRecording(configProto);
- this.sendStatus('Recording in progress...');
+ const traceConfigProto = extractTraceConfig(enableTracingProto);
+ if (!traceConfigProto) {
+ this.sendErrorMessage('Invalid config.');
+ return;
+ }
+
+ await this.startRecording(traceConfigProto);
+ const duration = extractDurationFromTraceConfig(traceConfigProto);
+ this.sendStatus(`Recording in progress${
+ duration ? ' for ' + duration.toString() + ' ms' : ''}...`);
} catch (e) {
this.sendErrorMessage(e.message);
}
@@ -100,15 +94,17 @@
async startRecording(configProto: Uint8Array) {
this.state = AdbState.RECORDING;
const recordCommand = this.generateStartTracingCommand(configProto);
- const recordShell: AdbStream = await this.adb.shell(recordCommand);
- let response = '';
- recordShell.onData = (str, _) => response += str;
- recordShell.onClose = () => {
+ this.recordShell = await this.adb.shell(recordCommand);
+ const output: string[] = [];
+ this.recordShell.onData = (str, _) => output.push(str);
+ this.recordShell.onClose = () => {
+ const response = output.join();
if (!this.tracingEndedSuccessfully(response)) {
this.sendErrorMessage(response);
this.state = AdbState.READY;
return;
}
+ this.sendStatus('Recording ended successfully. Fetching the trace..');
this.sendMessage({type: 'EnableTracingResponse'});
};
}
@@ -138,6 +134,9 @@
// things are not working, the chunks should be sent as they are received,
// like in the following line.
// this.sendMessage(this.generateChunkReadResponse(str));
+ // EDIT: we should send back a response as if it was a real
+ // ReadBufferResponse, with trace packets. Here we are only sending the
+ // trace split in several pieces.
trace += str;
};
readTraceShell.onClose = () => {
@@ -145,10 +144,34 @@
this.sendMessage(
this.generateChunkReadResponse(decoded, /* last */ true));
+ this.adb.disconnect();
this.state = AdbState.READY;
};
}
+ // TODO(nicomazz): Implement cancel/reset recording.
+ async disableTracing() {
+ console.assert(this.recordShell !== undefined);
+ if (!this.recordShell) return;
+
+ // We are not using 'pidof perfetto' so that we can use more filters. 'ps -u
+ // shell' is meant to catch processes started from shell, so if there are
+ // other ongoing tracing sessions started by others, we are not killing
+ // them.
+ const pid = await this.adb.shellOutputAsString(
+ `ps -u shell | grep perfetto | awk '{print $2}'`);
+ if (pid.length === 0 || isNaN(Number(pid))) {
+ this.sendErrorMessage(
+ 'Unexpected error, impossible to stop the recording');
+ console.error('Perfetto pid not found. Command output: ', pid);
+ return;
+ }
+ // Perfetto stops and finalizes the tracing session on SIGINT.
+ const killOutput =
+ await this.adb.shellOutputAsString(`kill -SIGINT ${pid}`);
+ console.assert(killOutput.length === 0);
+ }
+
generateChunkReadResponse(data: string, last = false): ReadBuffersResponse {
return {
type: 'ReadBuffersResponse',
diff --git a/ui/src/controller/adb_record_controller_jsdomtest.ts b/ui/src/controller/adb_record_controller_jsdomtest.ts
index dffb563..503f92d 100644
--- a/ui/src/controller/adb_record_controller_jsdomtest.ts
+++ b/ui/src/controller/adb_record_controller_jsdomtest.ts
@@ -14,14 +14,29 @@
import {dingus} from 'dingusjs';
+import {perfetto} from '../gen/protos';
import {AdbStream, MockAdb, MockAdbStream} from './adb_interfaces';
-import {AdbRecordController} from './adb_record_controller';
+import {AdbConsumerPort} from './adb_record_controller';
+import {Consumer} from './record_controller_interfaces';
-const mainCallback = jest.fn();
+function generateMockConsumer(): Consumer {
+ return {
+ onConsumerPortResponse: jest.fn(),
+ onError: jest.fn(),
+ onStatus: jest.fn()
+ };
+}
+const mainCallback = generateMockConsumer();
const adbMock = new MockAdb();
-const adbController = new AdbRecordController(adbMock, mainCallback);
+const adbController = new AdbConsumerPort(adbMock, mainCallback);
const mockIntArray = new Uint8Array();
+const enableTracingRequest = new perfetto.protos.EnableTracingRequest();
+enableTracingRequest.traceConfig = new perfetto.protos.TraceConfig();
+const enableTracingRequestProto =
+ perfetto.protos.EnableTracingRequest.encode(enableTracingRequest).finish();
+
+
test('handleCommand', () => {
adbController.findDevice = () => {
return Promise.resolve(dingus<USBDevice>());
@@ -44,9 +59,9 @@
});
test('enableTracing', async () => {
- const mainCallback = jest.fn();
+ const mainCallback = generateMockConsumer();
const adbMock = new MockAdb();
- const adbController = new AdbRecordController(adbMock, mainCallback);
+ const adbController = new AdbConsumerPort(adbMock, mainCallback);
adbController.sendErrorMessage =
jest.fn().mockImplementation(s => console.error(s));
@@ -71,13 +86,11 @@
adbController.generateStartTracingCommand = (_) => 'CMD';
- await adbController.enableTracing(mockIntArray);
+ await adbController.enableTracing(enableTracingRequestProto);
expect(adbShell).toBeCalledWith('CMD');
expect(findDevice).toHaveBeenCalledTimes(1);
expect(connectToDevice).toHaveBeenCalledTimes(1);
- // Two messages: RecordControllerStatus asking for allow the debug, and
- // another status to clear that message.
- expect(sendMessage).toHaveBeenCalledTimes(2);
+ expect(sendMessage).toHaveBeenCalledTimes(0);
stream.onData('starting tracing Wrote 123 bytes', mockIntArray);
@@ -110,4 +123,4 @@
'Connected to the Perfetto traced service, starting tracing for \
0 ms'))
.toBe(false);
-});
\ No newline at end of file
+});
diff --git a/ui/src/controller/chrome_proxy_record_controller.ts b/ui/src/controller/chrome_proxy_record_controller.ts
new file mode 100644
index 0000000..c2ce289
--- /dev/null
+++ b/ui/src/controller/chrome_proxy_record_controller.ts
@@ -0,0 +1,69 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import {uint8ArrayToString} from '../base/string_utils';
+
+import {ConsumerPortResponse, Typed} from './consumer_port_types';
+import {Consumer, RpcConsumerPort} from './record_controller_interfaces';
+
+export interface ChromeExtensionError extends Typed {
+ error: string;
+}
+
+export interface ChromeExtensionStatus extends Typed {
+ status: string;
+}
+
+export type ChromeExtensionMessage =
+ ChromeExtensionError|ChromeExtensionStatus|ConsumerPortResponse;
+
+function isError(obj: Typed): obj is ChromeExtensionError {
+ return obj.type === 'ChromeExtensionError';
+}
+
+function isStatus(obj: Typed): obj is ChromeExtensionStatus {
+ return obj.type === 'ChromeExtensionStatus';
+}
+
+// This class acts as a proxy from the record controller (running in a worker),
+// to the frontend. This is needed because we can't directly talk with the
+// extension from a web-worker, so we use a MessagePort to communicate with the
+// frontend, that will consecutively forward it to the extension.
+export class ChromeExtensionConsumerPort extends RpcConsumerPort {
+ private extensionPort: MessagePort;
+
+ constructor(extensionPort: MessagePort, consumerPortListener: Consumer) {
+ super(consumerPortListener);
+ this.extensionPort = extensionPort;
+ this.extensionPort.onmessage = this.onExtensionMessage.bind(this);
+ }
+
+ onExtensionMessage(message: {data: ChromeExtensionMessage}) {
+ if (isError(message.data)) {
+ this.sendErrorMessage(message.data.error);
+ } else if (isStatus(message.data)) {
+ this.sendStatus(message.data.status);
+ } else {
+ this.sendMessage(message.data);
+ }
+ }
+
+ handleCommand(method: string, requestData: Uint8Array): void {
+ const buffer = uint8ArrayToString(requestData);
+ // We need to encode the buffer as a string because the message port doesn't
+ // fully support sending ArrayBuffers (they are converted to objects with
+ // indexes as keys).
+ this.extensionPort.postMessage({method, requestData: buffer});
+ }
+}
diff --git a/ui/src/controller/globals.ts b/ui/src/controller/globals.ts
index 94f839d..062770b 100644
--- a/ui/src/controller/globals.ts
+++ b/ui/src/controller/globals.ts
@@ -28,8 +28,8 @@
import {ControllerAny} from './controller';
type PublishKinds = 'OverviewData'|'TrackData'|'Threads'|'QueryResult'|
- 'LegacyTrace'|'SliceDetails'|'Loading'|'Search'|'BufferUsage'|
- 'RecordingLog'|'SearchResult';
+ 'LegacyTrace'|'SliceDetails'|'CounterDetails'|'HeapDumpDetails'|'Loading'|
+ 'Search'|'BufferUsage'|'RecordingLog'|'SearchResult';
export interface App {
state: State;
diff --git a/ui/src/controller/record_controller.ts b/ui/src/controller/record_controller.ts
index 34feb53..69a3f48 100644
--- a/ui/src/controller/record_controller.ts
+++ b/ui/src/controller/record_controller.ts
@@ -15,6 +15,7 @@
import {ungzip} from 'pako';
import {Message, Method, rpc, RPCImplCallback} from 'protobufjs';
+import {stringToUint8Array, uint8ArrayToBase64} from '../base/string_utils';
import {Actions} from '../common/actions';
import {
AndroidLogConfig,
@@ -34,47 +35,27 @@
isAndroidTarget,
isChromeTarget,
MAX_TIME,
- RecordConfig
+ RecordConfig,
+ TargetOs
} from '../common/state';
+import {perfetto} from '../gen/protos';
import {AdbOverWebUsb} from './adb';
-import {AdbRecordController} from './adb_record_controller';
+import {AdbConsumerPort} from './adb_record_controller';
+import {ChromeExtensionConsumerPort} from './chrome_proxy_record_controller';
import {
ConsumerPortResponse,
GetTraceStatsResponse,
isEnableTracingResponse,
isGetTraceStatsResponse,
isReadBuffersResponse,
- Typed,
} from './consumer_port_types';
import {Controller} from './controller';
import {App, globals} from './globals';
+import {Consumer, RpcConsumerPort} from './record_controller_interfaces';
type RPCImplMethod = (Method|rpc.ServiceMethod<Message<{}>, Message<{}>>);
-export interface RecordControllerError extends Typed {
- message: string;
-}
-
-export interface RecordControllerStatus extends Typed {
- status: string;
-}
-
-export type RecordControllerMessage =
- RecordControllerError|RecordControllerStatus;
-
-function isError(obj: Typed): obj is RecordControllerError {
- return obj.type === 'RecordControllerError';
-}
-
-function isStatus(obj: Typed): obj is RecordControllerStatus {
- return obj.type === 'RecordControllerStatus';
-}
-
-export function uint8ArrayToBase64(buffer: Uint8Array): string {
- return btoa(String.fromCharCode.apply(null, Array.from(buffer)));
-}
-
export function genConfigProto(uiCfg: RecordConfig): Uint8Array {
return TraceConfig.encode(genConfig(uiCfg)).finish();
}
@@ -150,12 +131,6 @@
ftraceEvents.add('power/gpu_frequency');
}
- if (uiCfg.gpuSched) {
- ftraceEvents.add('gpu/gpu_sched_enqueue');
- ftraceEvents.add('gpu/gpu_sched_submit');
- ftraceEvents.add('gpu/gpu_sched_complete');
- }
-
if (uiCfg.cpuSyscall) {
ftraceEvents.add('raw_syscalls/sys_enter');
ftraceEvents.add('raw_syscalls/sys_exit');
@@ -273,6 +248,10 @@
protoCfg.dataSources.push(ds);
}
+ if (uiCfg.chromeLogs) {
+ chromeCategories.add('log');
+ }
+
if (uiCfg.taskScheduling) {
chromeCategories.add('toplevel');
chromeCategories.add('sequence_manager');
@@ -436,7 +415,28 @@
return [...message(json, 0)].join('');
}
-export class RecordController extends Controller<'main'> {
+export function extractTraceConfig(enableTracingRequest: Uint8Array):
+ Uint8Array|undefined {
+ try {
+ const enableTracingObject =
+ perfetto.protos.EnableTracingRequest.decode(enableTracingRequest);
+ if (!enableTracingObject.traceConfig) return undefined;
+ return perfetto.protos.TraceConfig.encode(enableTracingObject.traceConfig)
+ .finish();
+ } catch (e) { // This catch is for possible proto encoding/decoding issues.
+ console.error('Error extracting the config: ', e.message);
+ return undefined;
+ }
+}
+
+export function extractDurationFromTraceConfig(traceConfigProto: Uint8Array) {
+ try {
+ return perfetto.protos.TraceConfig.decode(traceConfigProto).durationMs;
+ } catch (e) { // This catch is for possible proto encoding/decoding issues.
+ return undefined;
+ }
+}
+export class RecordController extends Controller<'main'> implements Consumer {
private app: App;
private config: RecordConfig|null = null;
private extensionPort: MessagePort;
@@ -445,14 +445,14 @@
private traceBuffer = '';
private bufferUpdateInterval: ReturnType<typeof setTimeout>|undefined;
- private adbRecordController = new AdbRecordController(
- new AdbOverWebUsb(), this.onConsumerPortMessage.bind(this));
+ // We have a different controller for each targetOS. The correct one will be
+ // created when needed, and stored here.
+ private controllers = new Map<TargetOs, RpcConsumerPort>();
constructor(args: {app: App, extensionPort: MessagePort}) {
super('main');
this.app = args.app;
this.consumerPort = ConsumerPort.create(this.rpcImpl.bind(this));
this.extensionPort = args.extensionPort;
- this.extensionPort.onmessage = this.onConsumerPortMessage.bind(this);
}
run() {
@@ -510,16 +510,14 @@
this.consumerPort.readBuffers({});
}
- onConsumerPortMessage({data}: {
- data: ConsumerPortResponse|RecordControllerMessage
- }) {
+ onConsumerPortResponse(data: ConsumerPortResponse) {
if (data === undefined) return;
-
if (isReadBuffersResponse(data)) {
if (!data.slices) return;
+ // TODO(nicomazz): handle this as intended by consumer_port.proto.
this.traceBuffer += data.slices[0].data;
// TODO(nicomazz): Stream the chunks directly in the trace processor.
- if (data.slices[0].lastSliceForPacket) this.openTraceInUI();
+ if (data.slices[0].lastSliceForPacket) this.onTraceComplete();
} else if (isEnableTracingResponse(data)) {
this.readBuffers();
} else if (isGetTraceStatsResponse(data)) {
@@ -527,77 +525,81 @@
if (percentage) {
globals.publish('BufferUsage', {percentage});
}
- } else if (isError(data)) {
- this.handleError(data.message);
- } else if (isStatus(data)) {
- this.handleStatus(data.status);
+ } else {
+ console.error('Unrecognized consumer port response:', data);
}
}
- openTraceInUI() {
+ onTraceComplete() {
this.consumerPort.freeBuffers({});
globals.dispatch(Actions.setRecordingStatus({status: undefined}));
- const trace = ungzip(this.stringToArrayBuffer(this.traceBuffer));
+ if (globals.state.recordingCancelled) {
+ globals.dispatch(
+ Actions.setLastRecordingError({error: 'Recording cancelled.'}));
+ return;
+ }
+ const trace = ungzip(stringToUint8Array(this.traceBuffer));
globals.dispatch(Actions.openTraceFromBuffer({buffer: trace.buffer}));
this.traceBuffer = '';
}
- stringToArrayBuffer(str: string): Uint8Array {
- const buf = new ArrayBuffer(str.length);
- const bufView = new Uint8Array(buf);
- for (let i = 0, strLen = str.length; i < strLen; i++) {
- bufView[i] = str.charCodeAt(i);
- }
- return bufView;
- }
-
getBufferUsagePercentage(data: GetTraceStatsResponse): number {
if (!data.traceStats || !data.traceStats.bufferStats) return 0.0;
- let used = 0.0, total = 0.0;
+ let maximumUsage = 0;
for (const buffer of data.traceStats.bufferStats) {
- used += buffer.bytesWritten as number;
- total += buffer.bufferSize as number;
+ const used = buffer.bytesWritten as number;
+ const total = buffer.bufferSize as number;
+ maximumUsage = Math.max(maximumUsage, used / total);
}
- if (total === 0.0) return 0;
- return used / total;
+ return maximumUsage;
}
- handleError(message: string) {
+ onError(message: string) {
globals.dispatch(
Actions.setLastRecordingError({error: message.substr(0, 150)}));
globals.dispatch(Actions.stopRecording({}));
}
- handleStatus(message: string) {
+ onStatus(message: string) {
globals.dispatch(Actions.setRecordingStatus({status: message}));
}
// Depending on the recording target, different implementation of the
// consumer_port will be used.
// - Chrome target: This forwards the messages that have to be sent
- // to the extension to the frontend. This is necessary because this controller
- // is running in a separate worker, that can't directly send messages to the
- // extension.
+ // to the extension to the frontend. This is necessary because this
+ // controller is running in a separate worker, that can't directly send
+ // messages to the extension.
// - Android device target: WebUSB is used to communicate using the adb
- // protocol. Actually, there is no full consumer_port implementation, but only
- // the support to start tracing and fetch the file.
+ // protocol. Actually, there is no full consumer_port implementation, but
+ // only the support to start tracing and fetch the file.
+ getTargetController(target: TargetOs): RpcConsumerPort {
+ let controller = this.controllers.get(target);
+ if (controller) return controller;
+
+ if (isChromeTarget(target)) {
+ controller = new ChromeExtensionConsumerPort(this.extensionPort, this);
+ } else if (isAndroidTarget(target)) {
+ // TODO(nicomazz): create the correct controller also based on the
+ // selected android device.
+ controller = new AdbConsumerPort(new AdbOverWebUsb(), this);
+ }
+
+ if (!controller) throw Error(`Unknown target: ${target}`);
+
+ this.controllers.set(target, controller);
+ return controller;
+ }
+
private rpcImpl(
method: RPCImplMethod, requestData: Uint8Array,
_callback: RPCImplCallback) {
- const target = this.app.state.recordConfig.targetOS;
- if (isChromeTarget(target) && method !== null && method.name !== null &&
- this.config !== null) {
- this.extensionPort.postMessage(
- {method: method.name, traceConfig: requestData});
- } else if (isAndroidTarget(target)) {
- // TODO(nicomazz): In theory requestData should contain the configuration
- // proto, but in practice there are missing fields. As a temporary
- // workaround I'm directly passing the configuration.
- this.adbRecordController.handleCommand(
- method.name, genConfigProto(this.config!));
- } else {
- console.error(`Target ${target} not supported!`);
+ try {
+ this.getTargetController(this.app.state.recordConfig.targetOS)
+ .handleCommand(method.name, requestData);
+ } catch (e) {
+ console.error(`error invoking ${method}: ${e.message}`);
}
}
}
diff --git a/ui/src/controller/record_controller_interfaces.ts b/ui/src/controller/record_controller_interfaces.ts
new file mode 100644
index 0000000..afd1d8b
--- /dev/null
+++ b/ui/src/controller/record_controller_interfaces.ts
@@ -0,0 +1,36 @@
+import {ConsumerPortResponse} from './consumer_port_types';
+
+export type ConsumerPortCallback = (_: ConsumerPortResponse) => void;
+export type ErrorCallback = (_: string) => void;
+export type StatusCallback = (_: string) => void;
+
+export abstract class RpcConsumerPort {
+ // The responses of the call invocations should be sent through this listener.
+ // This is done by the 3 "send" methods in this abstract class.
+ private consumerPortListener: Consumer;
+
+ constructor(consumerPortListener: Consumer) {
+ this.consumerPortListener = consumerPortListener;
+ }
+
+ // RequestData is the proto representing the arguments of the function call.
+ abstract handleCommand(methodName: string, requestData: Uint8Array): void;
+
+ sendMessage(data: ConsumerPortResponse) {
+ this.consumerPortListener.onConsumerPortResponse(data);
+ }
+
+ sendErrorMessage(message: string) {
+ this.consumerPortListener.onError(message);
+ }
+
+ sendStatus(status: string) {
+ this.consumerPortListener.onStatus(status);
+ }
+}
+
+export interface Consumer {
+ onConsumerPortResponse(data: ConsumerPortResponse): void;
+ onError: ErrorCallback;
+ onStatus: StatusCallback;
+}
\ No newline at end of file
diff --git a/ui/src/controller/record_controller_jsdomtest.ts b/ui/src/controller/record_controller_jsdomtest.ts
index 3455b52..8fb9983 100644
--- a/ui/src/controller/record_controller_jsdomtest.ts
+++ b/ui/src/controller/record_controller_jsdomtest.ts
@@ -19,18 +19,7 @@
import {createEmptyRecordConfig, RecordConfig} from '../common/state';
import {App} from './globals';
-import {
- genConfigProto,
- RecordController,
- toPbtxt,
- uint8ArrayToBase64
-} from './record_controller';
-
-test('uint8ArrayToBase64', () => {
- const bytes = [...'Hello, world'].map(c => c.charCodeAt(0));
- const buffer = new Uint8Array(bytes);
- expect(uint8ArrayToBase64(buffer)).toEqual('SGVsbG8sIHdvcmxk');
-});
+import {genConfigProto, RecordController, toPbtxt} from './record_controller';
test('encodeConfig', () => {
const config = createEmptyRecordConfig();
diff --git a/ui/src/controller/search_controller.ts b/ui/src/controller/search_controller.ts
index 8738d63..3e02125 100644
--- a/ui/src/controller/search_controller.ts
+++ b/ui/src/controller/search_controller.ts
@@ -65,7 +65,8 @@
const visibleState = this.app.state.frontendLocalState.visibleState;
const omniboxState = this.app.state.frontendLocalState.omniboxState;
- if (visibleState === undefined || omniboxState === undefined) {
+ if (visibleState === undefined || omniboxState === undefined ||
+ omniboxState.mode === 'COMMAND') {
return;
}
const newSpan = new TimeSpan(visibleState.startSec, visibleState.endSec);
diff --git a/ui/src/controller/selection_controller.ts b/ui/src/controller/selection_controller.ts
index 52068c3..9e881b7 100644
--- a/ui/src/controller/selection_controller.ts
+++ b/ui/src/controller/selection_controller.ts
@@ -13,8 +13,12 @@
// limitations under the License.
import {Engine} from '../common/engine';
-import {fromNs} from '../common/time';
-import {SliceDetails} from '../frontend/globals';
+import {fromNs, toNs} from '../common/time';
+import {
+ CounterDetails,
+ HeapDumpDetails,
+ SliceDetails
+} from '../frontend/globals';
import {Controller} from './controller';
import {globals} from './globals';
@@ -26,7 +30,7 @@
// This class queries the TP for the details on a specific slice that has
// been clicked.
export class SelectionController extends Controller<'main'> {
- private lastSelectedSlice?: number;
+ private lastSelectedId?: number;
private lastSelectedKind?: string;
constructor(private args: SelectionControllerArgs) {
super('main');
@@ -35,27 +39,50 @@
run() {
const selection = globals.state.currentSelection;
if (selection === null ||
- (selection.kind !== 'SLICE' && selection.kind !== 'CHROME_SLICE') ||
- (selection.id === this.lastSelectedSlice &&
- selection.kind === this.lastSelectedKind)) {
+ (selection.kind !== 'SLICE' && selection.kind !== 'CHROME_SLICE' &&
+ selection.kind !== 'COUNTER' && selection.kind !== 'HEAP_DUMP') ||
+ (selection.id === this.lastSelectedId &&
+ selection.kind === this.lastSelectedKind &&
+ selection.kind !== 'COUNTER')) {
return;
}
- const selectedSlice = selection.id;
- const selectedSliceKind = selection.kind;
- this.lastSelectedSlice = selectedSlice;
- this.lastSelectedKind = selectedSliceKind;
+ const selectedId = selection.id;
+ const selectedKind = selection.kind;
+ this.lastSelectedId = selectedId;
+ this.lastSelectedKind = selectedKind;
- if (selectedSlice === undefined) return;
+ if (selectedId === undefined) return;
- if (selectedSliceKind === 'SLICE') {
+ if (selection.kind === 'HEAP_DUMP') {
+ const selected: HeapDumpDetails = {};
+ const ts = selection.ts;
+ const upid = selection.upid;
+ this.heapDumpDetails(ts, upid).then(results => {
+ if (results !== undefined && selection &&
+ selection.kind === selectedKind && selection.id === selectedId) {
+ Object.assign(selected, results);
+ globals.publish('HeapDumpDetails', selected);
+ }
+ });
+ } else if (selection.kind === 'COUNTER') {
+ const selected: CounterDetails = {};
+ this.counterDetails(selection.leftTs, selection.rightTs, selection.id)
+ .then(results => {
+ if (results !== undefined && selection &&
+ selection.kind === selectedKind &&
+ selection.id === selectedId) {
+ Object.assign(selected, results);
+ globals.publish('CounterDetails', selected);
+ }
+ });
+ } else if (selectedKind === 'SLICE') {
const sqlQuery = `SELECT ts, dur, priority, end_state, utid FROM sched
- WHERE row_id = ${selectedSlice}`;
+ WHERE row_id = ${selectedId}`;
this.args.engine.query(sqlQuery).then(result => {
// Check selection is still the same on completion of query.
const selection = globals.state.currentSelection;
if (result.numRecords === 1 && selection &&
- selection.kind === selectedSliceKind &&
- selection.id === selectedSlice) {
+ selection.kind === selectedKind && selection.id === selectedId) {
const ts = result.columns[0].longValues![0] as number;
const timeFromStart = fromNs(ts) - globals.state.traceTime.startSec;
const dur = fromNs(result.columns[1].longValues![0] as number);
@@ -70,19 +97,18 @@
});
}
});
- } else if (selectedSliceKind === 'CHROME_SLICE') {
- if (selectedSlice === -1) {
+ } else if (selectedKind === 'CHROME_SLICE') {
+ if (selectedId === -1) {
globals.publish('SliceDetails', {ts: 0, name: 'Summarized slice'});
return;
}
const sqlQuery = `SELECT ts, dur, name, cat FROM slices
- WHERE slice_id = ${selectedSlice}`;
+ WHERE slice_id = ${selectedId}`;
this.args.engine.query(sqlQuery).then(result => {
// Check selection is still the same on completion of query.
const selection = globals.state.currentSelection;
if (result.numRecords === 1 && selection &&
- selection.kind === selectedSliceKind &&
- selection.id === selectedSlice) {
+ selection.kind === selectedKind && selection.id === selectedId) {
const ts = result.columns[0].longValues![0] as number;
const timeFromStart = fromNs(ts) - globals.state.traceTime.startSec;
const name = result.columns[2].stringValues![0];
@@ -97,6 +123,38 @@
}
}
+ async heapDumpDetails(ts: number, upid: number) {
+ const allocatedMemory = await this.args.engine.query(
+ `select sum(size) from heap_profile_allocation where ts <= ${
+ ts} and size > 0 and upid = ${upid}`);
+ const allocated = allocatedMemory.columns[0].longValues![0];
+ const allocatedNotFreedMemory = await this.args.engine.query(
+ `select sum(size) from heap_profile_allocation where ts <= ${
+ ts} and upid = ${upid}`);
+ const allocatedNotFreed = allocatedNotFreedMemory.columns[0].longValues![0];
+ const startTime = fromNs(ts) - globals.state.traceTime.startSec;
+ return {ts: startTime, allocated, allocatedNotFreed};
+ }
+
+ async counterDetails(ts: number, rightTs: number, id: number) {
+ const counter = await this.args.engine.query(
+ `SELECT value FROM counter_values WHERE ts = ${ts} AND counter_id = ${
+ id}`);
+ const value = counter.columns[0].doubleValues![0];
+ // Finding previous value. If there isn't previous one, it will return 0 for
+ // ts and value.
+ const previous = await this.args.engine.query(
+ `SELECT MAX(ts), value FROM counter_values WHERE ts < ${
+ ts} and counter_id = ${id}`);
+ const previousValue = previous.columns[1].doubleValues![0];
+ const endTs =
+ rightTs !== -1 ? rightTs : toNs(globals.state.traceTime.endSec);
+ const delta = value - previousValue;
+ const duration = endTs - ts;
+ const startTime = fromNs(ts) - globals.state.traceTime.startSec;
+ return {startTime, value, delta, duration};
+ }
+
async schedulingDetails(ts: number, utid: number|Long) {
let event = 'sched_waking';
const waking = await this.args.engine.query(
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index bf2376e..34a79a4 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -33,6 +33,7 @@
import {CPU_FREQ_TRACK_KIND} from '../tracks/cpu_freq/common';
import {CPU_SLICE_TRACK_KIND} from '../tracks/cpu_slices/common';
import {GPU_FREQ_TRACK_KIND} from '../tracks/gpu_freq/common';
+import {HEAP_PROFILE_TRACK_KIND} from '../tracks/heap_profile/common';
import {
PROCESS_SCHEDULING_TRACK_KIND
} from '../tracks/process_scheduling/common';
@@ -162,11 +163,11 @@
}
} else if (engineCfg.source instanceof ArrayBuffer) {
this.updateStatus(`${statusHeader} 0 %`);
- const buffer = engineCfg.source;
+ const buffer = new Uint8Array(engineCfg.source);
const SLICE_SIZE = 1024 * 1024;
for (let off = 0; off < buffer.byteLength; off += SLICE_SIZE) {
- const slice = buffer.slice(off, off + SLICE_SIZE);
- await this.engine.parse(new Uint8Array(slice));
+ const slice = buffer.subarray(off, off + SLICE_SIZE);
+ await this.engine.parse(slice);
const progress =
Math.round((off + slice.byteLength) / buffer.byteLength * 100);
this.updateStatus(`${statusHeader} ${progress} %`);
@@ -217,8 +218,9 @@
// We don't know the resolution at this point. However this will be
// replaced in 50ms so a guess is fine.
+ const resolution = (traceTime.end - traceTime.start) / 1000;
actions.push(Actions.setVisibleTraceTime(
- {...traceTimeState, lastUpdate: Date.now() / 1000, resolution: 0.008}));
+ {...traceTimeState, lastUpdate: Date.now() / 1000, resolution}));
globals.dispatchMultiple(actions);
@@ -305,6 +307,15 @@
}
}
+ const heapProfiles = await engine.query(`
+ select distinct(upid) from heap_profile_allocation`);
+
+ const heapUpids: Set<number> = new Set();
+ for (let i = 0; i < heapProfiles.numRecords; i++) {
+ const upid = heapProfiles.columns[0].longValues![i];
+ heapUpids.add(+upid);
+ }
+
const maxGpuFreq = await engine.query(`
select max(value)
from counters
@@ -492,6 +503,16 @@
});
});
}
+
+ if (heapUpids.has(upid)) {
+ tracksToAdd.push({
+ engineId: this.engineId,
+ kind: HEAP_PROFILE_TRACK_KIND,
+ name: `Heap Profile`,
+ trackGroup: pUuid,
+ config: {upid}
+ });
+ }
}
}
const counterThreadNames = counterUtids[utid];
diff --git a/ui/src/frontend/counter_panel.ts b/ui/src/frontend/counter_panel.ts
new file mode 100644
index 0000000..458a037
--- /dev/null
+++ b/ui/src/frontend/counter_panel.ts
@@ -0,0 +1,58 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use size file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as m from 'mithril';
+
+import {fromNs, timeToCode} from '../common/time';
+
+import {globals} from './globals';
+import {Panel} from './panel';
+
+interface CounterDetailsPanelAttrs {}
+
+export class CounterDetailsPanel extends Panel<CounterDetailsPanelAttrs> {
+ view() {
+ const counterInfo = globals.counterDetails;
+ if (counterInfo && counterInfo.startTime &&
+ counterInfo.value !== undefined && counterInfo.delta !== undefined &&
+ counterInfo.duration !== undefined) {
+ return m(
+ '.details-panel',
+ m('.details-panel-heading', `Counter Details:`),
+ m(
+ '.details-table',
+ [m('table',
+ [
+ m('tr',
+ m('th', `Start time`),
+ m('td', `${timeToCode(counterInfo.startTime)}`)),
+ m('tr',
+ m('th', `Value`),
+ m('td', `${counterInfo.value.toLocaleString()}`)),
+ m('tr',
+ m('th', `Delta`),
+ m('td', `${counterInfo.delta.toLocaleString()}`)),
+ m('tr',
+ m('th', `Duration`),
+ m('td', `${timeToCode(fromNs(counterInfo.duration))}`)),
+ ])],
+ ));
+ } else {
+ return m(
+ '.details-panel', m('.details-panel-heading', `Counter Details:`));
+ }
+ }
+
+ renderCanvas() {}
+}
diff --git a/ui/src/frontend/frontend_local_state.ts b/ui/src/frontend/frontend_local_state.ts
index e956f2b..8a1a6ed 100644
--- a/ui/src/frontend/frontend_local_state.ts
+++ b/ui/src/frontend/frontend_local_state.ts
@@ -61,6 +61,20 @@
};
}
+// Calculate the space a scrollbar takes up so that we can subtract it from
+// the canvas width.
+function calculateScrollbarWidth() {
+ const outer = document.createElement('div');
+ outer.style.overflowY = 'scroll';
+ const inner = document.createElement('div');
+ outer.appendChild(inner);
+ document.body.appendChild(outer);
+ const width =
+ outer.getBoundingClientRect().width - inner.getBoundingClientRect().width;
+ document.body.removeChild(outer);
+ return width;
+}
+
/**
* State that is shared between several frontend components, but not the
* controller. This state is updated at 60fps.
@@ -80,10 +94,12 @@
visibleTracks = new Set<string>();
prevVisibleTracks = new Set<string>();
searchIndex = -1;
+ private scrollBarWidth: undefined|number = undefined;
private _omniboxState: OmniboxState = {
lastUpdate: 0,
omnibox: '',
+ mode: 'SEARCH',
};
private _visibleState: VisibleState = {
@@ -97,6 +113,13 @@
// and a |timeScale| have a notion of time range. That should live in one
// place only.
+ getScrollbarWidth() {
+ if (this.scrollBarWidth === undefined) {
+ this.scrollBarWidth = calculateScrollbarWidth();
+ }
+ return this.scrollBarWidth;
+ }
+
togglePerfDebug() {
this.perfDebug = !this.perfDebug;
globals.rafScheduler.scheduleFullRedraw();
@@ -163,16 +186,19 @@
mergeState(state: FrontendState): void {
this._omniboxState = chooseLastest(this._omniboxState, state.omniboxState);
this._visibleState = chooseLastest(this._visibleState, state.visibleState);
- this.updateLocalTime(
- new TimeSpan(this._visibleState.startSec, this._visibleState.endSec));
+ if (this._visibleState === state.visibleState) {
+ this.updateLocalTime(
+ new TimeSpan(this._visibleState.startSec, this._visibleState.endSec));
+ }
}
private debouncedSetOmnibox = debounce(() => {
globals.dispatch(Actions.setOmnibox(this._omniboxState));
}, 20);
- set omnibox(value: string) {
+ setOmnibox(value: string, mode: 'SEARCH'|'COMMAND') {
this._omniboxState.omnibox = value;
+ this._omniboxState.mode = mode;
this._omniboxState.lastUpdate = Date.now() / 1000;
this.debouncedSetOmnibox();
}
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index 24038bc..1d44b88 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -35,6 +35,19 @@
name?: string;
}
+export interface CounterDetails {
+ startTime?: number;
+ value?: number;
+ delta?: number;
+ duration?: number;
+}
+
+export interface HeapDumpDetails {
+ ts?: number;
+ allocated?: number;
+ allocatedNotFreed?: number;
+}
+
export interface QuantizedLoad {
startSec: number;
endSec: number;
@@ -67,6 +80,8 @@
private _overviewStore?: OverviewStore = undefined;
private _threadMap?: ThreadMap = undefined;
private _sliceDetails?: SliceDetails = undefined;
+ private _counterDetails?: CounterDetails = undefined;
+ private _heapDumpDetails?: HeapDumpDetails = undefined;
private _isLoading = false;
private _bufferUsage?: number = undefined;
private _recordingLog?: string = undefined;
@@ -95,6 +110,8 @@
this._overviewStore = new Map<string, QuantizedLoad[]>();
this._threadMap = new Map<number, ThreadDesc>();
this._sliceDetails = {};
+ this._counterDetails = {};
+ this._heapDumpDetails = {};
}
get state(): State {
@@ -142,6 +159,22 @@
this._sliceDetails = assertExists(click);
}
+ get counterDetails() {
+ return assertExists(this._counterDetails);
+ }
+
+ set counterDetails(click: CounterDetails) {
+ this._counterDetails = assertExists(click);
+ }
+
+ get heapDumpDetails() {
+ return assertExists(this._heapDumpDetails);
+ }
+
+ set heapDumpDetails(click: HeapDumpDetails) {
+ this._heapDumpDetails = assertExists(click);
+ }
+
set loading(isLoading: boolean) {
this._isLoading = isLoading;
}
@@ -185,6 +218,12 @@
return Math.pow(2, Math.floor(Math.log2(resolution)));
}
+ makeSelection(action: DeferredAction<{}>) {
+ // A new selection should cancel the current search selection.
+ globals.frontendLocalState.searchIndex = -1;
+ globals.dispatch(action);
+ }
+
resetForTesting() {
this._dispatch = undefined;
this._state = undefined;
diff --git a/ui/src/frontend/heap_dump_panel.ts b/ui/src/frontend/heap_dump_panel.ts
new file mode 100644
index 0000000..d6c14e1
--- /dev/null
+++ b/ui/src/frontend/heap_dump_panel.ts
@@ -0,0 +1,59 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use size file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as m from 'mithril';
+
+import {timeToCode} from '../common/time';
+
+import {globals} from './globals';
+import {Panel} from './panel';
+
+interface HeapDumpDetailsPanelAttrs {}
+
+export class HeapDumpDetailsPanel extends Panel<HeapDumpDetailsPanelAttrs> {
+ view() {
+ const heapDumpInfo = globals.heapDumpDetails;
+ if (heapDumpInfo && heapDumpInfo.ts && heapDumpInfo.allocated &&
+ heapDumpInfo.allocatedNotFreed) {
+ return m(
+ '.details-panel',
+ m('.details-panel-heading', `Heap Snapshot Details:`),
+ m(
+ '.details-table',
+ [m('table',
+ [
+ m('tr',
+ m('th', `Snapshot time`),
+ m('td', `${timeToCode(heapDumpInfo.ts)}`)),
+ m('tr',
+ m('th', `Total allocated:`),
+ m('td',
+ `${heapDumpInfo.allocated.toLocaleString()} bytes`)),
+ m('tr',
+ m('th', `Allocated not freed:`),
+ m('td',
+ `${
+ heapDumpInfo.allocatedNotFreed
+ .toLocaleString()} bytes`)),
+ ])],
+ ));
+ } else {
+ return m(
+ '.details-panel',
+ m('.details-panel-heading', `Heap Snapshot Details:`));
+ }
+ }
+
+ renderCanvas() {}
+}
diff --git a/ui/src/frontend/index.ts b/ui/src/frontend/index.ts
index 132b179..bf59470 100644
--- a/ui/src/frontend/index.ts
+++ b/ui/src/frontend/index.ts
@@ -29,7 +29,14 @@
} from '../common/logs';
import {CurrentSearchResults, SearchSummary} from '../common/search_data';
-import {globals, QuantizedLoad, SliceDetails, ThreadDesc} from './globals';
+import {
+ CounterDetails,
+ globals,
+ HeapDumpDetails,
+ QuantizedLoad,
+ SliceDetails,
+ ThreadDesc
+} from './globals';
import {HomePage} from './home_page';
import {openBufferWithLegacyTraceViewer} from './legacy_trace_viewer';
import {postMessageHandler} from './post_message_handler';
@@ -111,6 +118,16 @@
this.redraw();
}
+ publishCounterDetails(click: CounterDetails) {
+ globals.counterDetails = click;
+ this.redraw();
+ }
+
+ publishHeapDumpDetails(click: HeapDumpDetails) {
+ globals.heapDumpDetails = click;
+ this.redraw();
+ }
+
publishLoading(loading: boolean) {
globals.loading = loading;
globals.rafScheduler.scheduleRedraw();
diff --git a/ui/src/frontend/keyboard_event_handler.ts b/ui/src/frontend/keyboard_event_handler.ts
index c687d9e..e1ac1dc 100644
--- a/ui/src/frontend/keyboard_event_handler.ts
+++ b/ui/src/frontend/keyboard_event_handler.ts
@@ -16,10 +16,11 @@
import {globals} from './globals';
import {toggleHelp} from './help_modal';
+import {executeSearch} from './search_handler';
// Handles all key events than are not handled by the
// pan and zoom handler.
-export function handleKey(key: string, down: boolean) {
+export function handleKey(key: string, down: boolean, isShiftDown: boolean) {
if (down && 'm' === key) {
selectSliceSpan();
}
@@ -40,6 +41,9 @@
if (down && '?' === key) {
toggleHelp();
}
+ if (down && 'Enter' === key) {
+ executeSearch(isShiftDown);
+ }
}
function selectSliceSpan() {
@@ -60,6 +64,6 @@
}
if (startTs !== -1 && endTs !== -1) {
- globals.dispatch(Actions.selectTimeSpan({startTs, endTs}));
+ globals.makeSelection(Actions.selectTimeSpan({startTs, endTs}));
}
}
diff --git a/ui/src/frontend/notes_panel.ts b/ui/src/frontend/notes_panel.ts
index 326117e..9920e98 100644
--- a/ui/src/frontend/notes_panel.ts
+++ b/ui/src/frontend/notes_panel.ts
@@ -173,7 +173,7 @@
if (note.isMovie) {
globals.frontendLocalState.setVidTimestamp(note.timestamp);
}
- globals.dispatch(Actions.selectNote({id: note.id}));
+ globals.makeSelection(Actions.selectNote({id: note.id}));
return;
}
}
diff --git a/ui/src/frontend/pan_and_zoom_handler.ts b/ui/src/frontend/pan_and_zoom_handler.ts
index fe93caa..f516ee5 100644
--- a/ui/src/frontend/pan_and_zoom_handler.ts
+++ b/ui/src/frontend/pan_and_zoom_handler.ts
@@ -184,7 +184,7 @@
}
// Handle key events that are not pan or zoom.
- handleKey(e.key, true);
+ handleKey(e.key, true, this.shiftDown);
}
private onKeyUp(e: KeyboardEvent) {
@@ -201,7 +201,7 @@
}
// Handle key events that are not pan or zoom.
- handleKey(e.key, false);
+ handleKey(e.key, false, this.shiftDown);
}
private updateShift(down: boolean) {
diff --git a/ui/src/frontend/panel_container.ts b/ui/src/frontend/panel_container.ts
index 9b3a7e6..80f99c2 100644
--- a/ui/src/frontend/panel_container.ts
+++ b/ui/src/frontend/panel_container.ts
@@ -171,7 +171,12 @@
const canvas = assertExists(ctx.canvas);
canvas.style.height = `${this.canvasHeight}px`;
const dpr = window.devicePixelRatio;
- ctx.canvas.width = this.parentWidth * dpr;
+ // On non-MacOS if there is a solid scroll bar it can cover important
+ // pixels, reduce the size of the canvas so it doesn't overlap with
+ // the scroll bar.
+ ctx.canvas.width =
+ (this.parentWidth - globals.frontendLocalState.getScrollbarWidth()) *
+ dpr;
ctx.canvas.height = this.canvasHeight * dpr;
ctx.scale(dpr, dpr);
}
diff --git a/ui/src/frontend/record_page.ts b/ui/src/frontend/record_page.ts
index f11e74a..ac9758a 100644
--- a/ui/src/frontend/record_page.ts
+++ b/ui/src/frontend/record_page.ts
@@ -214,13 +214,6 @@
descr: 'Records gpu frequency via ftrace',
setEnabled: (cfg, val) => cfg.gpuFreq = val,
isEnabled: (cfg) => cfg.gpuFreq
- } as ProbeAttrs),
- m(Probe, {
- title: 'GPU scheduling',
- img: 'rec_cpu_wakeup.png',
- descr: 'Records gpu scheduling via ftrace',
- setEnabled: (cfg, val) => cfg.gpuSched = val,
- isEnabled: (cfg) => cfg.gpuSched
} as ProbeAttrs));
}
@@ -481,6 +474,13 @@
setEnabled: (cfg, val) => cfg.navigationAndLoading = val,
isEnabled: (cfg) => cfg.navigationAndLoading
} as ProbeAttrs),
+ m(Probe, {
+ title: 'Chrome Logs',
+ img: null,
+ descr: `Records Chrome log messages`,
+ setEnabled: (cfg, val) => cfg.chromeLogs = val,
+ isEnabled: (cfg) => cfg.chromeLogs
+ } as ProbeAttrs),
ChromeCategoriesSelection());
}
@@ -494,14 +494,18 @@
// Show "disabled-by-default" categories last.
const categoriesMap = new Map<string, string>();
const disabledByDefaultCategories: string[] = [];
+ const disabledPrefix = 'disabled-by-default-';
categories.forEach(cat => {
- if (cat.startsWith('disabled')) {
+ if (cat.startsWith(disabledPrefix)) {
disabledByDefaultCategories.push(cat);
} else {
categoriesMap.set(cat, cat);
}
});
- disabledByDefaultCategories.forEach(cat => categoriesMap.set(cat, cat));
+ disabledByDefaultCategories.forEach(cat => {
+ categoriesMap.set(
+ cat, `${cat.replace(disabledPrefix, '')} (high overhead)`);
+ });
return m(Dropdown, {
title: 'Additional Chrome categories',
cssClass: '.multicolumn.two-columns.chrome-categories',
@@ -642,6 +646,7 @@
m('header', 'Instructions'),
RecordingSnippet(),
BufferUsageProgressBar(),
+ m('.buttons', StopCancelButtons()),
recordingLog());
}
@@ -768,11 +773,14 @@
const realDeviceTarget = state.androidDeviceConnected !== undefined;
const recInProgress = state.recordingInProgress;
- const startButton =
- m(`button${recInProgress ? '.selected' : ''}`,
- {onclick: onStartRecordingPressed},
+ const start =
+ m(`button`,
+ {
+ class: recInProgress ? '' : 'selected',
+ onclick: onStartRecordingPressed
+ },
'Start Recording');
- const showCmdButton =
+ const showCmd =
m(`button`,
{
onclick: () => {
@@ -781,28 +789,38 @@
}
},
'Show Command');
- const stopButton =
- m(`button${recInProgress ? '' : '.disabled'}`,
- {onclick: () => globals.dispatch(Actions.stopRecording({}))},
- 'Stop Recording');
const buttons: m.Children = [];
const targetOs = state.recordConfig.targetOS;
if (isAndroidTarget(targetOs)) {
- buttons.push(showCmdButton);
- if (realDeviceTarget) buttons.push(startButton);
- // TODO(nicomazz): Support stop recording on Android devices.
+ buttons.push(showCmd);
+ if (realDeviceTarget) buttons.push(start);
} else if (isChromeTarget(targetOs) && state.extensionInstalled) {
- buttons.push(startButton);
- if (recInProgress) buttons.push(stopButton);
+ buttons.push(start);
} else if (isLinuxTarget(targetOs)) {
- buttons.push(showCmdButton);
+ buttons.push(showCmd);
}
return m('.button', buttons);
}
+function StopCancelButtons() {
+ if (!globals.state.recordingInProgress) return [];
+
+ const stop =
+ m(`button.selected`,
+ {onclick: () => globals.dispatch(Actions.stopRecording({}))},
+ 'Stop');
+
+ const cancel =
+ m(`button`,
+ {onclick: () => globals.dispatch(Actions.cancelRecording({}))},
+ 'Cancel');
+
+ return [stop, cancel];
+}
+
function onStartRecordingPressed() {
location.href = '#!/record?p=instructions';
globals.rafScheduler.scheduleFullRedraw();
@@ -822,7 +840,7 @@
function ErrorLabel() {
const lastRecordingError = globals.state.lastRecordingError;
if (!lastRecordingError) return [];
- return m('label.error-label', `⚠️ Error: ${lastRecordingError}`);
+ return m('label.error-label', `Error: ${lastRecordingError}`);
}
function recordingLog() {
@@ -902,7 +920,7 @@
m(`li${routePage === 'gpu' ? '.active' : ''}`,
m('i.material-icons', 'aspect_ratio'),
m('.title', 'GPU'),
- m('.sub', 'GPU frequency, scheduling'))),
+ m('.sub', 'GPU frequency'))),
m('a[href="#!/record?p=power"]',
m(`li${routePage === 'power' ? '.active' : ''}`,
m('i.material-icons', 'battery_charging_full'),
diff --git a/ui/src/frontend/search_handler.ts b/ui/src/frontend/search_handler.ts
new file mode 100644
index 0000000..3343577
--- /dev/null
+++ b/ui/src/frontend/search_handler.ts
@@ -0,0 +1,83 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import {searchSegment} from '../base/binary_search';
+import {Actions} from '../common/actions';
+import {fromNs, TimeSpan, toNs} from '../common/time';
+
+import {globals} from './globals';
+
+export function executeSearch(reverse = false) {
+ const state = globals.frontendLocalState;
+ const index = state.searchIndex;
+ const startNs = toNs(globals.frontendLocalState.visibleWindowTime.start);
+ const endNs = toNs(globals.frontendLocalState.visibleWindowTime.end);
+ const currentTs = globals.currentSearchResults.tsStarts[index];
+
+ // If this is a new search or the currentTs is not in the viewport,
+ // select the first/last item in the viewport.
+ if (index === -1 || currentTs < startNs || currentTs > endNs) {
+ if (reverse) {
+ const [smaller,] =
+ searchSegment(globals.currentSearchResults.tsStarts, endNs);
+ globals.frontendLocalState.setSearchIndex(smaller);
+ } else {
+ const [, larger] =
+ searchSegment(globals.currentSearchResults.tsStarts, startNs);
+ globals.frontendLocalState.setSearchIndex(larger);
+ }
+ // If there is no result in the current viewport, move it.
+ const currentTs = globals.currentSearchResults.tsStarts[state.searchIndex];
+ if (currentTs < startNs || currentTs > endNs) {
+ moveViewportToCurrentSearch();
+ }
+ } else {
+ // If the currentTs is in the viewport, increment the index and move the
+ // viewport if necessary.
+ if (reverse) {
+ globals.frontendLocalState.setSearchIndex(Math.max(index - 1, 0));
+ } else {
+ globals.frontendLocalState.setSearchIndex(Math.min(
+ index + 1, globals.currentSearchResults.sliceIds.length - 1));
+ }
+ moveViewportToCurrentSearch();
+ }
+ selectCurrentSearchResult();
+}
+
+function moveViewportToCurrentSearch() {
+ // Move viewport if our selection moves outside.
+ const startNs = toNs(globals.frontendLocalState.visibleWindowTime.start);
+ const endNs = toNs(globals.frontendLocalState.visibleWindowTime.end);
+ const currentTs = globals.currentSearchResults
+ .tsStarts[globals.frontendLocalState.searchIndex];
+ const currentViewNs = endNs - startNs;
+ if (currentTs < startNs || currentTs > endNs) {
+ // TODO(taylori): This is an ugly jump, we should do a smooth pan instead.
+ globals.frontendLocalState.updateVisibleTime(new TimeSpan(
+ fromNs(currentTs - currentViewNs / 2),
+ fromNs(currentTs + currentViewNs / 2)));
+ }
+}
+
+function selectCurrentSearchResult() {
+ const state = globals.frontendLocalState;
+ const currentId = globals.currentSearchResults.sliceIds[state.searchIndex];
+ if (currentId !== undefined) {
+ globals.dispatch(Actions.selectSlice({
+ utid: globals.currentSearchResults.utids[state.searchIndex],
+ id: currentId
+ }));
+ }
+}
diff --git a/ui/src/frontend/time_axis_panel.ts b/ui/src/frontend/time_axis_panel.ts
index 89ce3fb..5005b1c 100644
--- a/ui/src/frontend/time_axis_panel.ts
+++ b/ui/src/frontend/time_axis_panel.ts
@@ -32,19 +32,24 @@
ctx.fillStyle = '#999';
// Write trace offset time + line.
- ctx.textAlign = 'right';
ctx.font = '12px Google Sans';
+
+ ctx.textAlign = 'right';
const offsetTime =
timeToString(range.start - globals.state.traceTime.startSec);
ctx.fillText(offsetTime, TRACK_SHELL_WIDTH - 6, 11);
- ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
+
+ ctx.textAlign = 'left';
+ const startTime = timeToString(globals.state.traceTime.startSec);
+ ctx.fillText(startTime + ' +', 6, 11);
// Draw time axis.
ctx.font = '10px Google Sans';
- ctx.textAlign = 'left';
for (const [x, time] of gridlines(size.width, range, timeScale)) {
ctx.fillRect(x, 0, 1, size.height);
ctx.fillText('+' + timeToString(time - range.start), x + 5, 10);
}
+
+ ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
}
}
diff --git a/ui/src/frontend/time_selection_panel.ts b/ui/src/frontend/time_selection_panel.ts
index cc5080a..cc899db 100644
--- a/ui/src/frontend/time_selection_panel.ts
+++ b/ui/src/frontend/time_selection_panel.ts
@@ -80,6 +80,35 @@
ctx.fillText(label, labelXLeft, yMid);
}
+function drawIBar(
+ ctx: CanvasRenderingContext2D, xPos: number, bounds: BBox, label: string) {
+ if (xPos < bounds.x) return;
+
+ ctx.fillStyle = '#222';
+ ctx.fillRect(xPos, 0, 1, bounds.width);
+
+ const yMid = Math.floor(bounds.height / 2 + bounds.y);
+ const labelWidth = ctx.measureText(label).width;
+ const padding = 3;
+
+ let xPosLabel;
+ if (xPos + padding + labelWidth > bounds.width) {
+ xPosLabel = xPos - padding;
+ ctx.textAlign = 'right';
+ } else {
+ xPosLabel = xPos + padding;
+ ctx.textAlign = 'left';
+ }
+
+ ctx.fillStyle = '#ffffff';
+ ctx.fillRect(xPosLabel - 1, 0, labelWidth + 2, bounds.height);
+
+ ctx.textBaseline = 'middle';
+ ctx.fillStyle = '#222';
+ ctx.font = '10px Google Sans';
+ ctx.fillText(label, xPosLabel, yMid);
+}
+
export class TimeSelectionPanel extends Panel {
view() {
return m('.time-selection-panel');
@@ -100,9 +129,20 @@
const start = Math.min(selection.startTs, selection.endTs);
const end = Math.max(selection.startTs, selection.endTs);
this.renderSpan(ctx, size, new TimeSpan(start, end));
+ } else if (globals.frontendLocalState.showTimeSelectPreview) {
+ this.renderHover(ctx, size, globals.frontendLocalState.hoveredTimestamp);
}
}
+ renderHover(ctx: CanvasRenderingContext2D, size: PanelSize, ts: number) {
+ const timeScale = globals.frontendLocalState.timeScale;
+ const xPos = TRACK_SHELL_WIDTH + Math.floor(timeScale.timeToPx(ts));
+ const offsetTime = timeToString(ts - globals.state.traceTime.startSec);
+ const timeFromStart = timeToString(ts);
+ const label = `${offsetTime} (${timeFromStart})`;
+ drawIBar(ctx, xPos, this.bounds(size), label);
+ }
+
renderSpan(ctx: CanvasRenderingContext2D, size: PanelSize, span: TimeSpan) {
const timeScale = globals.frontendLocalState.timeScale;
const xLeft = timeScale.timeToPx(span.start);
@@ -116,7 +156,11 @@
width: xRight - xLeft,
height: size.height
},
- {x: 0, y: 0, width: size.width, height: size.height},
+ this.bounds(size),
label);
}
+
+ private bounds(size: PanelSize): BBox {
+ return {x: TRACK_SHELL_WIDTH, y: 0, width: size.width, height: size.height};
+ }
}
diff --git a/ui/src/frontend/topbar.ts b/ui/src/frontend/topbar.ts
index 72fbf03..f8814ec 100644
--- a/ui/src/frontend/topbar.ts
+++ b/ui/src/frontend/topbar.ts
@@ -14,13 +14,12 @@
import * as m from 'mithril';
-import {searchSegment} from '../base/binary_search';
import {Actions} from '../common/actions';
import {QueryResponse} from '../common/queries';
import {EngineConfig} from '../common/state';
-import {fromNs, TimeSpan, toNs} from '../common/time';
import {globals} from './globals';
+import {executeSearch} from './search_handler';
const QUERY_ID = 'quicksearch';
@@ -37,7 +36,6 @@
let numResults = 0;
let mode: Mode = SEARCH;
let displayStepThrough = false;
-let prevOmniBox: string|undefined = undefined;
function clearOmniboxResults(e: Event) {
globals.queryResults.delete(QUERY_ID);
@@ -50,8 +48,11 @@
}
function onKeyDown(e: Event) {
- e.stopPropagation();
- const key = (e as KeyboardEvent).key;
+ const event = (e as KeyboardEvent);
+ const key = event.key;
+ if (key !== 'Enter') {
+ e.stopPropagation();
+ }
const txt = (e.target as HTMLInputElement);
// Avoid that the global 'a', 'd', 'w', 's' handler sees these keystrokes.
@@ -73,12 +74,15 @@
globals.rafScheduler.scheduleFullRedraw();
return;
}
+
+ if (mode === SEARCH && key === 'Enter') {
+ txt.blur();
+ }
}
function onKeyUp(e: Event) {
e.stopPropagation();
const event = (e as KeyboardEvent);
- const state = globals.frontendLocalState;
const key = event.key;
const txt = e.target as HTMLInputElement;
if (key === 'ArrowUp' || key === 'ArrowDown') {
@@ -103,86 +107,8 @@
globals.dispatch(Actions.executeQuery(
{engineId: '0', queryId: 'command', query: txt.value}));
}
- if (mode === SEARCH && key === 'Enter') {
- const index = state.searchIndex;
- const startNs = toNs(globals.frontendLocalState.visibleWindowTime.start);
- const endNs = toNs(globals.frontendLocalState.visibleWindowTime.end);
- const currentTs = globals.currentSearchResults.tsStarts[index];
- // If this is a new search or the currentTs is not in the viewport,
- // select the first/last item in the viewport.
- if (index === -1 || currentTs < startNs || currentTs > endNs) {
- if (event.shiftKey) {
- const [smaller,] =
- searchSegment(globals.currentSearchResults.tsStarts, endNs);
- globals.frontendLocalState.setSearchIndex(smaller);
- } else {
- const [, larger] =
- searchSegment(globals.currentSearchResults.tsStarts, startNs);
- globals.frontendLocalState.setSearchIndex(larger);
- }
- // If there is no result in the current viewport, move it.
- const currentTs =
- globals.currentSearchResults.tsStarts[state.searchIndex];
- if (currentTs < startNs || currentTs > endNs) {
- moveViewportToCurrent();
- }
- } else {
- // If the currentTs is in the viewport, increment the index and move the
- // viewport if necessary.
- if (event.shiftKey) {
- globals.frontendLocalState.setSearchIndex(Math.max(index - 1, 0));
- } else {
- globals.frontendLocalState.setSearchIndex(Math.min(
- index + 1, globals.currentSearchResults.sliceIds.length - 1));
- }
- moveViewportToCurrent();
- }
- displaySearchResults();
- }
}
-function moveViewportToCurrent() {
- // Move viewport if our selection moves outside.
- const startNs = toNs(globals.frontendLocalState.visibleWindowTime.start);
- const endNs = toNs(globals.frontendLocalState.visibleWindowTime.end);
- const currentTs = globals.currentSearchResults
- .tsStarts[globals.frontendLocalState.searchIndex];
- const currentViewNs = endNs - startNs;
- if (currentTs < startNs || currentTs > endNs) {
- // TODO(taylori): This is an ugly jump, we should do a smooth pan instead.
- globals.frontendLocalState.updateVisibleTime(new TimeSpan(
- fromNs(currentTs - currentViewNs / 2),
- fromNs(currentTs + currentViewNs / 2)));
- }
-}
-
-function displaySearchResults() {
- const state = globals.frontendLocalState;
- const current = globals.currentSearchResults;
- if (current === undefined) return;
- if (globals.frontendLocalState.omnibox !== prevOmniBox) {
- globals.frontendLocalState.setSearchIndex(-1);
- }
- if (globals.frontendLocalState.omnibox === '' ||
- globals.frontendLocalState.omnibox.length < 4) {
- displayStepThrough = false;
- return;
- }
- displayStepThrough = true;
-
- const currentId = globals.currentSearchResults.sliceIds[state.searchIndex];
- if (currentId !== undefined) {
- globals.dispatch(Actions.selectSlice({
- utid: globals.currentSearchResults.utids[state.searchIndex],
- id: currentId
- }));
- }
- // TODO(taylori): Here we should zoom to an appropriate level.
- globals.rafScheduler.scheduleFullRedraw();
- prevOmniBox = globals.frontendLocalState.omnibox;
-}
-
-
class Omnibox implements m.ClassComponent {
oncreate(vnode: m.VnodeDOM) {
const txt = vnode.dom.querySelector('input') as HTMLInputElement;
@@ -192,7 +118,6 @@
}
view() {
- displaySearchResults();
const msgTTL = globals.state.status.timestamp + 1 - Date.now() / 1e3;
let enginesAreBusy = false;
for (const engine of Object.values(globals.state.engines)) {
@@ -228,9 +153,11 @@
oninput: m.withAttr(
'value',
v => {
- globals.frontendLocalState.omnibox = v;
- if (v === '') {
- displayStepThrough = false;
+ globals.frontendLocalState.setOmnibox(
+ v, commandMode ? 'COMMAND' : 'SEARCH');
+ if (mode === SEARCH) {
+ globals.frontendLocalState.setSearchIndex(-1);
+ displayStepThrough = v.length >= 4;
globals.rafScheduler.scheduleFullRedraw();
}
}),
@@ -249,10 +176,7 @@
{
disabled: state.searchIndex <= 0,
onclick: () => {
- globals.frontendLocalState.setSearchIndex(
- state.searchIndex - 1);
- moveViewportToCurrent();
- displaySearchResults();
+ executeSearch(true /* reverse direction */);
}
},
m('i.material-icons.left', 'keyboard_arrow_left')),
@@ -261,10 +185,7 @@
disabled: state.searchIndex ===
globals.currentSearchResults.totalResults - 1,
onclick: () => {
- globals.frontendLocalState.setSearchIndex(
- state.searchIndex + 1);
- moveViewportToCurrent();
- displaySearchResults();
+ executeSearch();
}
},
m('i.material-icons.right', 'keyboard_arrow_right')),
diff --git a/ui/src/frontend/track.ts b/ui/src/frontend/track.ts
index acd475c..de688ff 100644
--- a/ui/src/frontend/track.ts
+++ b/ui/src/frontend/track.ts
@@ -12,10 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import * as m from 'mithril';
import {TrackState} from '../common/state';
import {TrackData} from '../common/track_data';
import {globals} from './globals';
+import {TrackButtonAttrs} from './track_panel';
/**
* This interface forces track implementations to have some static properties.
@@ -51,6 +53,10 @@
return 40;
}
+ getTrackShellButtons(): Array<m.Vnode<TrackButtonAttrs>> {
+ return [];
+ }
+
onMouseMove(_position: {x: number, y: number}) {}
/**
diff --git a/ui/src/frontend/track_panel.ts b/ui/src/frontend/track_panel.ts
index 514fc4a..be93418 100644
--- a/ui/src/frontend/track_panel.ts
+++ b/ui/src/frontend/track_panel.ts
@@ -14,7 +14,7 @@
import * as m from 'mithril';
-import {Actions, DeferredAction} from '../common/actions';
+import {Actions} from '../common/actions';
import {TrackState} from '../common/state';
import {globals} from './globals';
@@ -33,6 +33,7 @@
}
interface TrackShellAttrs {
+ track: Track;
trackState: TrackState;
}
@@ -64,9 +65,15 @@
title: attrs.trackState.name,
},
attrs.trackState.name),
+ attrs.track.getTrackShellButtons(),
m(TrackButton, {
- action: Actions.toggleTrackPinned({trackId: attrs.trackState.id}),
+ action: () => {
+ globals.dispatch(
+ Actions.toggleTrackPinned({trackId: attrs.trackState.id}));
+ },
i: isPinned(attrs.trackState.id) ? 'star' : 'star_border',
+ tooltip: isPinned(attrs.trackState.id) ? 'Unpin' : 'Pin to top',
+ selected: isPinned(attrs.trackState.id),
}));
}
@@ -167,22 +174,26 @@
}
},
[
- m(TrackShell, {trackState: attrs.trackState}),
+ m(TrackShell, {track: attrs.track, trackState: attrs.trackState}),
m(TrackContent, {track: attrs.track})
]);
}
}
-interface TrackButtonAttrs {
- action: DeferredAction;
+export interface TrackButtonAttrs {
+ action: () => void;
i: string;
+ tooltip: string;
+ selected: boolean;
}
-class TrackButton implements m.ClassComponent<TrackButtonAttrs> {
+export class TrackButton implements m.ClassComponent<TrackButtonAttrs> {
view({attrs}: m.CVnode<TrackButtonAttrs>) {
return m(
'i.material-icons.track-button',
{
- onclick: () => globals.dispatch(attrs.action),
+ class: `${attrs.selected ? 'show' : ''}`,
+ onclick: attrs.action,
+ title: attrs.tooltip,
},
attrs.i);
}
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index 30ac1e5..a6c415f 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -21,8 +21,10 @@
import {ChromeSliceDetailsPanel} from './chrome_slice_panel';
import {copyToClipboard} from './clipboard';
+import {CounterDetailsPanel} from './counter_panel';
import {DragGestureHandler} from './drag_gesture_handler';
import {globals} from './globals';
+import {HeapDumpDetailsPanel} from './heap_dump_panel';
import {LogPanel} from './logs_panel';
import {NotesEditorPanel, NotesPanel} from './notes_panel';
import {OverviewTimelinePanel} from './overview_timeline_panel';
@@ -255,7 +257,7 @@
scale.pxToTime(startPx - TRACK_SHELL_WIDTH));
const endTs = Math.min(traceTime.endSec,
scale.pxToTime(endPx - TRACK_SHELL_WIDTH));
- globals.dispatch(Actions.selectTimeSpan({startTs, endTs}));
+ globals.makeSelection(Actions.selectTimeSpan({startTs, endTs}));
globals.rafScheduler.scheduleRedraw();
}
});
@@ -301,6 +303,16 @@
utid: curSelection.utid,
}));
break;
+ case 'COUNTER':
+ detailsPanels.push(m(CounterDetailsPanel, {
+ key: 'counter',
+ }));
+ break;
+ case 'HEAP_DUMP':
+ detailsPanels.push(m(HeapDumpDetailsPanel, {
+ key: 'heap_dump',
+ }));
+ break;
case 'CHROME_SLICE':
detailsPanels.push(m(ChromeSliceDetailsPanel));
break;
@@ -340,7 +352,7 @@
this.keepCurrentSelection = false;
return;
}
- globals.dispatch(Actions.deselect({}));
+ globals.makeSelection(Actions.deselect({}));
}
},
m('.pinned-panel-container', m(PanelContainer, {
diff --git a/ui/src/tracks/all_controller.ts b/ui/src/tracks/all_controller.ts
index 7afaab6..79d3070 100644
--- a/ui/src/tracks/all_controller.ts
+++ b/ui/src/tracks/all_controller.ts
@@ -17,6 +17,7 @@
import './android_log/controller';
import './chrome_slices/controller';
import './counter/controller';
+import './heap_profile/controller';
import './cpu_freq/controller';
import './gpu_freq/controller';
import './cpu_slices/controller';
diff --git a/ui/src/tracks/all_frontend.ts b/ui/src/tracks/all_frontend.ts
index 9b59a76..dfa57fc 100644
--- a/ui/src/tracks/all_frontend.ts
+++ b/ui/src/tracks/all_frontend.ts
@@ -17,6 +17,7 @@
import './android_log/frontend';
import './chrome_slices/frontend';
import './counter/frontend';
+import './heap_profile/frontend';
import './cpu_freq/frontend';
import './gpu_freq/frontend';
import './cpu_slices/frontend';
diff --git a/ui/src/tracks/chrome_slices/frontend.ts b/ui/src/tracks/chrome_slices/frontend.ts
index 80e67f6..7038b4a 100644
--- a/ui/src/tracks/chrome_slices/frontend.ts
+++ b/ui/src/tracks/chrome_slices/frontend.ts
@@ -159,7 +159,7 @@
if (data === undefined) return false;
const sliceId = data.slice_ids[sliceIndex];
if (sliceId) {
- globals.dispatch(Actions.selectChromeSlice({slice_id: sliceId}));
+ globals.makeSelection(Actions.selectChromeSlice({slice_id: sliceId}));
return true;
}
return false;
diff --git a/ui/src/tracks/counter/common.ts b/ui/src/tracks/counter/common.ts
index ab2854a..0eb6dfb 100644
--- a/ui/src/tracks/counter/common.ts
+++ b/ui/src/tracks/counter/common.ts
@@ -23,6 +23,7 @@
timestamps: Float64Array;
values: Float64Array;
+ ids: Float64Array;
}
export interface Config {
@@ -30,4 +31,5 @@
maximumValue?: number;
minimumValue?: number;
ref: number;
+ scale?: 'DEFAULT'|'RELATIVE';
}
diff --git a/ui/src/tracks/counter/controller.ts b/ui/src/tracks/counter/controller.ts
index 2ef24af..4085845 100644
--- a/ui/src/tracks/counter/controller.ts
+++ b/ui/src/tracks/counter/controller.ts
@@ -94,15 +94,15 @@
// Union that with the query that finds all the counters within
// the current query range.
query = `
- select * from (select ts, value from counters
+ select * from (select ts, value, counter_id from counters
where name = '${this.config.name}' and ref = ${this.config.ref} and
ts <= ${startNs} order by ts desc limit 1)
UNION
- select * from (select ts, value
+ select * from (select ts, value, counter_id
from (select
ts,
lead(ts, 1, ts) over (partition by ref_type order by ts) as ts_end,
- value
+ value, counter_id
from counters
where name = '${this.config.name}' and ref = ${this.config.ref})
where ts <= ${endNs} and ${startNs} <= ts_end limit ${LIMIT});`;
@@ -122,25 +122,36 @@
resolution,
timestamps: new Float64Array(numRows),
values: new Float64Array(numRows),
+ ids: new Float64Array(numRows),
};
const cols = rawResult.columns;
for (let row = 0; row < numRows; row++) {
const startSec = fromNs(+cols[0].longValues![row]);
const value = +cols[1].doubleValues![row];
+ const id = +cols[2].longValues![row];
data.timestamps[row] = startSec;
data.values[row] = value;
+ data.ids[row] = id;
}
return data;
}
private maximumValue() {
- return Math.max(this.config.maximumValue || 0, this.maximumValueSeen);
+ if (this.config.maximumValue === undefined) {
+ return this.maximumValueSeen;
+ } else {
+ return this.config.maximumValue;
+ }
}
private minimumValue() {
- return Math.min(this.config.minimumValue || 0, this.minimumValueSeen);
+ if (this.config.minimumValue === undefined) {
+ return this.minimumValueSeen;
+ } else {
+ return this.config.minimumValue;
+ }
}
}
diff --git a/ui/src/tracks/counter/frontend.ts b/ui/src/tracks/counter/frontend.ts
index 9226301..8060dd0 100644
--- a/ui/src/tracks/counter/frontend.ts
+++ b/ui/src/tracks/counter/frontend.ts
@@ -12,12 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import * as m from 'mithril';
+
import {searchSegment} from '../../base/binary_search';
import {assertTrue} from '../../base/logging';
+import {Actions} from '../../common/actions';
import {TrackState} from '../../common/state';
+import {toNs} from '../../common/time';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
import {Track} from '../../frontend/track';
+import {TrackButton, TrackButtonAttrs} from '../../frontend/track_panel';
import {trackRegistry} from '../../frontend/track_registry';
import {
@@ -45,6 +50,27 @@
super(trackState);
}
+ getTrackShellButtons(): Array<m.Vnode<TrackButtonAttrs>> {
+ const buttons: Array<m.Vnode<TrackButtonAttrs>> = [];
+ buttons.push(m(TrackButton, {
+ action: () => {
+ if (this.config.scale === 'RELATIVE') {
+ this.config.scale = 'DEFAULT';
+ } else {
+ this.config.scale = 'RELATIVE';
+ }
+ Actions.updateTrackConfig(
+ {id: this.trackState.id, config: this.config});
+ globals.rafScheduler.scheduleFullRedraw();
+ },
+ i: 'show_chart',
+ tooltip: (this.config.scale === 'RELATIVE') ? 'Use zero-based scale' :
+ 'Use relative scale',
+ selected: this.config.scale === 'RELATIVE',
+ }));
+ return buttons;
+ }
+
renderCanvas(ctx: CanvasRenderingContext2D): void {
// TODO: fonts and colors should come from the CSS and not hardcoded here.
const {timeScale, visibleWindowTime} = globals.frontendLocalState;
@@ -54,11 +80,10 @@
assertTrue(data.timestamps.length === data.values.length);
- const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
const endPx = Math.floor(timeScale.timeToPx(visibleWindowTime.end));
const zeroY = MARGIN_TOP + RECT_HEIGHT / (data.minimumValue < 0 ? 2 : 1);
- let lastX = startPx;
+ let lastX = Math.floor(timeScale.timeToPx(data.timestamps[0]));
let lastY = zeroY;
// Quantize the Y axis to quarters of powers of tens (7.5K, 10K, 12.5K).
@@ -69,9 +94,20 @@
const exp = Math.ceil(Math.log10(Math.max(yMax, 1)));
const pow10 = Math.pow(10, exp);
yMax = Math.ceil(yMax / (pow10 / 4)) * (pow10 / 4);
- const yRange = data.minimumValue < 0 ? yMax * 2 : yMax;
+ let yRange = 0;
const unitGroup = Math.floor(exp / 3);
- const yLabel = `${yMax / Math.pow(10, unitGroup * 3)} ${kUnits[unitGroup]}`;
+ let yMin = 0;
+ let yLabel = '';
+ if (this.config.scale === 'RELATIVE') {
+ yRange = data.maximumValue - data.minimumValue;
+ yMin = data.minimumValue;
+ yLabel = 'min - max';
+ } else {
+ yRange = data.minimumValue < 0 ? yMax * 2 : yMax;
+ yMin = data.minimumValue < 0 ? -yMax : 0;
+ yLabel = `${yMax / Math.pow(10, unitGroup * 3)} ${kUnits[unitGroup]}`;
+ }
+
// There are 360deg of hue. We want a scale that starts at green with
// exp <= 3 (<= 1KB), goes orange around exp = 6 (~1MB) and red/violet
// around exp >= 9 (1GB).
@@ -90,7 +126,7 @@
for (let i = 0; i < data.values.length; i++) {
const value = data.values[i];
const startTime = data.timestamps[i];
- const nextY = zeroY - Math.round((value / yRange) * RECT_HEIGHT);
+ const nextY = zeroY - Math.round(((value - yMin) / yRange) * RECT_HEIGHT);
if (nextY === lastY) continue;
lastX = Math.floor(timeScale.timeToPx(startTime));
@@ -105,7 +141,7 @@
ctx.stroke();
// Draw the Y=0 dashed line.
- ctx.strokeStyle = `hsl(${hue}, 10%, 15%)`;
+ ctx.strokeStyle = `hsl(${hue}, 10%, 71%)`;
ctx.beginPath();
ctx.setLineDash([2, 4]);
ctx.moveTo(0, zeroY);
@@ -129,7 +165,8 @@
const xEnd = this.hoveredTsEnd === undefined ?
endPx :
Math.floor(timeScale.timeToPx(this.hoveredTsEnd));
- const y = zeroY - Math.round((this.hoveredValue / yRange) * RECT_HEIGHT);
+ const y = zeroY -
+ Math.round(((this.hoveredValue - yMin) / yRange) * RECT_HEIGHT);
// Highlight line.
ctx.beginPath();
@@ -184,18 +221,31 @@
this.hoveredTs = left === -1 ? undefined : data.timestamps[left];
this.hoveredTsEnd = right === -1 ? undefined : data.timestamps[right];
this.hoveredValue = left === -1 ? undefined : data.values[left];
-
- // for (let i = 0; i < data.values.length; i++) {
- // if (data.timestamps[i] > time) break;
- // this.hoveredTs = data.timestamps[i];
- // this.hoveredValue = data.values[i];
- //}
}
onMouseOut() {
this.hoveredValue = undefined;
this.hoveredTs = undefined;
}
+
+ onMouseClick({x}: {x: number}) {
+ const data = this.data();
+ if (data === undefined) return false;
+ const {timeScale} = globals.frontendLocalState;
+ const time = timeScale.pxToTime(x);
+ const [left, right] = searchSegment(data.timestamps, time);
+ if (left === -1) {
+ return false;
+ } else {
+ const counterId = data.ids[left];
+ globals.makeSelection(Actions.selectCounter({
+ leftTs: toNs(data.timestamps[left]),
+ rightTs: right !== -1 ? toNs(data.timestamps[right]) : -1,
+ id: counterId
+ }));
+ return true;
+ }
+ }
}
trackRegistry.register(CounterTrack);
diff --git a/ui/src/tracks/cpu_slices/frontend.ts b/ui/src/tracks/cpu_slices/frontend.ts
index c158672..a25f7ba 100644
--- a/ui/src/tracks/cpu_slices/frontend.ts
+++ b/ui/src/tracks/cpu_slices/frontend.ts
@@ -307,9 +307,8 @@
const index = search(data.starts, time);
const id = index === -1 ? undefined : data.ids[index];
if (id && this.utidHoveredInThisTrack !== -1) {
- globals.frontendLocalState.searchIndex = -1;
- globals.dispatch(Actions.selectSlice(
- {utid: this.utidHoveredInThisTrack, id}));
+ globals.makeSelection(
+ Actions.selectSlice({utid: this.utidHoveredInThisTrack, id}));
return true;
}
return false;
diff --git a/ui/src/tracks/heap_profile/common.ts b/ui/src/tracks/heap_profile/common.ts
new file mode 100644
index 0000000..fc9da62
--- /dev/null
+++ b/ui/src/tracks/heap_profile/common.ts
@@ -0,0 +1,24 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+import {TrackData} from '../../common/track_data';
+
+export const HEAP_PROFILE_TRACK_KIND = 'HeapProfileTrack';
+
+export interface Data extends TrackData {
+ tsStarts: Float64Array;
+}
+
+export interface Config {
+ upid: number;
+}
diff --git a/ui/src/tracks/heap_profile/controller.ts b/ui/src/tracks/heap_profile/controller.ts
new file mode 100644
index 0000000..61ad335
--- /dev/null
+++ b/ui/src/tracks/heap_profile/controller.ts
@@ -0,0 +1,53 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import {
+ TrackController,
+ trackControllerRegistry
+} from '../../controller/track_controller';
+
+import {
+ Config,
+ Data,
+ HEAP_PROFILE_TRACK_KIND,
+} from './common';
+
+class HeapProfileTrackController extends TrackController<Config, Data> {
+ static readonly kind = HEAP_PROFILE_TRACK_KIND;
+ async onBoundsChange(start: number, end: number, resolution: number):
+ Promise<Data> {
+ if (this.config.upid === undefined) {
+ return {start, end, resolution, length: 0, tsStarts: new Float64Array()};
+ }
+ const result = await this.query(`
+ select distinct(ts) from heap_profile_allocation where upid = ${
+ this.config.upid}`);
+ const numRows = +result.numRecords;
+ const data: Data = {
+ start,
+ end,
+ resolution,
+ length: numRows,
+ tsStarts: new Float64Array(numRows),
+ };
+
+ for (let row = 0; row < numRows; row++) {
+ data.tsStarts[row] = +result.columns[0].longValues![row];
+ }
+
+ return data;
+ }
+}
+
+trackControllerRegistry.register(HeapProfileTrackController);
diff --git a/ui/src/tracks/heap_profile/frontend.ts b/ui/src/tracks/heap_profile/frontend.ts
new file mode 100644
index 0000000..20a850e
--- /dev/null
+++ b/ui/src/tracks/heap_profile/frontend.ts
@@ -0,0 +1,110 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import {searchSegment} from '../../base/binary_search';
+import {Actions} from '../../common/actions';
+import {TrackState} from '../../common/state';
+import {fromNs, toNs} from '../../common/time';
+import {globals} from '../../frontend/globals';
+import {Track} from '../../frontend/track';
+import {trackRegistry} from '../../frontend/track_registry';
+
+import {Config, Data, HEAP_PROFILE_TRACK_KIND} from './common';
+
+// 0.5 Makes the horizontal lines sharp.
+const MARGIN_TOP = 4.5;
+const RECT_HEIGHT = 30.5;
+
+class HeapProfileTrack extends Track<Config, Data> {
+ private centerY = this.getHeight() / 2;
+ private width = (this.getHeight() - MARGIN_TOP) / 2;
+
+ static readonly kind = HEAP_PROFILE_TRACK_KIND;
+ static create(trackState: TrackState): HeapProfileTrack {
+ return new HeapProfileTrack(trackState);
+ }
+
+ constructor(trackState: TrackState) {
+ super(trackState);
+ }
+
+ getHeight() {
+ return MARGIN_TOP + RECT_HEIGHT - 1;
+ }
+
+ renderCanvas(ctx: CanvasRenderingContext2D): void {
+ const {
+ timeScale,
+ } = globals.frontendLocalState;
+ const data = this.data();
+
+ if (data === undefined) return;
+
+ for (let i = 0; i < data.tsStarts.length; i++) {
+ const centerX = data.tsStarts[i];
+ this.drawMarker(ctx, timeScale.timeToPx(fromNs(centerX)), this.centerY);
+ }
+ }
+
+ drawMarker(ctx: CanvasRenderingContext2D, x: number, y: number): void {
+ ctx.fillStyle = '#d9b3ff';
+ ctx.beginPath();
+ ctx.moveTo(x, y - this.width);
+ ctx.lineTo(x - this.width, y);
+ ctx.lineTo(x, y + this.width);
+ ctx.lineTo(x + this.width, y);
+ ctx.lineTo(x, y - this.width);
+ ctx.fill();
+ ctx.closePath();
+ }
+
+ // TODO(tneda): Add a border to show the currently selected marker and
+ // a hover state.
+ onMouseClick({x, y}: {x: number, y: number}) {
+ const data = this.data();
+ if (data === undefined) return false;
+ const {timeScale} = globals.frontendLocalState;
+
+ const time = toNs(timeScale.pxToTime(x));
+ const [left, right] = searchSegment(data.tsStarts, time);
+
+ let index = -1;
+ if (left !== -1) {
+ const centerX = timeScale.timeToPx(fromNs(data.tsStarts[left]));
+ if (this.isInMarker(x, y, centerX)) {
+ index = left;
+ }
+ }
+ if (right !== -1) {
+ const centerX = timeScale.timeToPx(fromNs(data.tsStarts[right]));
+ if (this.isInMarker(x, y, centerX)) {
+ index = right;
+ }
+ }
+
+ // If the markers overlap the rightmost one will be selected.
+ if (index !== -1) {
+ globals.makeSelection(Actions.selectHeapDump(
+ {id: index, upid: this.config.upid, ts: data.tsStarts[index]}));
+ return true;
+ }
+ return false;
+ }
+
+ isInMarker(x: number, y: number, centerX: number) {
+ return Math.abs(x - centerX) + Math.abs(y - this.centerY) <= this.width;
+ }
+}
+
+trackRegistry.register(HeapProfileTrack);
diff --git a/ui/src/tracks/process_summary/controller.ts b/ui/src/tracks/process_summary/controller.ts
index d18cb6b..a7a73aa 100644
--- a/ui/src/tracks/process_summary/controller.ts
+++ b/ui/src/tracks/process_summary/controller.ts
@@ -83,7 +83,8 @@
bucketSizeNs: number): Promise<Data> {
const startNs = toNs(start);
const endNs = toNs(end);
- const numBuckets = Math.ceil((endNs - startNs) / bucketSizeNs);
+ const numBuckets =
+ Math.min(Math.ceil((endNs - startNs) / bucketSizeNs), LIMIT);
const query = `select
quantum_ts as bucket,
@@ -99,13 +100,16 @@
start,
end,
resolution,
- length: numRows,
+ length: numBuckets,
bucketSizeSeconds: fromNs(bucketSizeNs),
utilizations: new Float64Array(numBuckets),
};
const cols = rawResult.columns;
for (let row = 0; row < numRows; row++) {
const bucket = +cols[0].longValues![row];
+ if (bucket > numBuckets) {
+ continue;
+ }
summary.utilizations[bucket] = +cols[1].doubleValues![row];
}
return summary;
diff --git a/ui/src/tracks/thread_state/frontend.ts b/ui/src/tracks/thread_state/frontend.ts
index 85c4504..d4fc287 100644
--- a/ui/src/tracks/thread_state/frontend.ts
+++ b/ui/src/tracks/thread_state/frontend.ts
@@ -118,7 +118,7 @@
const cpu = index === -1 ? undefined : data.cpu[index];
const utid = this.config.utid;
if (ts && state && tsEnd && cpu !== undefined) {
- globals.dispatch(
+ globals.makeSelection(
Actions.selectThreadState({utid, ts, dur: tsEnd - ts, state, cpu}));
return true;
}