Merge "TraceProcessor RPC: add binary-pipe interface"
diff --git a/include/perfetto/tracing/event_context.h b/include/perfetto/tracing/event_context.h
index 21cb788..e0c1a16 100644
--- a/include/perfetto/tracing/event_context.h
+++ b/include/perfetto/tracing/event_context.h
@@ -72,7 +72,7 @@
static_assert(std::is_base_of<protozero::Message, MessageType>::value,
"TracedProto can be used only with protozero messages");
- return TracedProto<MessageType>(message, *this);
+ return TracedProto<MessageType>(message, this);
}
private:
diff --git a/include/perfetto/tracing/traced_proto.h b/include/perfetto/tracing/traced_proto.h
index a52972b..4298bcc 100644
--- a/include/perfetto/tracing/traced_proto.h
+++ b/include/perfetto/tracing/traced_proto.h
@@ -60,8 +60,6 @@
MessageType* message() { return message_; }
- EventContext& context() const { return context_; }
-
// Write additional untyped values into the same context, which is useful
// when a given C++ class has a typed representation, but also either has
// members which can only be written into an untyped context (e.g. they are
@@ -87,14 +85,47 @@
return TracedDictionary(message_, MessageType::kDebugAnnotations, nullptr);
}
+ // Write a nested message into a field according to the provided metadata.
+ template <typename FieldMetadata>
+ TracedProto<typename FieldMetadata::cpp_field_type> WriteNestedMessage() {
+ static_assert(std::is_base_of<MessageType,
+ typename FieldMetadata::message_type>::value,
+ "Field should belong to the current message");
+ return TracedProto<typename FieldMetadata::cpp_field_type>(
+ message_->template BeginNestedMessage<
+ typename FieldMetadata::cpp_field_type>(FieldMetadata::kFieldId),
+ context_);
+ }
+
+ template <typename FieldMetadata>
+ TracedProto<typename FieldMetadata::cpp_field_type> WriteNestedMessage(
+ protozero::proto_utils::internal::FieldMetadataHelper<FieldMetadata>) {
+ return WriteNestedMessage<FieldMetadata>();
+ }
+
private:
friend class EventContext;
+ // Allow TracedProto<Foo> to create TracedProto<Bar>.
+ template <typename T>
+ friend class TracedProto;
- TracedProto(MessageType* message, EventContext& context)
+ // Wraps a raw protozero message using the same context as the current object.
+ template <typename ChildMessageType>
+ TracedProto<ChildMessageType> Wrap(ChildMessageType* message) {
+ return TracedProto(message, context_);
+ }
+
+ // Context might be null here when writing typed message which is
+ // nested into untyped legacy trace event macro argument.
+ // TODO(altimin): Turn this into EventContext& when this case is eliminated
+ // and expose it in public API.
+ EventContext* context() const { return context_; }
+
+ TracedProto(MessageType* message, EventContext* context)
: message_(message), context_(context) {}
MessageType* const message_;
- EventContext& context_;
+ EventContext* context_;
};
namespace internal {
@@ -157,11 +188,7 @@
std::is_same<Check, void>::value>
Write(TracedProto<Proto> context, ValueType&& value) {
// TODO(altimin): support TraceFormatTraits here.
- value.WriteIntoTrace(
- context.context().Wrap(context.message()
- ->template BeginNestedMessage<
- typename FieldMetadata::cpp_field_type>(
- FieldMetadata::kFieldId)));
+ value.WriteIntoTrace(context.template WriteNestedMessage<FieldMetadata>());
}
// Nested repeated non-packed field.
@@ -173,11 +200,7 @@
Write(TracedProto<Proto> context, ValueType&& value) {
// TODO(altimin): support TraceFormatTraits here.
for (auto&& item : value) {
- item.WriteIntoTrace(context.context().Wrap(
- context.message()
- ->template BeginNestedMessage<
- typename FieldMetadata::cpp_field_type>(
- FieldMetadata::kFieldId)));
+ item.WriteIntoTrace(context.template WriteNestedMessage<FieldMetadata>());
}
}
};
diff --git a/src/android_stats/perfetto_atoms.h b/src/android_stats/perfetto_atoms.h
index 3731c2e..0a857b9 100644
--- a/src/android_stats/perfetto_atoms.h
+++ b/src/android_stats/perfetto_atoms.h
@@ -69,6 +69,7 @@
kTracedEnableTracingUnknown = 35,
kTracedStartTracingInvalidSessionState = 36,
kTracedEnableTracingInvalidFilter = 47,
+ kTracedEnableTracingOobTargetBuffer = 48,
// Checkpoints inside perfetto_cmd after tracing has finished.
kOnTracingDisabled = 4,
diff --git a/src/profiling/memory/shared_ring_buffer_write_fuzzer.cc b/src/profiling/memory/shared_ring_buffer_write_fuzzer.cc
index 486033e..62b82eb 100644
--- a/src/profiling/memory/shared_ring_buffer_write_fuzzer.cc
+++ b/src/profiling/memory/shared_ring_buffer_write_fuzzer.cc
@@ -70,6 +70,7 @@
memcpy(&header, data, sizeof(header));
SharedRingBuffer::MetadataPage& metadata_page = header.metadata_page;
metadata_page.spinlock.locked = false;
+ metadata_page.spinlock.poisoned = false;
PERFETTO_CHECK(ftruncate(*fd, static_cast<off_t>(total_size_pages *
base::kPageSize)) == 0);
diff --git a/src/trace_processor/importers/proto/profiler_util.cc b/src/trace_processor/importers/proto/profiler_util.cc
index 175942f..c28f2fc 100644
--- a/src/trace_processor/importers/proto/profiler_util.cc
+++ b/src/trace_processor/importers/proto/profiler_util.cc
@@ -104,7 +104,8 @@
return "com.google.android.gm";
}
- if (location.find("PrebuiltGmsCore") != std::string::npos) {
+ if (location.find("PrebuiltGmsCore") != std::string::npos ||
+ location.find("com.google.android.gms") != std::string::npos) {
return "com.google.android.gms";
}
diff --git a/src/trace_processor/importers/proto/track_event_parser.cc b/src/trace_processor/importers/proto/track_event_parser.cc
index 7926bd3..6be84c5 100644
--- a/src/trace_processor/importers/proto/track_event_parser.cc
+++ b/src/trace_processor/importers/proto/track_event_parser.cc
@@ -110,6 +110,8 @@
}
bool AddJson(const Key& key, const protozero::ConstChars& value) final {
auto json_value = json::ParseJsonString(value);
+ if (!json_value)
+ return false;
return json::AddJsonValueToArgs(*json_value, base::StringView(key.flat_key),
base::StringView(key.key), &storage_,
&inserter_);
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index 63839b0..1a5b43d 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -647,6 +647,21 @@
return PERFETTO_SVC_ERR("Too many buffers configured (%d)",
cfg.buffers_size());
}
+ // Check that the config specifies all buffers for its data sources. This
+ // is also checked in SetupDataSource, but it is simpler to return a proper
+ // error to the consumer from here (and there will be less state to undo).
+ for (const TraceConfig::DataSource& cfg_data_source : cfg.data_sources()) {
+ size_t num_buffers = static_cast<size_t>(cfg.buffers_size());
+ size_t target_buffer = cfg_data_source.config().target_buffer();
+ if (target_buffer >= num_buffers) {
+ MaybeLogUploadEvent(
+ cfg, PerfettoStatsdAtom::kTracedEnableTracingOobTargetBuffer);
+ return PERFETTO_SVC_ERR(
+ "Data source \"%s\" specified an out of bounds target_buffer (%zu >= "
+ "%zu)",
+ cfg_data_source.config().name().c_str(), target_buffer, num_buffers);
+ }
+ }
if (!cfg.unique_session_name().empty()) {
const std::string& name = cfg.unique_session_name();
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index d91a3bb..1b3580e 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -544,11 +544,13 @@
let hasSliceName = false;
let hasDur = false;
let hasUpid = false;
+ let hasValue = false;
for (let i = 0; i < slowlyCountRows(result); i++) {
const name = result.columns[1].stringValues![i];
hasSliceName = hasSliceName || name === 'slice_name';
hasDur = hasDur || name === 'dur';
hasUpid = hasUpid || name === 'upid';
+ hasValue = hasValue || name === 'value';
}
const upidColumnSelect = hasUpid ? 'upid' : '0 AS upid';
@@ -579,7 +581,6 @@
`);
}
- const hasValue = result.columnDescriptors.some(x => x.name === 'value');
if (hasValue) {
const minMax = await engine.query(`
SELECT MIN(value) as min_value, MAX(value) as max_value