Merge changes Idcc16653,I6c774825
* changes:
trace_processor: Import statsd atom trace events
bazel: Fix arm64 build
diff --git a/Android.bp b/Android.bp
index 1c4d613..89c806c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -2100,6 +2100,7 @@
"perfetto_src_base_version_gen_h",
"perfetto_src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
"perfetto_src_trace_processor_importers_gen_cc_config_descriptor",
+ "perfetto_src_trace_processor_importers_gen_cc_statsd_atoms_descriptor",
"perfetto_src_trace_processor_importers_gen_cc_track_event_descriptor",
"perfetto_src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
"perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
@@ -8824,6 +8825,21 @@
],
}
+// GN: //src/trace_processor/importers:gen_cc_statsd_atoms_descriptor
+genrule {
+ name: "perfetto_src_trace_processor_importers_gen_cc_statsd_atoms_descriptor",
+ srcs: [
+ "src/trace_processor/importers/proto/atoms.descriptor",
+ ],
+ cmd: "$(location tools/gen_cc_proto_descriptor.py) --gen_dir=$(genDir) --cpp_out=$(out) $(in)",
+ out: [
+ "src/trace_processor/importers/atoms.descriptor.h",
+ ],
+ tool_files: [
+ "tools/gen_cc_proto_descriptor.py",
+ ],
+}
+
// GN: //src/trace_processor/importers:gen_cc_track_event_descriptor
genrule {
name: "perfetto_src_trace_processor_importers_gen_cc_track_event_descriptor",
@@ -9199,6 +9215,7 @@
"src/trace_processor/importers/proto/proto_trace_parser.cc",
"src/trace_processor/importers/proto/proto_trace_reader.cc",
"src/trace_processor/importers/proto/proto_trace_tokenizer.cc",
+ "src/trace_processor/importers/proto/statsd_module.cc",
"src/trace_processor/importers/proto/track_event_module.cc",
"src/trace_processor/importers/proto/track_event_parser.cc",
"src/trace_processor/importers/proto/track_event_tokenizer.cc",
@@ -10808,6 +10825,7 @@
"perfetto_src_trace_processor_gen_cc_test_messages_descriptor",
"perfetto_src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
"perfetto_src_trace_processor_importers_gen_cc_config_descriptor",
+ "perfetto_src_trace_processor_importers_gen_cc_statsd_atoms_descriptor",
"perfetto_src_trace_processor_importers_gen_cc_track_event_descriptor",
"perfetto_src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
"perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
@@ -10990,6 +11008,7 @@
"perfetto_src_base_version_gen_h",
"perfetto_src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
"perfetto_src_trace_processor_importers_gen_cc_config_descriptor",
+ "perfetto_src_trace_processor_importers_gen_cc_statsd_atoms_descriptor",
"perfetto_src_trace_processor_importers_gen_cc_track_event_descriptor",
"perfetto_src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
"perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
@@ -11164,6 +11183,7 @@
"perfetto_src_base_version_gen_h",
"perfetto_src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
"perfetto_src_trace_processor_importers_gen_cc_config_descriptor",
+ "perfetto_src_trace_processor_importers_gen_cc_statsd_atoms_descriptor",
"perfetto_src_trace_processor_importers_gen_cc_track_event_descriptor",
"perfetto_src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
"perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
diff --git a/BUILD b/BUILD
index 8d5d7c7..c7c272d 100644
--- a/BUILD
+++ b/BUILD
@@ -1152,6 +1152,16 @@
)
perfetto_cc_proto_descriptor(
+ name = "src_trace_processor_importers_gen_cc_statsd_atoms_descriptor",
+ deps = [
+ "src/trace_processor/importers/proto/atoms.descriptor",
+ ],
+ outs = [
+ "src/trace_processor/importers/atoms.descriptor.h",
+ ],
+)
+
+perfetto_cc_proto_descriptor(
name = "src_trace_processor_importers_gen_cc_track_event_descriptor",
deps = [
":protos_perfetto_trace_track_event_descriptor",
@@ -1676,6 +1686,8 @@
"src/trace_processor/importers/proto/proto_trace_reader.h",
"src/trace_processor/importers/proto/proto_trace_tokenizer.cc",
"src/trace_processor/importers/proto/proto_trace_tokenizer.h",
+ "src/trace_processor/importers/proto/statsd_module.cc",
+ "src/trace_processor/importers/proto/statsd_module.h",
"src/trace_processor/importers/proto/track_event_module.cc",
"src/trace_processor/importers/proto/track_event_module.h",
"src/trace_processor/importers/proto/track_event_parser.cc",
@@ -4070,6 +4082,7 @@
":src_trace_processor_containers_containers",
":src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
":src_trace_processor_importers_gen_cc_config_descriptor",
+ ":src_trace_processor_importers_gen_cc_statsd_atoms_descriptor",
":src_trace_processor_importers_gen_cc_track_event_descriptor",
":src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
":src_trace_processor_metrics_gen_cc_metrics_descriptor",
@@ -4177,6 +4190,7 @@
":src_trace_processor_containers_containers",
":src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
":src_trace_processor_importers_gen_cc_config_descriptor",
+ ":src_trace_processor_importers_gen_cc_statsd_atoms_descriptor",
":src_trace_processor_importers_gen_cc_track_event_descriptor",
":src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
":src_trace_processor_metrics_gen_cc_metrics_descriptor",
@@ -4347,6 +4361,7 @@
":src_trace_processor_containers_containers",
":src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
":src_trace_processor_importers_gen_cc_config_descriptor",
+ ":src_trace_processor_importers_gen_cc_statsd_atoms_descriptor",
":src_trace_processor_importers_gen_cc_track_event_descriptor",
":src_trace_processor_metrics_gen_cc_all_chrome_metrics_descriptor",
":src_trace_processor_metrics_gen_cc_metrics_descriptor",
diff --git a/bazel/BUILD b/bazel/BUILD
index bf64b69..bb4a04b 100644
--- a/bazel/BUILD
+++ b/bazel/BUILD
@@ -21,6 +21,14 @@
)
config_setting(
+ name = "cpu_arm64",
+ constraint_values = [
+ "@platforms//cpu:arm64",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+config_setting(
name = "os_linux",
constraint_values = [
"@platforms//os:linux",
diff --git a/bazel/zlib.BUILD b/bazel/zlib.BUILD
index cd4a6d3..9c203dd 100644
--- a/bazel/zlib.BUILD
+++ b/bazel/zlib.BUILD
@@ -46,7 +46,10 @@
"zlib.h",
"zutil.c",
"zutil.h",
- ],
+ ] + select({
+ "@perfetto//bazel:cpu_arm64": ["contrib/optimizations/slide_hash_neon.h"],
+ "//conditions:default": [],
+ }),
hdrs = [
"zlib.h",
],
diff --git a/gn/perfetto_cc_proto_descriptor.gni b/gn/perfetto_cc_proto_descriptor.gni
index 852dc0b..57efba7 100644
--- a/gn/perfetto_cc_proto_descriptor.gni
+++ b/gn/perfetto_cc_proto_descriptor.gni
@@ -15,18 +15,31 @@
import("perfetto.gni")
template("perfetto_cc_proto_descriptor") {
+ is_target = defined(invoker.descriptor_target)
+ is_path = defined(invoker.descriptor_path)
+
+ # You must define exactly one of:
+ # descriptor_target
+ # descriptor_path
+ assert((is_target || is_path) && !(is_target && is_path))
+
config("${target_name}_config") {
include_dirs = [ "${root_gen_dir}/${perfetto_root_path}" ]
}
action(target_name) {
generated_header = "${target_gen_dir}/${invoker.descriptor_name}.h"
- descriptor_file_path =
- get_label_info(invoker.descriptor_target, "target_gen_dir") +
- "/${invoker.descriptor_name}"
+ if (is_target) {
+ descriptor_file_path =
+ get_label_info(invoker.descriptor_target, "target_gen_dir") +
+ "/${invoker.descriptor_name}"
+ deps = [ invoker.descriptor_target ]
+ } else {
+ descriptor_file_path = invoker.descriptor_path
+ deps = []
+ }
script = "$perfetto_root_path/tools/gen_cc_proto_descriptor.py"
- deps = [ invoker.descriptor_target ]
args = [
"--gen_dir",
rebase_path(root_gen_dir, root_build_dir),
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index c692f8a..17d5982 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -139,6 +139,10 @@
"importers/proto/proto_trace_reader.h",
"importers/proto/proto_trace_tokenizer.cc",
"importers/proto/proto_trace_tokenizer.h",
+
+ # XXX: is this the correct place
+ "importers/proto/statsd_module.cc",
+ "importers/proto/statsd_module.h",
"importers/proto/track_event_module.cc",
"importers/proto/track_event_module.h",
"importers/proto/track_event_parser.cc",
@@ -168,6 +172,7 @@
"../protozero",
"containers",
"importers:gen_cc_chrome_track_event_descriptor",
+ "importers:gen_cc_statsd_atoms_descriptor",
"importers:gen_cc_track_event_descriptor",
"importers/common",
"importers/memory_tracker:graph_processor",
@@ -195,6 +200,7 @@
"../../protos/perfetto/trace/power:zero",
"../../protos/perfetto/trace/profiling:zero",
"../../protos/perfetto/trace/ps:zero",
+ "../../protos/perfetto/trace/statsd:zero",
"../../protos/perfetto/trace/sys_stats:zero",
"../../protos/perfetto/trace/system_info:zero",
"../../protos/perfetto/trace/track_event:zero",
diff --git a/src/trace_processor/importers/BUILD.gn b/src/trace_processor/importers/BUILD.gn
index 908ae8d..ad01aac 100644
--- a/src/trace_processor/importers/BUILD.gn
+++ b/src/trace_processor/importers/BUILD.gn
@@ -14,6 +14,11 @@
import("../../../gn/perfetto_cc_proto_descriptor.gni")
+perfetto_cc_proto_descriptor("gen_cc_statsd_atoms_descriptor") {
+ descriptor_name = "atoms.descriptor"
+ descriptor_path = "./proto/atoms.descriptor"
+}
+
perfetto_cc_proto_descriptor("gen_cc_config_descriptor") {
descriptor_name = "config.descriptor"
descriptor_target = "../../../protos/perfetto/config:descriptor"
diff --git a/src/trace_processor/importers/additional_modules.cc b/src/trace_processor/importers/additional_modules.cc
index 5368ed9..7fbbeb5 100644
--- a/src/trace_processor/importers/additional_modules.cc
+++ b/src/trace_processor/importers/additional_modules.cc
@@ -19,6 +19,7 @@
#include "src/trace_processor/importers/proto/android_probes_module.h"
#include "src/trace_processor/importers/proto/graphics_event_module.h"
#include "src/trace_processor/importers/proto/heap_graph_module.h"
+#include "src/trace_processor/importers/proto/statsd_module.h"
#include "src/trace_processor/importers/proto/system_probes_module.h"
#include "src/trace_processor/importers/proto/translation_table_module.h"
@@ -31,9 +32,11 @@
context->modules.emplace_back(new HeapGraphModule(context));
context->modules.emplace_back(new SystemProbesModule(context));
context->modules.emplace_back(new TranslationTableModule(context));
- context->modules.emplace_back(new FtraceModuleImpl(context));
+ context->modules.emplace_back(new StatsdModule(context));
+
// Ftrace module is special, because it has one extra method for parsing
// ftrace packets. So we need to store a pointer to it separately.
+ context->modules.emplace_back(new FtraceModuleImpl(context));
context->ftrace_module =
static_cast<FtraceModule*>(context->modules.back().get());
}
diff --git a/src/trace_processor/importers/proto/statsd_module.cc b/src/trace_processor/importers/proto/statsd_module.cc
new file mode 100644
index 0000000..7b2d8aa
--- /dev/null
+++ b/src/trace_processor/importers/proto/statsd_module.cc
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2022 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/importers/proto/statsd_module.h"
+
+#include "perfetto/ext/base/string_utils.h"
+#include "protos/perfetto/trace/statsd/statsd_atom.pbzero.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "src/trace_processor/importers/common/slice_tracker.h"
+#include "src/trace_processor/importers/common/track_tracker.h"
+#include "src/trace_processor/importers/proto/async_track_set_tracker.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/timestamped_trace_piece.h"
+#include "src/trace_processor/trace_sorter.h"
+#include "src/trace_processor/util/descriptors.h"
+
+#include "src/trace_processor/importers/atoms.descriptor.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+constexpr const char* kAtomProtoName = ".android.os.statsd.Atom";
+
+using BoundInserter = ArgsTracker::BoundInserter;
+
+class InserterDelegate : public util::ProtoToArgsParser::Delegate {
+ public:
+ InserterDelegate(BoundInserter& inserter, TraceStorage& storage)
+ : inserter_(inserter), storage_(storage) {}
+ ~InserterDelegate() override = default;
+
+ using Key = util::ProtoToArgsParser::Key;
+
+ void AddInteger(const Key& key, int64_t value) override {
+ StringId flat_key_id =
+ storage_.InternString(base::StringView(key.flat_key));
+ StringId key_id = storage_.InternString(base::StringView(key.key));
+ Variadic variadic_val = Variadic::Integer(value);
+ inserter_.AddArg(flat_key_id, key_id, variadic_val);
+ }
+
+ void AddUnsignedInteger(const Key& key, uint64_t value) override {
+ StringId flat_key_id =
+ storage_.InternString(base::StringView(key.flat_key));
+ StringId key_id = storage_.InternString(base::StringView(key.key));
+ Variadic variadic_val = Variadic::UnsignedInteger(value);
+ inserter_.AddArg(flat_key_id, key_id, variadic_val);
+ }
+
+ void AddString(const Key& key, const protozero::ConstChars& value) override {
+ StringId flat_key_id =
+ storage_.InternString(base::StringView(key.flat_key));
+ StringId key_id = storage_.InternString(base::StringView(key.key));
+ Variadic variadic_val = Variadic::String(storage_.InternString(value));
+ inserter_.AddArg(flat_key_id, key_id, variadic_val);
+ }
+
+ void AddString(const Key& key, const std::string& value) override {
+ StringId flat_key_id =
+ storage_.InternString(base::StringView(key.flat_key));
+ StringId key_id = storage_.InternString(base::StringView(key.key));
+ Variadic variadic_val =
+ Variadic::String(storage_.InternString(base::StringView(value)));
+ inserter_.AddArg(flat_key_id, key_id, variadic_val);
+ }
+
+ void AddDouble(const Key& key, double value) override {
+ StringId flat_key_id =
+ storage_.InternString(base::StringView(key.flat_key));
+ StringId key_id = storage_.InternString(base::StringView(key.key));
+ Variadic variadic_val = Variadic::Real(value);
+ inserter_.AddArg(flat_key_id, key_id, variadic_val);
+ }
+
+ void AddPointer(const Key& key, const void* value) override {
+ StringId flat_key_id =
+ storage_.InternString(base::StringView(key.flat_key));
+ StringId key_id = storage_.InternString(base::StringView(key.key));
+ Variadic variadic_val =
+ Variadic::Pointer(reinterpret_cast<uintptr_t>(value));
+ inserter_.AddArg(flat_key_id, key_id, variadic_val);
+ }
+
+ void AddBoolean(const Key& key, bool value) override {
+ StringId flat_key_id =
+ storage_.InternString(base::StringView(key.flat_key));
+ StringId key_id = storage_.InternString(base::StringView(key.key));
+ Variadic variadic_val = Variadic::Boolean(value);
+ inserter_.AddArg(flat_key_id, key_id, variadic_val);
+ }
+
+ bool AddJson(const Key& key, const protozero::ConstChars& value) override {
+ 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_);
+ }
+
+ void AddNull(const Key& key) override {
+ StringId flat_key_id =
+ storage_.InternString(base::StringView(key.flat_key));
+ StringId key_id = storage_.InternString(base::StringView(key.key));
+ Variadic variadic_val = Variadic::Null();
+ inserter_.AddArg(flat_key_id, key_id, variadic_val);
+ }
+
+ size_t GetArrayEntryIndex(const std::string& array_key) override {
+ base::ignore_result(array_key);
+ return 0;
+ }
+
+ size_t IncrementArrayEntryIndex(const std::string& array_key) override {
+ base::ignore_result(array_key);
+ return 0;
+ }
+
+ PacketSequenceStateGeneration* seq_state() override { return nullptr; }
+
+ protected:
+ InternedMessageView* GetInternedMessageView(uint32_t field_id,
+ uint64_t iid) override {
+ base::ignore_result(field_id);
+ base::ignore_result(iid);
+ return nullptr;
+ }
+
+ private:
+ BoundInserter& inserter_;
+ TraceStorage& storage_;
+};
+
+} // namespace
+
+using perfetto::protos::pbzero::TracePacket;
+
+PoolAndDescriptor::PoolAndDescriptor(const uint8_t* data,
+ size_t size,
+ const char* name) {
+ pool_.AddFromFileDescriptorSet(data, size);
+ base::Optional<uint32_t> opt_idx = pool_.FindDescriptorIdx(name);
+ if (opt_idx.has_value()) {
+ descriptor_ = &pool_.descriptors()[opt_idx.value()];
+ }
+}
+
+PoolAndDescriptor::~PoolAndDescriptor() = default;
+
+StatsdModule::StatsdModule(TraceProcessorContext* context)
+ : context_(context),
+ pool_(kAtomsDescriptor.data(), kAtomsDescriptor.size(), kAtomProtoName),
+ args_parser_(*(pool_.pool())) {
+ RegisterForField(TracePacket::kStatsdAtomFieldNumber, context);
+}
+
+StatsdModule::~StatsdModule() = default;
+
+void StatsdModule::ParsePacket(const TracePacket::Decoder& decoder,
+ const TimestampedTracePiece& ttp,
+ uint32_t field_id) {
+ if (field_id != TracePacket::kStatsdAtomFieldNumber) {
+ return;
+ }
+ int64_t ts = ttp.timestamp;
+ const auto& atoms_wrapper =
+ protos::pbzero::StatsdAtom::Decoder(decoder.statsd_atom());
+ for (auto it = atoms_wrapper.nested(); it; ++it) {
+ ParseAtom(ts, *it);
+ }
+}
+
+void StatsdModule::ParseAtom(int64_t ts, protozero::ConstBytes nested_bytes) {
+ // nested_bytes is an Atom proto. We (deliberately) don't generate
+ // decoding code for every kind of atom (or the parent Atom proto)
+ // and instead use the descriptor to parse the args/name.
+
+ // Atom is a giant oneof of all the possible 'kinds' of atom so here
+ // we use the protozero decoder implementation to grab the first
+ // field id which we we use to look up the field name:
+ protozero::ProtoDecoder nested_decoder(nested_bytes);
+ protozero::Field field = nested_decoder.ReadField();
+ uint32_t nested_field_id = 0;
+ if (field.valid()) {
+ nested_field_id = field.id();
+ }
+ StringId atom_name = GetAtomName(nested_field_id);
+
+ AsyncTrackSetTracker::TrackSetId track_set = InternAsyncTrackSetId();
+ TrackId track = context_->async_track_set_tracker->Scoped(track_set, ts, 0);
+ base::Optional<SliceId> opt_slice =
+ context_->slice_tracker->Scoped(ts, track, kNullStringId, atom_name, 0);
+ if (!opt_slice) {
+ return;
+ }
+ SliceId slice = opt_slice.value();
+ auto inserter = context_->args_tracker->AddArgsTo(slice);
+ InserterDelegate delgate(inserter, *context_->storage.get());
+ args_parser_.ParseMessage(nested_bytes, kAtomProtoName,
+ nullptr /* parse all fields */, delgate);
+}
+
+StringId StatsdModule::GetAtomName(uint32_t atom_field_id) {
+ StringId* cached_name = atom_names_.Find(atom_field_id);
+ if (cached_name == nullptr) {
+ if (pool_.descriptor() == nullptr) {
+ return context_->storage->InternString("Could not load atom descriptor");
+ }
+
+ const auto& fields = pool_.descriptor()->fields();
+ const auto& field_it = fields.find(atom_field_id);
+ if (field_it == fields.end()) {
+ return context_->storage->InternString("Unknown atom");
+ }
+
+ const FieldDescriptor& field = field_it->second;
+ StringId name =
+ context_->storage->InternString(base::StringView(field.name()));
+ atom_names_[atom_field_id] = name;
+ return name;
+ }
+ return *cached_name;
+}
+
+AsyncTrackSetTracker::TrackSetId StatsdModule::InternAsyncTrackSetId() {
+ if (!track_set_id_) {
+ StringId name = context_->storage->InternString("Statsd Atoms");
+ track_set_id_ =
+ context_->async_track_set_tracker->InternGlobalTrackSet(name);
+ }
+ return track_set_id_.value();
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/statsd_module.h b/src/trace_processor/importers/proto/statsd_module.h
new file mode 100644
index 0000000..50184c0
--- /dev/null
+++ b/src/trace_processor/importers/proto/statsd_module.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 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_IMPORTERS_PROTO_STATSD_MODULE_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_STATSD_MODULE_H_
+
+#include <cstdint>
+
+#include "perfetto/ext/base/flat_hash_map.h"
+#include "perfetto/ext/base/optional.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "src/trace_processor/importers/proto/async_track_set_tracker.h"
+#include "src/trace_processor/importers/proto/proto_importer_module.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/tables/slice_tables.h"
+#include "src/trace_processor/tables/track_tables.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/util/descriptors.h"
+#include "src/trace_processor/util/proto_to_args_parser.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// Wraps a DescriptorPool and a pointer into that pool. This prevents
+// common bugs where moving/changing the pool invalidates the pointer.
+class PoolAndDescriptor {
+ public:
+ PoolAndDescriptor(const uint8_t* data, size_t size, const char* name);
+ virtual ~PoolAndDescriptor();
+
+ const DescriptorPool* pool() const { return &pool_; }
+
+ const ProtoDescriptor* descriptor() const { return descriptor_; }
+
+ private:
+ PoolAndDescriptor(const PoolAndDescriptor&) = delete;
+ PoolAndDescriptor& operator=(const PoolAndDescriptor&) = delete;
+ PoolAndDescriptor(PoolAndDescriptor&&) = delete;
+ PoolAndDescriptor& operator=(PoolAndDescriptor&&) = delete;
+
+ DescriptorPool pool_;
+ const ProtoDescriptor* descriptor_{};
+};
+
+class StatsdModule : public ProtoImporterModule {
+ public:
+ explicit StatsdModule(TraceProcessorContext* context);
+
+ ~StatsdModule() override;
+
+ void ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
+ const TimestampedTracePiece& ttp,
+ uint32_t field_id) override;
+
+ private:
+ void ParseAtom(int64_t ts, protozero::ConstBytes bytes);
+ StringId GetAtomName(uint32_t atom_field_id);
+ AsyncTrackSetTracker::TrackSetId InternAsyncTrackSetId();
+
+ TraceProcessorContext* context_;
+ base::FlatHashMap<uint32_t, StringId> atom_names_;
+ PoolAndDescriptor pool_;
+ util::ProtoToArgsParser args_parser_;
+ base::Optional<AsyncTrackSetTracker::TrackSetId> track_set_id_;
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_STATSD_MODULE_H_
diff --git a/test/data/statsd_atoms.pb.sha256 b/test/data/statsd_atoms.pb.sha256
new file mode 100644
index 0000000..934ccb7
--- /dev/null
+++ b/test/data/statsd_atoms.pb.sha256
@@ -0,0 +1 @@
+d68011231cf87c73baf1b459b3629fb5a8b248a8dde03e90118349b7573b06da
\ No newline at end of file
diff --git a/test/trace_processor/parsing/all_atoms_test.sql b/test/trace_processor/parsing/all_atoms_test.sql
new file mode 100644
index 0000000..b92a851
--- /dev/null
+++ b/test/trace_processor/parsing/all_atoms_test.sql
@@ -0,0 +1 @@
+SELECT slice.name, args.key, args.display_value FROM track JOIN slice ON track.id = slice.track_id JOIN args USING(arg_set_id) WHERE track.name = "Statsd Atoms";
diff --git a/test/trace_processor/parsing/index b/test/trace_processor/parsing/index
index ada90d1..e1cbe46 100644
--- a/test/trace_processor/parsing/index
+++ b/test/trace_processor/parsing/index
@@ -153,3 +153,6 @@
# Per-process Binder transaction metrics
android_binder.py android_binder android_binder.out
+
+# Statsd Atoms
+../../data/statsd_atoms.pb all_atoms_test.sql statsd_atoms_all_atoms.out
diff --git a/test/trace_processor/parsing/statsd_atoms_all_atoms.out b/test/trace_processor/parsing/statsd_atoms_all_atoms.out
new file mode 100644
index 0000000..2848fcf
--- /dev/null
+++ b/test/trace_processor/parsing/statsd_atoms_all_atoms.out
@@ -0,0 +1,39 @@
+"name","key","display_value"
+"system_uptime","system_uptime.uptime_millis","24559955"
+"system_uptime","system_uptime.uptime_millis","24559955"
+"system_uptime","system_uptime.uptime_millis","24560959"
+"system_uptime","system_uptime.uptime_millis","24560959"
+"system_uptime","system_uptime.uptime_millis","24561963"
+"system_uptime","system_uptime.uptime_millis","24561963"
+"system_uptime","system_uptime.uptime_millis","24562967"
+"system_uptime","system_uptime.uptime_millis","24562967"
+"system_uptime","system_uptime.uptime_millis","24563972"
+"system_uptime","system_uptime.uptime_millis","24563972"
+"system_uptime","system_uptime.uptime_millis","24564984"
+"system_uptime","system_uptime.uptime_millis","24564984"
+"flashlight_state_changed","flashlight_state_changed.attribution_node[0].uid","10218"
+"flashlight_state_changed","flashlight_state_changed.attribution_node[0].tag",""
+"flashlight_state_changed","flashlight_state_changed.state","ON"
+"system_uptime","system_uptime.uptime_millis","24565988"
+"system_uptime","system_uptime.uptime_millis","24565988"
+"flashlight_state_changed","flashlight_state_changed.attribution_node[0].uid","10218"
+"flashlight_state_changed","flashlight_state_changed.attribution_node[0].tag",""
+"flashlight_state_changed","flashlight_state_changed.state","OFF"
+"system_uptime","system_uptime.uptime_millis","24566992"
+"flashlight_state_changed","flashlight_state_changed.attribution_node[0].uid","10218"
+"flashlight_state_changed","flashlight_state_changed.attribution_node[0].tag",""
+"flashlight_state_changed","flashlight_state_changed.state","ON"
+"system_uptime","system_uptime.uptime_millis","24566992"
+"system_uptime","system_uptime.uptime_millis","24567996"
+"flashlight_state_changed","flashlight_state_changed.attribution_node[0].uid","10218"
+"flashlight_state_changed","flashlight_state_changed.attribution_node[0].tag",""
+"flashlight_state_changed","flashlight_state_changed.state","OFF"
+"system_uptime","system_uptime.uptime_millis","24567996"
+"system_uptime","system_uptime.uptime_millis","24569000"
+"flashlight_state_changed","flashlight_state_changed.attribution_node[0].uid","10218"
+"flashlight_state_changed","flashlight_state_changed.attribution_node[0].tag",""
+"flashlight_state_changed","flashlight_state_changed.state","ON"
+"system_uptime","system_uptime.uptime_millis","24569000"
+"flashlight_state_changed","flashlight_state_changed.attribution_node[0].uid","10218"
+"flashlight_state_changed","flashlight_state_changed.attribution_node[0].tag",""
+"flashlight_state_changed","flashlight_state_changed.state","OFF"
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index fccf537..a369ff7 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -793,6 +793,10 @@
module.genrule_headers.add(module.name)
module.srcs.update(
':' + label_to_module_name(dep) for dep in target.proto_deps)
+ module.srcs.update(
+ gn_utils.label_to_path(src)
+ for src in target.inputs
+ if "tmp.gn_utils" not in src)
module.out.update(target.outputs)
blueprint.add_module(module)
return module
diff --git a/tools/gen_bazel b/tools/gen_bazel
index 8754486..1c64257 100755
--- a/tools/gen_bazel
+++ b/tools/gen_bazel
@@ -141,6 +141,8 @@
label = BazelLabel(
get_bazel_label_name(target.name), 'perfetto_cc_proto_descriptor')
label.deps += [':' + get_bazel_label_name(x) for x in target.proto_deps]
+ label.deps += [gn_utils.label_to_path(src) for src in target.inputs if "tmp.gn_utils" not in src]
+
label.outs += target.outputs
return [label]