Merge "ui: Fix thread and process names being null"
diff --git a/Android.bp b/Android.bp
index 391cbec..6a66249 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3730,6 +3730,7 @@
"protos/perfetto/metrics/chrome/blink_gc_metric.proto",
"protos/perfetto/metrics/chrome/dropped_frames.proto",
"protos/perfetto/metrics/chrome/frame_times.proto",
+ "protos/perfetto/metrics/chrome/long_latency.proto",
"protos/perfetto/metrics/chrome/media_metric.proto",
"protos/perfetto/metrics/chrome/reported_by_page.proto",
"protos/perfetto/metrics/chrome/scroll_jank.proto",
@@ -8145,6 +8146,7 @@
name: "perfetto_src_trace_processor_importers_common_common",
srcs: [
"src/trace_processor/importers/common/args_tracker.cc",
+ "src/trace_processor/importers/common/args_translation_table.cc",
"src/trace_processor/importers/common/clock_tracker.cc",
"src/trace_processor/importers/common/event_tracker.cc",
"src/trace_processor/importers/common/flow_tracker.cc",
@@ -8160,6 +8162,7 @@
filegroup {
name: "perfetto_src_trace_processor_importers_common_unittests",
srcs: [
+ "src/trace_processor/importers/common/args_translation_table_unittest.cc",
"src/trace_processor/importers/common/clock_tracker_unittest.cc",
"src/trace_processor/importers/common/event_tracker_unittest.cc",
"src/trace_processor/importers/common/flow_tracker_unittest.cc",
@@ -8390,6 +8393,7 @@
"src/trace_processor/metrics/sql/chrome/touch_jank.sql",
"src/trace_processor/metrics/sql/experimental/blink_gc_metric.sql",
"src/trace_processor/metrics/sql/experimental/chrome_dropped_frames.sql",
+ "src/trace_processor/metrics/sql/experimental/chrome_long_latency.sql",
"src/trace_processor/metrics/sql/experimental/frame_times.sql",
"src/trace_processor/metrics/sql/experimental/media_metric.sql",
"src/trace_processor/metrics/sql/experimental/reported_by_page.sql",
@@ -8541,6 +8545,7 @@
"src/trace_processor/importers/proto/track_event_parser.cc",
"src/trace_processor/importers/proto/track_event_tokenizer.cc",
"src/trace_processor/importers/proto/track_event_tracker.cc",
+ "src/trace_processor/importers/proto/translation_table_module.cc",
"src/trace_processor/trace_blob.cc",
"src/trace_processor/trace_processor_context.cc",
"src/trace_processor/trace_processor_storage.cc",
diff --git a/BUILD b/BUILD
index dcdc2fc..3260a6e 100644
--- a/BUILD
+++ b/BUILD
@@ -971,6 +971,8 @@
srcs = [
"src/trace_processor/importers/common/args_tracker.cc",
"src/trace_processor/importers/common/args_tracker.h",
+ "src/trace_processor/importers/common/args_translation_table.cc",
+ "src/trace_processor/importers/common/args_translation_table.h",
"src/trace_processor/importers/common/chunked_trace_reader.h",
"src/trace_processor/importers/common/clock_tracker.cc",
"src/trace_processor/importers/common/clock_tracker.h",
@@ -1130,6 +1132,7 @@
"src/trace_processor/metrics/sql/chrome/touch_jank.sql",
"src/trace_processor/metrics/sql/experimental/blink_gc_metric.sql",
"src/trace_processor/metrics/sql/experimental/chrome_dropped_frames.sql",
+ "src/trace_processor/metrics/sql/experimental/chrome_long_latency.sql",
"src/trace_processor/metrics/sql/experimental/frame_times.sql",
"src/trace_processor/metrics/sql/experimental/media_metric.sql",
"src/trace_processor/metrics/sql/experimental/reported_by_page.sql",
@@ -1529,6 +1532,8 @@
"src/trace_processor/importers/proto/track_event_tokenizer.h",
"src/trace_processor/importers/proto/track_event_tracker.cc",
"src/trace_processor/importers/proto/track_event_tracker.h",
+ "src/trace_processor/importers/proto/translation_table_module.cc",
+ "src/trace_processor/importers/proto/translation_table_module.h",
"src/trace_processor/importers/syscalls/syscall_tracker.h",
"src/trace_processor/importers/systrace/systrace_line.h",
"src/trace_processor/timestamped_trace_piece.h",
@@ -2716,6 +2721,7 @@
"protos/perfetto/metrics/chrome/blink_gc_metric.proto",
"protos/perfetto/metrics/chrome/dropped_frames.proto",
"protos/perfetto/metrics/chrome/frame_times.proto",
+ "protos/perfetto/metrics/chrome/long_latency.proto",
"protos/perfetto/metrics/chrome/media_metric.proto",
"protos/perfetto/metrics/chrome/reported_by_page.proto",
"protos/perfetto/metrics/chrome/scroll_jank.proto",
diff --git a/include/perfetto/tracing/track.h b/include/perfetto/tracing/track.h
index f288e81..3a84364 100644
--- a/include/perfetto/tracing/track.h
+++ b/include/perfetto/tracing/track.h
@@ -115,6 +115,15 @@
parent);
}
+ // Construct a track using |ptr| as identifier within thread-scope.
+ // Shorthand for `Track::FromPointer(ptr, ThreadTrack::Current())`
+ // Usage: TRACE_EVENT_BEGIN("...", "...", perfetto::Track::ThreadScoped(this))
+ static Track ThreadScoped(
+ const void* ptr,
+ Track parent = MakeThreadTrack(base::GetThreadId())) {
+ return Track::FromPointer(ptr, parent);
+ }
+
protected:
constexpr Track(uint64_t uuid_, uint64_t parent_uuid_)
: uuid(uuid_), parent_uuid(parent_uuid_) {}
diff --git a/protos/perfetto/metrics/chrome/BUILD.gn b/protos/perfetto/metrics/chrome/BUILD.gn
index e686114..9e88247 100644
--- a/protos/perfetto/metrics/chrome/BUILD.gn
+++ b/protos/perfetto/metrics/chrome/BUILD.gn
@@ -25,6 +25,7 @@
"blink_gc_metric.proto",
"dropped_frames.proto",
"frame_times.proto",
+ "long_latency.proto",
"media_metric.proto",
"reported_by_page.proto",
"scroll_jank.proto",
diff --git a/protos/perfetto/metrics/chrome/all_chrome_metrics.proto b/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
index 2632405..4a24580 100644
--- a/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
+++ b/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
@@ -22,6 +22,7 @@
import "protos/perfetto/metrics/chrome/blink_gc_metric.proto";
import "protos/perfetto/metrics/chrome/dropped_frames.proto";
import "protos/perfetto/metrics/chrome/frame_times.proto";
+import "protos/perfetto/metrics/chrome/long_latency.proto";
import "protos/perfetto/metrics/chrome/media_metric.proto";
import "protos/perfetto/metrics/chrome/reported_by_page.proto";
import "protos/perfetto/metrics/chrome/scroll_jank.proto";
@@ -38,4 +39,5 @@
optional MediaMetric media_metric = 1006;
optional TouchJank touch_jank = 1007;
optional ChromeDroppedFrames chrome_dropped_frames = 1008;
+ optional ChromeLongLatency chrome_long_latency = 1009;
}
diff --git a/protos/perfetto/metrics/chrome/long_latency.proto b/protos/perfetto/metrics/chrome/long_latency.proto
new file mode 100644
index 0000000..2c5fbaf
--- /dev/null
+++ b/protos/perfetto/metrics/chrome/long_latency.proto
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+package perfetto.protos;
+
+// Information of a frame associated with long latency input events.
+// The latency info is extracted from EventLatency slices.
+message ChromeLongLatency {
+ message LongLatency {
+ // The ending timestamp of the input event, i.e. the presentation time of
+ // the frame that contains updates triggered by the input event.
+ optional int64 ts = 1;
+
+ // The type of the input event as reported in the EventLatency slice,
+ // e.g. 'GestureScrollUpdate'.
+ optional string event_type = 2;
+
+ // The name and pid of the process where the EventLatency slice
+ // originates from.
+ optional string process_name = 3;
+ optional int64 pid = 4;
+ }
+
+ repeated LongLatency long_latency = 1;
+}
\ No newline at end of file
diff --git a/src/protozero/test/example_proto/test_messages.proto b/src/protozero/test/example_proto/test_messages.proto
index 8e710b4..ba3e5d3 100644
--- a/src/protozero/test/example_proto/test_messages.proto
+++ b/src/protozero/test/example_proto/test_messages.proto
@@ -101,8 +101,26 @@
message PackedRepeatedFields {
repeated int32 field_int32 = 1 [packed = true];
+ repeated int64 field_int64 = 4 [packed = true];
+ repeated uint32 field_uint32 = 5 [packed = true];
+ repeated uint64 field_uint64 = 6 [packed = true];
+ // Repeated packed Zig-zag fields are currently unsupported by our protoc
+ // plugin.
+ // repeated sint32 field_sint32 = 7 [packed = true];
+ // repeated sint64 field_sint64 = 8 [packed = true];
repeated fixed32 field_fixed32 = 2 [packed = true];
+ repeated fixed64 field_fixed64 = 9 [packed = true];
+ repeated sfixed32 field_sfixed32 = 10 [packed = true];
repeated sfixed64 field_sfixed64 = 3 [packed = true];
+ repeated float field_float = 11 [packed = true];
+ repeated double field_double = 12 [packed = true];
+ // Repeated (even non-packed) bool fields are currently unsupported by our
+ // protoc plugin.
+ // repeated bool field_bool = 13 [packed = true];
+ // Repeated packed enum fields are currently unsupported by our protoc plugin.
+ // repeated SmallEnum small_enum = 51 [packed = true];
+ // repeated SignedEnum signed_enum = 52 [packed = true];
+ // repeated BigEnum big_enum = 53 [packed = true];
}
// The following two messages are for testing that unknown fields being
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 3cbfca5..45e9774 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -131,6 +131,8 @@
"importers/proto/track_event_tokenizer.h",
"importers/proto/track_event_tracker.cc",
"importers/proto/track_event_tracker.h",
+ "importers/proto/translation_table_module.cc",
+ "importers/proto/translation_table_module.h",
"importers/syscalls/syscall_tracker.h",
"importers/systrace/systrace_line.h",
"timestamped_trace_piece.h",
@@ -177,6 +179,7 @@
"../../protos/perfetto/trace/sys_stats:zero",
"../../protos/perfetto/trace/system_info:zero",
"../../protos/perfetto/trace/track_event:zero",
+ "../../protos/perfetto/trace/translation:zero",
]
# json_utils optionally depends on jsoncpp.
diff --git a/src/trace_processor/importers/additional_modules.cc b/src/trace_processor/importers/additional_modules.cc
index 1627893..5368ed9 100644
--- a/src/trace_processor/importers/additional_modules.cc
+++ b/src/trace_processor/importers/additional_modules.cc
@@ -20,6 +20,7 @@
#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/system_probes_module.h"
+#include "src/trace_processor/importers/proto/translation_table_module.h"
namespace perfetto {
namespace trace_processor {
@@ -29,6 +30,7 @@
context->modules.emplace_back(new GraphicsEventModule(context));
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));
// Ftrace module is special, because it has one extra method for parsing
// ftrace packets. So we need to store a pointer to it separately.
diff --git a/src/trace_processor/importers/common/BUILD.gn b/src/trace_processor/importers/common/BUILD.gn
index aa7f57c..534c2bb 100644
--- a/src/trace_processor/importers/common/BUILD.gn
+++ b/src/trace_processor/importers/common/BUILD.gn
@@ -18,6 +18,8 @@
sources = [
"args_tracker.cc",
"args_tracker.h",
+ "args_translation_table.cc",
+ "args_translation_table.h",
"chunked_trace_reader.h",
"clock_tracker.cc",
"clock_tracker.h",
@@ -56,6 +58,7 @@
source_set("unittests") {
sources = [
+ "args_translation_table_unittest.cc",
"clock_tracker_unittest.cc",
"event_tracker_unittest.cc",
"flow_tracker_unittest.cc",
diff --git a/src/trace_processor/importers/common/args_translation_table.cc b/src/trace_processor/importers/common/args_translation_table.cc
new file mode 100644
index 0000000..ee91b30
--- /dev/null
+++ b/src/trace_processor/importers/common/args_translation_table.cc
@@ -0,0 +1,38 @@
+/*
+ * 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/common/args_translation_table.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+base::Optional<base::StringView>
+ArgsTranslationTable::TranslateChromeHistogramHash(uint64_t hash) const {
+ auto* value = chrome_histogram_hash_to_name_.Find(hash);
+ if (!value) {
+ return base::nullopt;
+ }
+ return base::StringView(*value);
+}
+
+void ArgsTranslationTable::AddChromeHistogramTranslationRule(
+ uint64_t hash,
+ base::StringView name) {
+ chrome_histogram_hash_to_name_.Insert(hash, name.ToStdString());
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/common/args_translation_table.h b/src/trace_processor/importers/common/args_translation_table.h
new file mode 100644
index 0000000..0e34e2c
--- /dev/null
+++ b/src/trace_processor/importers/common/args_translation_table.h
@@ -0,0 +1,50 @@
+/*
+ * 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_COMMON_ARGS_TRANSLATION_TABLE_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_ARGS_TRANSLATION_TABLE_H_
+
+#include <cstdint>
+
+#include "perfetto/ext/base/flat_hash_map.h"
+#include "perfetto/ext/base/optional.h"
+#include "perfetto/ext/base/string_view.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// Tracks and stores args translation rules. It allows Trace Processor
+// to map for example hashes to their names.
+class ArgsTranslationTable {
+ public:
+ static constexpr char kChromeHistogramHashKey[] =
+ "chrome_histogram_sample.name_hash";
+ static constexpr char kChromeHistogramNameKey[] =
+ "chrome_histogram_sample.name";
+
+ base::Optional<base::StringView> TranslateChromeHistogramHash(
+ uint64_t hash) const;
+
+ void AddChromeHistogramTranslationRule(uint64_t hash, base::StringView name);
+
+ private:
+ base::FlatHashMap<uint64_t, std::string> chrome_histogram_hash_to_name_;
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_ARGS_TRANSLATION_TABLE_H_
diff --git a/src/trace_processor/importers/common/args_translation_table_unittest.cc b/src/trace_processor/importers/common/args_translation_table_unittest.cc
new file mode 100644
index 0000000..15dddff
--- /dev/null
+++ b/src/trace_processor/importers/common/args_translation_table_unittest.cc
@@ -0,0 +1,42 @@
+/*
+ * 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/common/args_translation_table.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+TEST(ArgsTranslationTable, EmptyTableByDefault) {
+ ArgsTranslationTable table;
+ EXPECT_EQ(table.TranslateChromeHistogramHash(1), base::nullopt);
+}
+
+TEST(ArgsTranslationTable, TranslatesHashes) {
+ ArgsTranslationTable table;
+ table.AddChromeHistogramTranslationRule(1, "hash1");
+ table.AddChromeHistogramTranslationRule(10, "hash2");
+ EXPECT_EQ(table.TranslateChromeHistogramHash(1),
+ base::Optional<base::StringView>("hash1"));
+ EXPECT_EQ(table.TranslateChromeHistogramHash(10),
+ base::Optional<base::StringView>("hash2"));
+ EXPECT_EQ(table.TranslateChromeHistogramHash(2), base::nullopt);
+}
+
+} // namespace
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/translation_table_module.cc b/src/trace_processor/importers/proto/translation_table_module.cc
new file mode 100644
index 0000000..cf523d9
--- /dev/null
+++ b/src/trace_processor/importers/proto/translation_table_module.cc
@@ -0,0 +1,61 @@
+/*
+ * 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/translation_table_module.h"
+
+#include "src/trace_processor/importers/common/args_translation_table.h"
+
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "protos/perfetto/trace/translation/translation_table.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+using perfetto::protos::pbzero::TracePacket;
+
+TranslationTableModule::TranslationTableModule(TraceProcessorContext* context)
+ : context_(context) {
+ RegisterForField(TracePacket::kTranslationTableFieldNumber, context);
+}
+
+TranslationTableModule::~TranslationTableModule() = default;
+
+void TranslationTableModule::ParsePacket(const TracePacket::Decoder& decoder,
+ const TimestampedTracePiece& /*ttp*/,
+ uint32_t field_id) {
+ if (field_id != TracePacket::kTranslationTableFieldNumber) {
+ return;
+ }
+ const auto translation_table =
+ protos::pbzero::TranslationTable::Decoder(decoder.translation_table());
+ if (translation_table.has_chrome_histogram()) {
+ ParseChromeHistogramRules(translation_table.chrome_histogram());
+ }
+}
+
+void TranslationTableModule::ParseChromeHistogramRules(
+ protozero::ConstBytes bytes) {
+ const auto chrome_histogram =
+ protos::pbzero::ChromeHistorgramTranslationTable::Decoder(bytes);
+ for (auto it = chrome_histogram.hash_to_name(); it; ++it) {
+ protos::pbzero::ChromeHistorgramTranslationTable::HashToNameEntry::Decoder
+ entry(*it);
+ context_->args_translation_table->AddChromeHistogramTranslationRule(
+ entry.key(), entry.value());
+ }
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/translation_table_module.h b/src/trace_processor/importers/proto/translation_table_module.h
new file mode 100644
index 0000000..c6c61a6
--- /dev/null
+++ b/src/trace_processor/importers/proto/translation_table_module.h
@@ -0,0 +1,49 @@
+/*
+ * 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_TRANSLATION_TABLE_MODULE_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRANSLATION_TABLE_MODULE_H_
+
+#include <cstdint>
+
+#include "perfetto/ext/base/optional.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "src/trace_processor/importers/proto/proto_importer_module.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class TranslationTableModule : public ProtoImporterModule {
+ public:
+ explicit TranslationTableModule(TraceProcessorContext* context);
+
+ ~TranslationTableModule() override;
+
+ void ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
+ const TimestampedTracePiece& ttp,
+ uint32_t field_id) override;
+
+ private:
+ void ParseChromeHistogramRules(protozero::ConstBytes bytes);
+
+ TraceProcessorContext* context_;
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRANSLATION_TABLE_MODULE_H_
diff --git a/src/trace_processor/metrics/sql/BUILD.gn b/src/trace_processor/metrics/sql/BUILD.gn
index f8de2ad..fbbb41c 100644
--- a/src/trace_processor/metrics/sql/BUILD.gn
+++ b/src/trace_processor/metrics/sql/BUILD.gn
@@ -110,6 +110,7 @@
"chrome/touch_jank.sql",
"experimental/blink_gc_metric.sql",
"experimental/chrome_dropped_frames.sql",
+ "experimental/chrome_long_latency.sql",
"experimental/frame_times.sql",
"experimental/media_metric.sql",
"experimental/reported_by_page.sql",
diff --git a/src/trace_processor/metrics/sql/experimental/chrome_long_latency.sql b/src/trace_processor/metrics/sql/experimental/chrome_long_latency.sql
new file mode 100644
index 0000000..26fc2b5
--- /dev/null
+++ b/src/trace_processor/metrics/sql/experimental/chrome_long_latency.sql
@@ -0,0 +1,104 @@
+--
+-- Copyright 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
+--
+-- https://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.
+
+-- Find all long EventLatency slices > 100ms and also get the
+-- type of the event stored as 'debug.event' argument.
+-- In order to group all events
+-- Note that a long latency event is represented by the the ending time
+-- of an EventLatency slice, i.e. the timestamp of the frame presentation
+-- that reflects the event.
+DROP VIEW IF EXISTS long_eventlatency_slice;
+CREATE VIEW long_eventlatency_slice AS
+SELECT
+ ts + dur AS ts,
+ dur,
+ id,
+ track_id,
+ EXTRACT_ARG(arg_set_id, 'debug.event') AS event_type
+FROM slice WHERE name = 'EventLatency' AND dur > 100000000;
+
+-- Find the upid of the proccesses where the long latency occur.
+DROP VIEW IF EXISTS long_latency_with_upid;
+CREATE VIEW long_latency_with_upid AS
+SELECT
+ long_eventlatency_slice.ts,
+ long_eventlatency_slice.event_type,
+ process_track.upid
+FROM long_eventlatency_slice
+INNER JOIN process_track
+ON long_eventlatency_slice.track_id = process_track.id;
+
+-- Find the name and pid of the processes.
+-- Long latency events with the same timestamp and from the same process
+-- are considered one single long latency occurrence.
+DROP VIEW IF EXISTS long_latency_with_process_info;
+CREATE VIEW long_latency_with_process_info AS
+SELECT
+ long_latency_with_upid.ts,
+ long_latency_with_upid.event_type,
+ process.name AS process_name,
+ process.pid AS process_id
+FROM long_latency_with_upid
+INNER JOIN process
+ON long_latency_with_upid.upid = process.upid
+GROUP BY ts, process.pid;
+
+-- Create the derived event track for long latency.
+-- All tracks generated from chrome_long_latency_event are
+-- placed under a track group named 'Long Latency', whose summary
+-- track is the first track ('All Processes') in chrome_long_latency_event.
+-- Note that the 'All Processes' track is generated only when there are more
+-- than one source of long latency events.
+DROP VIEW IF EXISTS chrome_long_latency_event;
+CREATE VIEW chrome_long_latency_event AS
+SELECT
+ 'slice' AS track_type,
+ 'All Processes' AS track_name,
+ ts,
+ 0 AS dur,
+ event_type AS slice_name,
+ 'Long Latency' AS group_name
+FROM long_latency_with_process_info
+WHERE (SELECT COUNT(DISTINCT process_id)
+ FROM long_latency_with_process_info) > 1
+GROUP BY ts
+UNION ALL
+SELECT
+ 'slice' AS track_type,
+ process_name || ' ' || process_id AS track_name,
+ ts,
+ 0 AS dur,
+ event_type AS slice_name,
+ 'Long Latency' AS group_name
+FROM long_latency_with_process_info
+GROUP BY ts;
+
+-- Create the long latency metric output.
+DROP VIEW IF EXISTS chrome_long_latency_output;
+CREATE VIEW chrome_long_latency_output AS
+SELECT ChromeLongLatency(
+ 'long_latency', (
+ SELECT RepeatedField(
+ ChromeLongLatency_LongLatency(
+ 'ts', ts,
+ 'event_type', event_type,
+ 'process_name', process_name,
+ 'pid', process_id
+ )
+ )
+ FROM long_latency_with_process_info
+ ORDER BY ts
+ )
+);
\ No newline at end of file
diff --git a/src/trace_processor/trace_processor_context.cc b/src/trace_processor/trace_processor_context.cc
index 412b63a..75800f3 100644
--- a/src/trace_processor/trace_processor_context.cc
+++ b/src/trace_processor/trace_processor_context.cc
@@ -18,6 +18,7 @@
#include "src/trace_processor/forwarding_trace_parser.h"
#include "src/trace_processor/importers/common/args_tracker.h"
+#include "src/trace_processor/importers/common/args_translation_table.h"
#include "src/trace_processor/importers/common/chunked_trace_reader.h"
#include "src/trace_processor/importers/common/clock_tracker.h"
#include "src/trace_processor/importers/common/event_tracker.h"
diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc
index 53bc802..cdd671e 100644
--- a/src/trace_processor/trace_processor_storage_impl.cc
+++ b/src/trace_processor/trace_processor_storage_impl.cc
@@ -21,6 +21,7 @@
#include "src/trace_processor/forwarding_trace_parser.h"
#include "src/trace_processor/importers/chrome_track_event.descriptor.h"
#include "src/trace_processor/importers/common/args_tracker.h"
+#include "src/trace_processor/importers/common/args_translation_table.h"
#include "src/trace_processor/importers/common/clock_tracker.h"
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/flow_tracker.h"
@@ -49,6 +50,7 @@
context_.track_tracker.reset(new TrackTracker(&context_));
context_.async_track_set_tracker.reset(new AsyncTrackSetTracker(&context_));
context_.args_tracker.reset(new ArgsTracker(&context_));
+ context_.args_translation_table.reset(new ArgsTranslationTable());
context_.slice_tracker.reset(new SliceTracker(&context_));
context_.flow_tracker.reset(new FlowTracker(&context_));
context_.event_tracker.reset(new EventTracker(&context_));
diff --git a/src/trace_processor/types/trace_processor_context.h b/src/trace_processor/types/trace_processor_context.h
index 4bc0e2b..221c62b 100644
--- a/src/trace_processor/types/trace_processor_context.h
+++ b/src/trace_processor/types/trace_processor_context.h
@@ -27,6 +27,7 @@
namespace trace_processor {
class ArgsTracker;
+class ArgsTranslationTable;
class AsyncTrackSetTracker;
class AndroidProbesTracker;
class ChunkedTraceReader;
@@ -67,6 +68,7 @@
// trackers, as they may own ArgsTrackers themselves.
std::unique_ptr<GlobalArgsTracker> global_args_tracker;
std::unique_ptr<ArgsTracker> args_tracker;
+ std::unique_ptr<ArgsTranslationTable> args_translation_table;
std::unique_ptr<TrackTracker> track_tracker;
std::unique_ptr<AsyncTrackSetTracker> async_track_set_tracker;
diff --git a/src/trace_processor/util/protozero_to_text.cc b/src/trace_processor/util/protozero_to_text.cc
index cdb60d1..274f504 100644
--- a/src/trace_processor/util/protozero_to_text.cc
+++ b/src/trace_processor/util/protozero_to_text.cc
@@ -16,19 +16,8 @@
namespace {
-std::string BytesToHexEncodedString(const std::string& bytes) {
- // Each byte becomes four chars 'A' -> "\x41" + 1 for trailing null.
- std::string value(4 * bytes.size() + 1, 'Z');
- for (size_t i = 0; i < bytes.size(); ++i) {
- // snprintf prints 5 characters: '\x', then two hex digits, and finally a
- // null byte. As we write left to right, we keep overwriting the null
- // byte, except for the last call to snprintf.
- snprintf(&(value[4 * i]), 5, "\\x%02hhx", bytes[i]);
- }
- // Trim trailing null.
- value.resize(4 * bytes.size());
- return value;
-}
+using protozero::proto_utils::ProtoWireType;
+using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
// This function matches the implementation of TextFormatEscaper.escapeBytes
// from the Java protobuf library.
@@ -87,118 +76,16 @@
return '"' + ret + '"';
}
-// Recursively determine the size of all the string like things passed in the
-// parameter pack |rest|.
-size_t SizeOfStr() {
- return 0;
-}
-template <typename T, typename... Rest>
-size_t SizeOfStr(const T& first, Rest... rest) {
- return base::StringView(first).size() + SizeOfStr(rest...);
-}
-
-// Append |to_add| which is something string like to |out|.
-template <typename T>
-void StrAppendInternal(std::string* out, const T& to_add) {
- out->append(to_add);
-}
-
-template <typename T, typename... strings>
-void StrAppendInternal(std::string* out, const T& first, strings... values) {
- StrAppendInternal(out, first);
- StrAppendInternal(out, values...);
-}
-
// Append |to_add| which is something string like to |out|.
template <typename T>
void StrAppend(std::string* out, const T& to_add) {
- out->reserve(out->size() + base::StringView(to_add).size());
out->append(to_add);
}
template <typename T, typename... strings>
void StrAppend(std::string* out, const T& first, strings... values) {
- out->reserve(out->size() + SizeOfStr(values...));
- StrAppendInternal(out, first);
- StrAppendInternal(out, values...);
-}
-
-void ConvertProtoTypeToFieldAndValueString(const FieldDescriptor& fd,
- const protozero::Field& field,
- const std::string& separator,
- const std::string& indent,
- const DescriptorPool& pool,
- std::string* out) {
- using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
- switch (fd.type()) {
- case FieldDescriptorProto::TYPE_INT32:
- case FieldDescriptorProto::TYPE_SFIXED32:
- case FieldDescriptorProto::TYPE_FIXED32:
- StrAppend(out, separator, indent, fd.name(), ": ",
- std::to_string(field.as_int32()));
- return;
- case FieldDescriptorProto::TYPE_SINT32:
- StrAppend(out, separator, indent, fd.name(), ": ",
- std::to_string(field.as_sint32()));
- return;
- case FieldDescriptorProto::TYPE_INT64:
- case FieldDescriptorProto::TYPE_SFIXED64:
- case FieldDescriptorProto::TYPE_FIXED64:
- StrAppend(out, separator, indent, fd.name(), ": ",
- std::to_string(field.as_int64()));
- return;
- case FieldDescriptorProto::TYPE_SINT64:
- StrAppend(out, separator, indent, fd.name(), ": ",
- std::to_string(field.as_sint64()));
- return;
- case FieldDescriptorProto::TYPE_UINT32:
- StrAppend(out, separator, indent, fd.name(), ": ",
- std::to_string(field.as_uint32()));
- return;
- case FieldDescriptorProto::TYPE_UINT64:
- StrAppend(out, separator, indent, fd.name(), ": ",
- std::to_string(field.as_uint64()));
- return;
- case FieldDescriptorProto::TYPE_BOOL:
- StrAppend(out, separator, indent, fd.name(), ": ",
- field.as_bool() ? "true" : "false");
- return;
- case FieldDescriptorProto::TYPE_DOUBLE:
- StrAppend(out, separator, indent, fd.name(), ": ",
- std::to_string(field.as_double()));
- return;
- case FieldDescriptorProto::TYPE_FLOAT:
- StrAppend(out, separator, indent, fd.name(), ": ",
- std::to_string(field.as_float()));
- return;
- case FieldDescriptorProto::TYPE_STRING: {
- auto s = QuoteAndEscapeTextProtoString(field.as_std_string());
- StrAppend(out, separator, indent, fd.name(), ": ", s);
- return;
- }
- case FieldDescriptorProto::TYPE_BYTES: {
- std::string value = BytesToHexEncodedString(field.as_std_string());
- StrAppend(out, separator, indent, fd.name(), ": \"", value, "\"");
- return;
- }
- case FieldDescriptorProto::TYPE_ENUM: {
- auto opt_enum_descriptor_idx =
- pool.FindDescriptorIdx(fd.resolved_type_name());
- PERFETTO_DCHECK(opt_enum_descriptor_idx);
- auto opt_enum_string =
- pool.descriptors()[*opt_enum_descriptor_idx].FindEnumString(
- field.as_int32());
- PERFETTO_DCHECK(opt_enum_string);
- StrAppend(out, separator, indent, fd.name(), ": ", *opt_enum_string);
- return;
- }
- default: {
- PERFETTO_FATAL(
- "Tried to write value of type field %s (in proto type "
- "%s) which has type enum %d",
- fd.name().c_str(), fd.resolved_type_name().c_str(), fd.type());
- }
- }
+ StrAppend(out, first);
+ StrAppend(out, values...);
}
void IncreaseIndents(std::string* out) {
@@ -224,9 +111,232 @@
}
}
+void PrintVarIntField(const FieldDescriptor* fd,
+ const protozero::Field& field,
+ const DescriptorPool& pool,
+ std::string* out) {
+ uint32_t type = fd ? fd->type() : 0;
+ switch (type) {
+ case FieldDescriptorProto::TYPE_INT32:
+ StrAppend(out, fd->name(), ": ", std::to_string(field.as_int32()));
+ return;
+ case FieldDescriptorProto::TYPE_SINT32:
+ StrAppend(out, fd->name(), ": ", std::to_string(field.as_sint32()));
+ return;
+ case FieldDescriptorProto::TYPE_UINT32:
+ StrAppend(out, fd->name(), ": ", std::to_string(field.as_uint32()));
+ return;
+ case FieldDescriptorProto::TYPE_INT64:
+ StrAppend(out, fd->name(), ": ", std::to_string(field.as_int64()));
+ return;
+ case FieldDescriptorProto::TYPE_SINT64:
+ StrAppend(out, fd->name(), ": ", std::to_string(field.as_sint64()));
+ return;
+ case FieldDescriptorProto::TYPE_UINT64:
+ StrAppend(out, fd->name(), ": ", std::to_string(field.as_uint64()));
+ return;
+ case FieldDescriptorProto::TYPE_BOOL:
+ StrAppend(out, fd->name(), ": ", field.as_bool() ? "true" : "false");
+ return;
+ case FieldDescriptorProto::TYPE_ENUM: {
+ // If the enum value is unknown, treat it like a completely unknown field.
+ auto opt_enum_descriptor_idx =
+ pool.FindDescriptorIdx(fd->resolved_type_name());
+ if (!opt_enum_descriptor_idx)
+ break;
+ auto opt_enum_string =
+ pool.descriptors()[*opt_enum_descriptor_idx].FindEnumString(
+ field.as_int32());
+ if (!opt_enum_string)
+ break;
+ StrAppend(out, fd->name(), ": ", *opt_enum_string);
+ return;
+ }
+ case 0:
+ default:
+ break;
+ }
+ StrAppend(out, std::to_string(field.id()), ": ",
+ std::to_string(field.as_uint64()));
+}
+
+void PrintFixed32Field(const FieldDescriptor* fd,
+ const protozero::Field& field,
+ std::string* out) {
+ uint32_t type = fd ? fd->type() : 0;
+ switch (type) {
+ case FieldDescriptorProto::TYPE_SFIXED32:
+ StrAppend(out, fd->name(), ": ", std::to_string(field.as_int32()));
+ break;
+ case FieldDescriptorProto::TYPE_FIXED32:
+ StrAppend(out, fd->name(), ": ", std::to_string(field.as_uint32()));
+ break;
+ case FieldDescriptorProto::TYPE_FLOAT:
+ StrAppend(out, fd->name(), ": ", std::to_string(field.as_float()));
+ break;
+ case 0:
+ default:
+ base::StackString<12> padded_hex("0x%08" PRIx32, field.as_uint32());
+ StrAppend(out, std::to_string(field.id()), ": ", padded_hex.c_str());
+ break;
+ }
+}
+
+void PrintFixed64Field(const FieldDescriptor* fd,
+ const protozero::Field& field,
+ std::string* out) {
+ uint32_t type = fd ? fd->type() : 0;
+ switch (type) {
+ case FieldDescriptorProto::TYPE_SFIXED64:
+ StrAppend(out, fd->name(), ": ", std::to_string(field.as_int64()));
+ break;
+ case FieldDescriptorProto::TYPE_FIXED64:
+ StrAppend(out, fd->name(), ": ", std::to_string(field.as_uint64()));
+ break;
+ case FieldDescriptorProto::TYPE_DOUBLE:
+ StrAppend(out, fd->name(), ": ", std::to_string(field.as_double()));
+ break;
+ case 0:
+ default:
+ base::StackString<20> padded_hex("0x%016" PRIx64, field.as_uint64());
+ StrAppend(out, std::to_string(field.id()), ": ", padded_hex.c_str());
+ break;
+ }
+}
+
+void ProtozeroToTextInternal(const std::string& type,
+ protozero::ConstBytes protobytes,
+ NewLinesMode new_lines_mode,
+ const DescriptorPool& pool,
+ std::string* indents,
+ std::string* output);
+
+template <protozero::proto_utils::ProtoWireType wire_type, typename T>
+void PrintPackedField(const FieldDescriptor& fd,
+ const protozero::Field& field,
+ NewLinesMode new_lines_mode,
+ const std::string& indents,
+ std::string* out) {
+ const bool include_new_lines = new_lines_mode == kIncludeNewLines;
+ bool err = false;
+ bool first_output = true;
+ for (protozero::PackedRepeatedFieldIterator<wire_type, T> it(
+ field.data(), field.size(), &err);
+ it; it++) {
+ T value = *it;
+ if (!first_output) {
+ if (include_new_lines) {
+ StrAppend(out, "\n", indents);
+ } else {
+ StrAppend(out, " ");
+ }
+ }
+ StrAppend(out, fd.name(), ": ", std::to_string(value));
+ first_output = false;
+ }
+
+ if (err) {
+ if (!first_output) {
+ if (include_new_lines) {
+ StrAppend(out, "\n", indents);
+ } else {
+ StrAppend(out, " ");
+ }
+ }
+ StrAppend(out, "# Packed decoding failure for field ", fd.name(), "\n");
+ }
+}
+
+void PrintLengthDelimitedField(const FieldDescriptor* fd,
+ const protozero::Field& field,
+ NewLinesMode new_lines_mode,
+ std::string* indents,
+ const DescriptorPool& pool,
+ std::string* out) {
+ const bool include_new_lines = new_lines_mode == kIncludeNewLines;
+ uint32_t type = fd ? fd->type() : 0;
+ switch (type) {
+ case FieldDescriptorProto::TYPE_BYTES:
+ case FieldDescriptorProto::TYPE_STRING: {
+ std::string value = QuoteAndEscapeTextProtoString(field.as_std_string());
+ StrAppend(out, fd->name(), ": ", value);
+ return;
+ }
+ case FieldDescriptorProto::TYPE_MESSAGE:
+ StrAppend(out, FormattedFieldDescriptorName(*fd), ": {");
+ if (include_new_lines) {
+ IncreaseIndents(indents);
+ }
+ ProtozeroToTextInternal(fd->resolved_type_name(), field.as_bytes(),
+ new_lines_mode, pool, indents, out);
+ if (include_new_lines) {
+ DecreaseIndents(indents);
+ StrAppend(out, "\n", *indents, "}");
+ } else {
+ StrAppend(out, " }");
+ }
+ return;
+ case FieldDescriptorProto::TYPE_DOUBLE:
+ PrintPackedField<protozero::proto_utils::ProtoWireType::kFixed64, double>(
+ *fd, field, new_lines_mode, *indents, out);
+ return;
+ case FieldDescriptorProto::TYPE_FLOAT:
+ PrintPackedField<protozero::proto_utils::ProtoWireType::kFixed32, float>(
+ *fd, field, new_lines_mode, *indents, out);
+ return;
+ case FieldDescriptorProto::TYPE_INT64:
+ PrintPackedField<protozero::proto_utils::ProtoWireType::kVarInt, int64_t>(
+ *fd, field, new_lines_mode, *indents, out);
+ return;
+ case FieldDescriptorProto::TYPE_UINT64:
+ PrintPackedField<protozero::proto_utils::ProtoWireType::kVarInt,
+ uint64_t>(*fd, field, new_lines_mode, *indents, out);
+ return;
+ case FieldDescriptorProto::TYPE_INT32:
+ PrintPackedField<protozero::proto_utils::ProtoWireType::kVarInt, int32_t>(
+ *fd, field, new_lines_mode, *indents, out);
+ return;
+ case FieldDescriptorProto::TYPE_FIXED64:
+ PrintPackedField<protozero::proto_utils::ProtoWireType::kFixed64,
+ uint64_t>(*fd, field, new_lines_mode, *indents, out);
+ return;
+ case FieldDescriptorProto::TYPE_FIXED32:
+ PrintPackedField<protozero::proto_utils::ProtoWireType::kFixed32,
+ uint32_t>(*fd, field, new_lines_mode, *indents, out);
+ return;
+ case FieldDescriptorProto::TYPE_UINT32:
+ PrintPackedField<protozero::proto_utils::ProtoWireType::kVarInt,
+ uint32_t>(*fd, field, new_lines_mode, *indents, out);
+ return;
+ case FieldDescriptorProto::TYPE_SFIXED32:
+ PrintPackedField<protozero::proto_utils::ProtoWireType::kFixed32,
+ int32_t>(*fd, field, new_lines_mode, *indents, out);
+ return;
+ case FieldDescriptorProto::TYPE_SFIXED64:
+ PrintPackedField<protozero::proto_utils::ProtoWireType::kFixed64,
+ int64_t>(*fd, field, new_lines_mode, *indents, out);
+ return;
+ // Our protoc plugin cannot generate code for packed repeated fields with
+ // these types. Output a comment and then fall back to the raw field_id:
+ // string representation.
+ case FieldDescriptorProto::TYPE_BOOL:
+ case FieldDescriptorProto::TYPE_ENUM:
+ case FieldDescriptorProto::TYPE_SINT32:
+ case FieldDescriptorProto::TYPE_SINT64:
+ StrAppend(out, "# Packed type ", std::to_string(type),
+ " not supported. Printing raw string.", "\n", *indents);
+ break;
+ case 0:
+ default:
+ break;
+ }
+ std::string value = QuoteAndEscapeTextProtoString(field.as_std_string());
+ StrAppend(out, std::to_string(field.id()), ": ", value);
+}
+
// Recursive case function, Will parse |protobytes| assuming it is a proto of
// |type| and will use |pool| to look up the |type|. All output will be placed
-// in |output| and between fields |separator| will be placed. When called for
+// in |output|, using |new_lines_mode| to separate fields. When called for
// |indents| will be increased by 2 spaces to improve readability.
void ProtozeroToTextInternal(const std::string& type,
protozero::ConstBytes protobytes,
@@ -237,44 +347,35 @@
auto opt_proto_descriptor_idx = pool.FindDescriptorIdx(type);
PERFETTO_DCHECK(opt_proto_descriptor_idx);
auto& proto_descriptor = pool.descriptors()[*opt_proto_descriptor_idx];
- bool include_new_lines = new_lines_mode == kIncludeNewLines;
+ const bool include_new_lines = new_lines_mode == kIncludeNewLines;
protozero::ProtoDecoder decoder(protobytes.data, protobytes.size);
for (auto field = decoder.ReadField(); field.valid();
field = decoder.ReadField()) {
- auto opt_field_descriptor = proto_descriptor.FindFieldByTag(field.id());
- if (!opt_field_descriptor) {
- StrAppend(
- output, output->empty() ? "" : "\n", *indents,
- "# Ignoring unknown field with id: ", std::to_string(field.id()));
- continue;
- }
- const auto& field_descriptor = *opt_field_descriptor;
-
- if (field_descriptor.type() ==
- protos::pbzero::FieldDescriptorProto::TYPE_MESSAGE) {
+ if (!output->empty()) {
if (include_new_lines) {
- StrAppend(output, output->empty() ? "" : "\n", *indents,
- FormattedFieldDescriptorName(field_descriptor), ": {");
- IncreaseIndents(indents);
+ StrAppend(output, "\n", *indents);
} else {
- StrAppend(output, output->empty() ? "" : " ",
- FormattedFieldDescriptorName(field_descriptor), ": {");
- }
- ProtozeroToTextInternal(field_descriptor.resolved_type_name(),
- field.as_bytes(), new_lines_mode, pool, indents,
- output);
- if (include_new_lines) {
- DecreaseIndents(indents);
- StrAppend(output, "\n", *indents, "}");
- } else {
- StrAppend(output, " }");
+ StrAppend(output, " ", *indents);
}
} else {
- ConvertProtoTypeToFieldAndValueString(
- field_descriptor, field,
- output->empty() ? "" : include_new_lines ? "\n" : " ", *indents, pool,
- output);
+ StrAppend(output, *indents);
+ }
+ auto* opt_field_descriptor = proto_descriptor.FindFieldByTag(field.id());
+ switch (field.type()) {
+ case ProtoWireType::kVarInt:
+ PrintVarIntField(opt_field_descriptor, field, pool, output);
+ break;
+ case ProtoWireType::kLengthDelimited:
+ PrintLengthDelimitedField(opt_field_descriptor, field, new_lines_mode,
+ indents, pool, output);
+ break;
+ case ProtoWireType::kFixed32:
+ PrintFixed32Field(opt_field_descriptor, field, output);
+ break;
+ case ProtoWireType::kFixed64:
+ PrintFixed64Field(opt_field_descriptor, field, output);
+ break;
}
}
PERFETTO_DCHECK(decoder.bytes_left() == 0);
@@ -341,10 +442,6 @@
new_lines_mode);
}
-std::string BytesToHexEncodedStringForTesting(const std::string& s) {
- return BytesToHexEncodedString(s);
-}
-
} // namespace protozero_to_text
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/util/protozero_to_text.h b/src/trace_processor/util/protozero_to_text.h
index c7b793b..9a0acf1 100644
--- a/src/trace_processor/util/protozero_to_text.h
+++ b/src/trace_processor/util/protozero_to_text.h
@@ -71,8 +71,6 @@
return ProtozeroEnumToText(type, static_cast<int32_t>(enum_value));
}
-std::string BytesToHexEncodedStringForTesting(const std::string&);
-
} // namespace protozero_to_text
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/util/protozero_to_text_unittests.cc b/src/trace_processor/util/protozero_to_text_unittests.cc
index bd92298..6b664cd 100644
--- a/src/trace_processor/util/protozero_to_text_unittests.cc
+++ b/src/trace_processor/util/protozero_to_text_unittests.cc
@@ -180,10 +180,6 @@
TrackEvent::TYPE_SLICE_END));
}
-TEST(ProtozeroToTextTest, BytesToHexEncodedString) {
- EXPECT_EQ(BytesToHexEncodedStringForTesting("abc"), R"(\x61\x62\x63)");
-}
-
// Sets up a descriptor pool with all the messages from
// "src/protozero/test/example_proto/test_messages.proto"
class ProtozeroToTextTestMessageTest : public testing::Test {
@@ -278,8 +274,7 @@
"big_enum: END");
}
-// TODO(b/224800278): Fix ProtozeroToText() crash and reenable.
-TEST_F(ProtozeroToTextTestMessageTest, DISABLED_FieldVarIntEnumUnknown) {
+TEST_F(ProtozeroToTextTestMessageTest, FieldVarIntEnumUnknown) {
protozero::HeapBuffered<EveryField> msg;
msg->AppendVarInt(EveryField::kSmallEnumFieldNumber, 42);
ASSERT_EQ(EveryField::kSmallEnumFieldNumber, 51);
@@ -293,15 +288,12 @@
protozero::HeapBuffered<EveryField> msg;
msg->AppendVarInt(/*field_id=*/9999, /*value=*/42);
- // TODO(b/224800278): "protoc --decode" also prints the varint value, which is
- // more useful.
EXPECT_EQ(ProtozeroToText(pool_, ".protozero.test.protos.EveryField",
msg.SerializeAsArray(), kIncludeNewLines),
- "# Ignoring unknown field with id: 9999");
+ "9999: 42");
}
-// TODO(b/224800278): Fix ProtozeroToText() crash and reenable.
-TEST_F(ProtozeroToTextTestMessageTest, DISABLED_FieldVarIntMismatch) {
+TEST_F(ProtozeroToTextTestMessageTest, FieldVarIntMismatch) {
protozero::HeapBuffered<EveryField> msg;
ASSERT_EQ(EveryField::kFieldStringFieldNumber, 500);
msg->AppendVarInt(EveryField::kFieldStringFieldNumber, 42);
@@ -336,11 +328,9 @@
protozero::HeapBuffered<EveryField> msg;
msg->set_field_fixed32(3000000000);
- // TODO(b/224800278): This is a bug. fixed32 is supposed to be unsigned, but
- // the code prints it as signed.
EXPECT_EQ(ProtozeroToText(pool_, ".protozero.test.protos.EveryField",
msg.SerializeAsArray(), kIncludeNewLines),
- "field_fixed32: -1294967296");
+ "field_fixed32: 3000000000");
}
TEST_F(ProtozeroToTextTestMessageTest, FieldFixed32Float) {
@@ -356,15 +346,12 @@
protozero::HeapBuffered<EveryField> msg;
msg->AppendFixed<uint32_t>(/*field_id=*/9999, /*value=*/0x1);
- // TODO(b/224800278): "protoc --decode" also prints the 32-bit value, which is
- // more useful.
EXPECT_EQ(ProtozeroToText(pool_, ".protozero.test.protos.EveryField",
msg.SerializeAsArray(), kIncludeNewLines),
- "# Ignoring unknown field with id: 9999");
+ "9999: 0x00000001");
}
-// TODO(b/224800278): Fix ProtozeroToText() crash and reenable.
-TEST_F(ProtozeroToTextTestMessageTest, DISABLED_FieldFixed32Mismatch) {
+TEST_F(ProtozeroToTextTestMessageTest, FieldFixed32Mismatch) {
protozero::HeapBuffered<EveryField> msg;
ASSERT_EQ(EveryField::kFieldStringFieldNumber, 500);
msg->AppendFixed<uint32_t>(EveryField::kFieldStringFieldNumber, 0x1);
@@ -405,15 +392,12 @@
protozero::HeapBuffered<EveryField> msg;
msg->AppendFixed<uint64_t>(/*field_id=*/9999, /*value=*/0x1);
- // TODO(b/224800278): "protoc --decode" also prints the 64-bit value, which is
- // more useful.
EXPECT_EQ(ProtozeroToText(pool_, ".protozero.test.protos.EveryField",
msg.SerializeAsArray(), kIncludeNewLines),
- "# Ignoring unknown field with id: 9999");
+ "9999: 0x0000000000000001");
}
-// TODO(b/224800278): Fix ProtozeroToText() crash and reenable.
-TEST_F(ProtozeroToTextTestMessageTest, DISABLED_FieldFixed64Mismatch) {
+TEST_F(ProtozeroToTextTestMessageTest, FieldFixed64Mismatch) {
protozero::HeapBuffered<EveryField> msg;
ASSERT_EQ(EveryField::kFieldStringFieldNumber, 500);
msg->AppendFixed<uint64_t>(EveryField::kFieldStringFieldNumber, 0x1);
@@ -436,35 +420,257 @@
protozero::HeapBuffered<EveryField> msg;
msg->set_field_bytes("Hello");
- // TODO(b/224800278): "protoc --decode" always tries to print the value as
- // ASCII.
EXPECT_EQ(ProtozeroToText(pool_, ".protozero.test.protos.EveryField",
msg.SerializeAsArray(), kIncludeNewLines),
- R"(field_bytes: "\x48\x65\x6c\x6c\x6f")");
+ R"(field_bytes: "Hello")");
}
TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedUnknown) {
protozero::HeapBuffered<EveryField> msg;
msg->AppendString(9999, "Hello");
- // TODO(b/224800278): "protoc --decode" also prints the string value, which is
- // more useful.
EXPECT_EQ(ProtozeroToText(pool_, ".protozero.test.protos.EveryField",
msg.SerializeAsArray(), kIncludeNewLines),
- "# Ignoring unknown field with id: 9999");
+ R"(9999: "Hello")");
}
-// TODO(b/224800278): Fix ProtozeroToText() crash and reenable.
-TEST_F(ProtozeroToTextTestMessageTest, DISABLED_FieldLengthLimitedMismatch) {
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedMismatch) {
protozero::HeapBuffered<EveryField> msg;
ASSERT_EQ(EveryField::kFieldBoolFieldNumber, 13);
msg->AppendString(EveryField::kFieldBoolFieldNumber, "Hello");
EXPECT_EQ(ProtozeroToText(pool_, ".protozero.test.protos.EveryField",
msg.SerializeAsArray(), kIncludeNewLines),
+ "# Packed type 8 not supported. Printing raw string.\n"
R"(13: "Hello")");
}
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedForNonPacked) {
+ // Even though repeated_int32 doesn't have [packed = true], it still accepts a
+ // packed representation.
+ protozero::HeapBuffered<EveryField> msg;
+ protozero::PackedVarInt buf;
+ buf.Append<int32_t>(-42);
+ buf.Append<int32_t>(2147483647);
+ msg->AppendBytes(EveryField::kRepeatedInt32FieldNumber, buf.data(),
+ buf.size());
+
+ EXPECT_EQ(ProtozeroToText(pool_, ".protozero.test.protos.EveryField",
+ msg.SerializeAsArray(), kIncludeNewLines),
+ "repeated_int32: -42\nrepeated_int32: 2147483647");
+}
+
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedVarIntInt32) {
+ protozero::HeapBuffered<PackedRepeatedFields> msg;
+ protozero::PackedVarInt buf;
+ buf.Append<int32_t>(-42);
+ buf.Append<int32_t>(2147483647);
+ msg->set_field_int32(buf);
+
+ EXPECT_EQ(
+ ProtozeroToText(pool_, ".protozero.test.protos.PackedRepeatedFields",
+ msg.SerializeAsArray(), kIncludeNewLines),
+ "field_int32: -42\nfield_int32: 2147483647");
+}
+
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedVarIntInt64) {
+ protozero::HeapBuffered<PackedRepeatedFields> msg;
+ protozero::PackedVarInt buf;
+ buf.Append<int64_t>(-42);
+ buf.Append<int64_t>(3000000000);
+ msg->set_field_int64(buf);
+
+ EXPECT_EQ(
+ ProtozeroToText(pool_, ".protozero.test.protos.PackedRepeatedFields",
+ msg.SerializeAsArray(), kIncludeNewLines),
+ "field_int64: -42\nfield_int64: 3000000000");
+}
+
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedVarIntUint32) {
+ protozero::HeapBuffered<PackedRepeatedFields> msg;
+ protozero::PackedVarInt buf;
+ buf.Append<uint32_t>(42);
+ buf.Append<uint32_t>(3000000000);
+ msg->set_field_uint32(buf);
+
+ EXPECT_EQ(
+ ProtozeroToText(pool_, ".protozero.test.protos.PackedRepeatedFields",
+ msg.SerializeAsArray(), kIncludeNewLines),
+ "field_uint32: 42\nfield_uint32: 3000000000");
+}
+
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedVarIntUint64) {
+ protozero::HeapBuffered<PackedRepeatedFields> msg;
+ protozero::PackedVarInt buf;
+ buf.Append<uint64_t>(42);
+ buf.Append<uint64_t>(3000000000000);
+ msg->set_field_uint64(buf);
+
+ EXPECT_EQ(
+ ProtozeroToText(pool_, ".protozero.test.protos.PackedRepeatedFields",
+ msg.SerializeAsArray(), kIncludeNewLines),
+ "field_uint64: 42\nfield_uint64: 3000000000000");
+}
+
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedFixed32Uint32) {
+ protozero::HeapBuffered<PackedRepeatedFields> msg;
+ protozero::PackedFixedSizeInt<uint32_t> buf;
+ buf.Append(42);
+ buf.Append(3000000000);
+ msg->set_field_fixed32(buf);
+
+ EXPECT_EQ(
+ ProtozeroToText(pool_, ".protozero.test.protos.PackedRepeatedFields",
+ msg.SerializeAsArray(), kIncludeNewLines),
+ "field_fixed32: 42\nfield_fixed32: 3000000000");
+}
+
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedFixed32Int32) {
+ protozero::HeapBuffered<PackedRepeatedFields> msg;
+ protozero::PackedFixedSizeInt<int32_t> buf;
+ buf.Append(-42);
+ buf.Append(42);
+ msg->set_field_sfixed32(buf);
+
+ EXPECT_EQ(
+ ProtozeroToText(pool_, ".protozero.test.protos.PackedRepeatedFields",
+ msg.SerializeAsArray(), kIncludeNewLines),
+ "field_sfixed32: -42\nfield_sfixed32: 42");
+}
+
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedFixed32Float) {
+ protozero::HeapBuffered<PackedRepeatedFields> msg;
+ protozero::PackedFixedSizeInt<float> buf;
+ buf.Append(-42);
+ buf.Append(42.125);
+ msg->set_field_float(buf);
+
+ std::string output =
+ ProtozeroToText(pool_, ".protozero.test.protos.PackedRepeatedFields",
+ msg.SerializeAsArray(), kIncludeNewLines);
+
+ EXPECT_THAT(base::SplitString(output, "\n"),
+ ElementsAre(StartsWith("field_float: -42"),
+ StartsWith("field_float: 42.125")));
+}
+
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedFixed64Uint64) {
+ protozero::HeapBuffered<PackedRepeatedFields> msg;
+ protozero::PackedFixedSizeInt<uint64_t> buf;
+ buf.Append(42);
+ buf.Append(3000000000000);
+ msg->set_field_fixed64(buf);
+
+ EXPECT_EQ(
+ ProtozeroToText(pool_, ".protozero.test.protos.PackedRepeatedFields",
+ msg.SerializeAsArray(), kIncludeNewLines),
+ "field_fixed64: 42\nfield_fixed64: 3000000000000");
+}
+
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedFixed64Int64) {
+ protozero::HeapBuffered<PackedRepeatedFields> msg;
+ protozero::PackedFixedSizeInt<int64_t> buf;
+ buf.Append(-42);
+ buf.Append(3000000000000);
+ msg->set_field_sfixed64(buf);
+
+ EXPECT_EQ(
+ ProtozeroToText(pool_, ".protozero.test.protos.PackedRepeatedFields",
+ msg.SerializeAsArray(), kIncludeNewLines),
+ "field_sfixed64: -42\nfield_sfixed64: 3000000000000");
+}
+
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedFixed64Double) {
+ protozero::HeapBuffered<PackedRepeatedFields> msg;
+ protozero::PackedFixedSizeInt<double> buf;
+ buf.Append(-42);
+ buf.Append(42.125);
+ msg->set_field_double(buf);
+
+ EXPECT_THAT(
+ base::SplitString(
+ ProtozeroToText(pool_, ".protozero.test.protos.PackedRepeatedFields",
+ msg.SerializeAsArray(), kIncludeNewLines),
+ "\n"),
+ ElementsAre(StartsWith("field_double: -42"),
+ StartsWith("field_double: 42.125")));
+}
+
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedFixedErrShort) {
+ protozero::HeapBuffered<PackedRepeatedFields> msg;
+ std::string buf;
+ buf = "\x01";
+ // buf does not contain enough data for a fixed 64
+ msg->AppendBytes(PackedRepeatedFields::kFieldFixed64FieldNumber, buf.data(),
+ buf.size());
+
+ // "protoc --decode", instead, returns an error on stderr and doesn't output
+ // anything at all.
+ EXPECT_EQ(
+ ProtozeroToText(pool_, ".protozero.test.protos.PackedRepeatedFields",
+ msg.SerializeAsArray(), kIncludeNewLines),
+ "# Packed decoding failure for field field_fixed64\n");
+}
+
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedFixedGarbage) {
+ protozero::HeapBuffered<PackedRepeatedFields> msg;
+ protozero::PackedFixedSizeInt<uint64_t> buf;
+ buf.Append(42);
+ buf.Append(3000000000000);
+ std::string buf_and_garbage(reinterpret_cast<const char*>(buf.data()),
+ buf.size());
+ buf_and_garbage += "\x01";
+ // buf contains extra garbage
+ msg->AppendBytes(PackedRepeatedFields::kFieldFixed64FieldNumber,
+ buf_and_garbage.data(), buf_and_garbage.size());
+
+ // "protoc --decode", instead, returns an error on stderr and doesn't output
+ // anything at all.
+ EXPECT_EQ(
+ ProtozeroToText(pool_, ".protozero.test.protos.PackedRepeatedFields",
+ msg.SerializeAsArray(), kIncludeNewLines),
+ "# Packed decoding failure for field field_fixed64\n");
+}
+
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedVarIntShort) {
+ protozero::HeapBuffered<PackedRepeatedFields> msg;
+ std::string buf;
+ buf = "\xFF";
+ // for the varint to be valid, buf should contain another byte.
+ msg->AppendBytes(PackedRepeatedFields::kFieldInt32FieldNumber, buf.data(),
+ buf.size());
+
+ // "protoc --decode", instead, returns an error on stderr and doesn't output
+ // anything at all.
+ EXPECT_EQ(
+ ProtozeroToText(pool_, ".protozero.test.protos.PackedRepeatedFields",
+ msg.SerializeAsArray(), kIncludeNewLines),
+ "# Packed decoding failure for field field_int32\n");
+}
+
+TEST_F(ProtozeroToTextTestMessageTest, FieldLengthLimitedPackedVarIntGarbage) {
+ protozero::HeapBuffered<PackedRepeatedFields> msg;
+ protozero::PackedVarInt buf;
+ buf.Append(42);
+ buf.Append(105);
+ std::string buf_and_garbage(reinterpret_cast<const char*>(buf.data()),
+ buf.size());
+ buf_and_garbage += "\xFF";
+ // buf contains extra garbage
+ msg->AppendBytes(PackedRepeatedFields::kFieldInt32FieldNumber,
+ buf_and_garbage.data(), buf_and_garbage.size());
+
+ // "protoc --decode", instead:
+ // * doesn't output anything.
+ // * returns an error on stderr.
+ EXPECT_EQ(
+ ProtozeroToText(pool_, ".protozero.test.protos.PackedRepeatedFields",
+ msg.SerializeAsArray(), kIncludeNewLines),
+ "field_int32: 42\n"
+ "field_int32: 105\n"
+ "# Packed decoding failure for field field_int32\n");
+}
+
} // namespace
} // namespace protozero_to_text
} // namespace trace_processor
diff --git a/src/traced/probes/android_log/android_log_data_source.cc b/src/traced/probes/android_log/android_log_data_source.cc
index 4d8d309..2d4d264 100644
--- a/src/traced/probes/android_log/android_log_data_source.cc
+++ b/src/traced/probes/android_log/android_log_data_source.cc
@@ -368,8 +368,6 @@
if (!ReadAndAdvance(&buf, end, &eid))
return false;
- // TODO test events with 0 arguments. DNS.
-
const EventFormat* fmt = GetEventFormat(eid);
if (!fmt) {
// We got an event which doesn't have a corresponding entry in
diff --git a/src/traced/probes/ps/process_stats_data_source.cc b/src/traced/probes/ps/process_stats_data_source.cc
index d61e41c..665a350 100644
--- a/src/traced/probes/ps/process_stats_data_source.cc
+++ b/src/traced/probes/ps/process_stats_data_source.cc
@@ -23,7 +23,6 @@
#include "perfetto/base/task_runner.h"
#include "perfetto/base/time.h"
-#include "perfetto/ext/base/crash_keys.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/hash.h"
#include "perfetto/ext/base/metatrace.h"
@@ -55,10 +54,6 @@
// was provided in the config. The cache is trimmed if it exceeds this size.
const size_t kThreadTimeInStateCacheSize = 10000;
-// TODO(b/189749310): For debugging of b/189749310. Remove by Jan 2022.
-base::CrashKey g_crash_key_proc_file("proc_file");
-base::CrashKey g_crash_key_proc_count("proc_count");
-
int32_t ReadNextNumericDir(DIR* dirp) {
while (struct dirent* dir_ent = readdir(dirp)) {
if (dir_ent->d_type != DT_DIR)
@@ -344,8 +339,6 @@
std::string ProcessStatsDataSource::ReadProcPidFile(int32_t pid,
const std::string& file) {
base::StackString<128> path("/proc/%" PRId32 "/%s", pid, file.c_str());
- auto scoped_key = g_crash_key_proc_file.SetScoped(path.string_view());
- g_crash_key_proc_count.Set(g_crash_key_proc_count.int_value() + 1);
std::string contents;
contents.reserve(4096);
if (!base::ReadFile(path.c_str(), &contents))
@@ -433,7 +426,6 @@
base::WeakPtr<ProcessStatsDataSource> weak_this) {
if (!weak_this)
return;
- g_crash_key_proc_count.Clear();
ProcessStatsDataSource& thiz = *weak_this;
uint32_t period_ms = thiz.poll_period_ms_;
uint32_t delay_ms =
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index 18f6e69..f9da779 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -53,7 +53,6 @@
#include "perfetto/base/status.h"
#include "perfetto/base/task_runner.h"
#include "perfetto/ext/base/android_utils.h"
-#include "perfetto/ext/base/crash_keys.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/metatrace.h"
#include "perfetto/ext/base/string_utils.h"
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index 4a16b42..97a94f4 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -24,6 +24,7 @@
#include <mutex>
#include <regex>
#include <thread>
+#include <unordered_set>
#include <vector>
// We also want to test legacy trace events.
@@ -2805,6 +2806,56 @@
"]I:test.Event"));
}
+TEST_P(PerfettoApiTest, TrackEventTrackFromThreadScopedPointer) {
+ // Create a new trace session.
+ auto* tracing_session = NewTraceWithCategories({"test"});
+ tracing_session->get()->StartBlocking();
+
+ int num = 2;
+ TRACE_EVENT_INSTANT("test", "Event0.1");
+ TRACE_EVENT_INSTANT("test", "Event0.2");
+ TRACE_EVENT_INSTANT("test", "Event1.1", perfetto::Track::ThreadScoped(&num));
+ TRACE_EVENT_INSTANT("test", "Event1.2", perfetto::Track::ThreadScoped(&num));
+ std::thread t1([&]() {
+ TRACE_EVENT_INSTANT("test", "Event2.1",
+ perfetto::Track::ThreadScoped(&num));
+ TRACE_EVENT_INSTANT("test", "Event2.2",
+ perfetto::Track::ThreadScoped(&num));
+ });
+ t1.join();
+ std::thread t2([&]() {
+ TRACE_EVENT_INSTANT("test", "Event3.1",
+ perfetto::Track::ThreadScoped(&num));
+ TRACE_EVENT_INSTANT("test", "Event3.2",
+ perfetto::Track::ThreadScoped(&num));
+ });
+ t2.join();
+ perfetto::TrackEvent::Flush();
+ tracing_session->get()->StopBlocking();
+ std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ perfetto::protos::gen::Trace parsed_trace;
+ ASSERT_TRUE(parsed_trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+
+ std::unordered_map<std::string, uint64_t> track_uuid_map;
+ for (auto packet : parsed_trace.packet()) {
+ if (packet.has_interned_data()) {
+ for (auto& ename : packet.interned_data().event_names()) {
+ track_uuid_map.emplace(ename.name(), packet.track_event().track_uuid());
+ }
+ }
+ }
+ EXPECT_EQ(track_uuid_map.at("Event0.1"), track_uuid_map.at("Event0.2"));
+ EXPECT_EQ(track_uuid_map.at("Event1.1"), track_uuid_map.at("Event1.2"));
+ EXPECT_EQ(track_uuid_map.at("Event2.1"), track_uuid_map.at("Event2.2"));
+ EXPECT_EQ(track_uuid_map.at("Event3.1"), track_uuid_map.at("Event3.2"));
+
+ EXPECT_EQ(4u,
+ (std::unordered_set<uint64_t>{
+ track_uuid_map.at("Event0.1"), track_uuid_map.at("Event1.1"),
+ track_uuid_map.at("Event2.1"), track_uuid_map.at("Event3.1")})
+ .size());
+}
+
TEST_P(PerfettoApiTest, TrackEventDebugAnnotations) {
// Create a new trace session.
auto* tracing_session = NewTraceWithCategories({"test"});
diff --git a/test/trace_processor/chrome/chrome_long_latency_metric.out b/test/trace_processor/chrome/chrome_long_latency_metric.out
new file mode 100644
index 0000000..9779ed9
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_long_latency_metric.out
@@ -0,0 +1,5 @@
+
+"ts","event_type","process_name","process_id"
+200111000,"GestureScrollUpdate","Renderer",1001
+200111000,"GestureScrollUpdate","Renderer",1002
+280111001,"GestureScrollUpdate","Renderer",1001
diff --git a/test/trace_processor/chrome/chrome_long_latency_metric.sql b/test/trace_processor/chrome/chrome_long_latency_metric.sql
new file mode 100644
index 0000000..13db1ff
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_long_latency_metric.sql
@@ -0,0 +1,18 @@
+--
+-- Copyright 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
+--
+-- https://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.
+
+SELECT RUN_METRIC('experimental/chrome_long_latency.sql') AS suppress_query_output;
+
+SELECT * FROM long_latency_with_process_info;
\ No newline at end of file
diff --git a/test/trace_processor/chrome/index b/test/trace_processor/chrome/index
index 019067a..7e6856c 100644
--- a/test/trace_processor/chrome/index
+++ b/test/trace_processor/chrome/index
@@ -17,6 +17,7 @@
../track_event/track_event_counters.textproto chrome_thread_slice_repeated.sql chrome_thread_slice_repeated.out
../../data/chrome_rendering_desktop.pftrace frame_times frame_times_metric.out
../../data/chrome_rendering_desktop.pftrace chrome_dropped_frames chrome_dropped_frames_metric.out
+../chrome/long_event_latency.textproto chrome_long_latency_metric.sql chrome_long_latency_metric.out
scroll_jank_mojo_simple_watcher.py scroll_jank_mojo_simple_watcher.sql scroll_jank_mojo_simple_watcher.out
scroll_jank_gpu_check.py scroll_jank_gpu_check.sql scroll_jank_gpu_check.out
diff --git a/test/trace_processor/chrome/long_event_latency.textproto b/test/trace_processor/chrome/long_event_latency.textproto
new file mode 100644
index 0000000..8b6fa8b
--- /dev/null
+++ b/test/trace_processor/chrome/long_event_latency.textproto
@@ -0,0 +1,212 @@
+# Long latency events from two renderer processes
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ track_descriptor {
+ uuid: 10
+ process {
+ pid: 1001
+ process_name: "Renderer"
+ }
+ }
+}
+
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ track_descriptor {
+ uuid: 20
+ process {
+ pid: 1002
+ process_name: "Renderer"
+ }
+ }
+}
+
+# EventLatency 1: 200ms duration
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ track_descriptor {
+ uuid: 101
+ parent_uuid: 10
+ name: "EventLatency"
+ }
+}
+
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 111000
+ track_event {
+ track_uuid: 101
+ categories: "cat"
+ debug_annotations: {
+ name: "event"
+ string_value: "GestureScrollUpdate"
+ }
+ name: "EventLatency"
+ type: 1
+ }
+}
+
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 200111000
+ track_event {
+ track_uuid: 101
+ categories: "cat"
+ name: "EventLatency"
+ type: 2
+ }
+}
+
+# EventLatency 2: 110ms ending at the same timestamp as EventLatency 1.
+# EventLatency 1 and 2 are reported as one occurrence of long latency.
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ track_descriptor {
+ uuid: 102
+ parent_uuid: 10
+ name: "EventLatency"
+ }
+}
+
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 90111000
+ track_event {
+ track_uuid: 102
+ categories: "cat"
+ debug_annotations: {
+ name: "event"
+ string_value: "GestureScrollUpdate"
+ }
+ name: "EventLatency"
+ type: 1
+ }
+}
+
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 200111000
+ track_event {
+ track_uuid: 102
+ categories: "cat"
+ name: "EventLatency"
+ type: 2
+ }
+}
+
+# EventLatency 3: a long latency slightly above the 100ms threshold
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ track_descriptor {
+ uuid: 103
+ parent_uuid: 10
+ name: "EventLatency"
+ }
+}
+
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 180111000
+ track_event {
+ track_uuid: 103
+ categories: "cat"
+ debug_annotations: {
+ name: "event"
+ string_value: "GestureScrollUpdate"
+ }
+ name: "EventLatency"
+ type: 1
+ }
+}
+
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 280111001
+ track_event {
+ track_uuid: 103
+ categories: "cat"
+ name: "EventLatency"
+ type: 2
+ }
+}
+
+# EventLatency 4: below the 100ms threshold; not a long latency
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ track_descriptor {
+ uuid: 104
+ parent_uuid: 10
+ name: "EventLatency"
+ }
+}
+
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 250111001
+ track_event {
+ track_uuid: 104
+ categories: "cat"
+ debug_annotations: {
+ name: "event"
+ string_value: "GestureScrollUpdate"
+ }
+ name: "EventLatency"
+ type: 1
+ }
+}
+
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 350111000
+ track_event {
+ track_uuid: 104
+ categories: "cat"
+ name: "EventLatency"
+ type: 2
+ }
+}
+
+# EventLatency 5: long latency from the second renderer process;
+# should be reported as a standalone long latency occurrence despite having
+# the same end time as EventLatency 1.
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ track_descriptor {
+ uuid: 201
+ parent_uuid: 20
+ name: "EventLatency"
+ }
+}
+
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 111000
+ track_event {
+ track_uuid: 201
+ categories: "cat"
+ debug_annotations: {
+ name: "event"
+ string_value: "GestureScrollUpdate"
+ }
+ name: "EventLatency"
+ type: 1
+ }
+}
+
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 200111000
+ track_event {
+ track_uuid: 201
+ categories: "cat"
+ name: "EventLatency"
+ type: 2
+ }
+}
\ No newline at end of file
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index 18df6ce..da6809b 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -155,7 +155,10 @@
labels?: string[];
trackKindPriority: TrackKindPriority;
trackGroup?: string;
- config: {};
+ config: {
+ trackId?: number;
+ trackIds?: number[];
+ };
}
export interface TrackGroupState {
diff --git a/ui/src/controller/search_controller.ts b/ui/src/controller/search_controller.ts
index d38e64f..6bf5326 100644
--- a/ui/src/controller/search_controller.ts
+++ b/ui/src/controller/search_controller.ts
@@ -217,13 +217,12 @@
cpuToTrackId.set((track.config as {cpu: number}).cpu, track.id);
continue;
}
- if (track.kind === 'ChromeSliceTrack') {
- const config = (track.config as {trackId: number});
+ const config = track.config || {};
+ if (config.trackId !== undefined) {
engineTrackIdToTrackId.set(config.trackId, track.id);
continue;
}
- if (track.kind === 'AsyncSliceTrack') {
- const config = (track.config as {trackIds: number[]});
+ if (config.trackIds !== undefined) {
for (const trackId of config.trackIds) {
engineTrackIdToTrackId.set(trackId, track.id);
}
diff --git a/ui/src/controller/selection_controller.ts b/ui/src/controller/selection_controller.ts
index 66c55a0..a940716 100644
--- a/ui/src/controller/selection_controller.ts
+++ b/ui/src/controller/selection_controller.ts
@@ -50,7 +50,7 @@
processName?: string;
uid?: number;
packageName?: string;
- versionCode?: string;
+ versionCode?: number;
}
// This class queries the TP for the details on a specific slice that has
@@ -539,7 +539,7 @@
// check if the result has returned any rows.
if (packageResult.numRows() > 0) {
const packageDetails =
- packageResult.firstRow({package_name: STR, version_code: STR});
+ packageResult.firstRow({package_name: STR, version_code: NUM});
details.packageName = packageDetails.package_name;
details.versionCode = packageDetails.version_code;
}
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index dd5b51b..e5fa7ad 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -63,7 +63,7 @@
processName?: string;
uid?: number;
packageName?: string;
- versionCode?: string;
+ versionCode?: number;
args?: Args;
argsTree?: ArgsTree;
description?: Description;
diff --git a/ui/src/frontend/keyboard_event_handler.ts b/ui/src/frontend/keyboard_event_handler.ts
index 204fcb2..0bbb98e 100644
--- a/ui/src/frontend/keyboard_event_handler.ts
+++ b/ui/src/frontend/keyboard_event_handler.ts
@@ -42,8 +42,10 @@
const selection = globals.state.currentSelection;
const noModifiers = !(e.ctrlKey || e.metaKey || e.altKey || e.shiftKey);
const ctrlOrMeta = (e.ctrlKey || e.metaKey) && !(e.altKey || e.shiftKey);
+ // No other modifiers other than possibly Shift.
+ const maybeShift = !(e.ctrlKey || e.metaKey || e.altKey);
- if (down && 'm' === key && noModifiers) {
+ if (down && 'm' === key && maybeShift) {
if (selection && selection.kind === 'AREA') {
globals.dispatch(Actions.toggleMarkCurrentArea({persistent: e.shiftKey}));
} else if (selection) {
@@ -56,10 +58,10 @@
if (down && 'b' === key && ctrlOrMeta) {
globals.dispatch(Actions.toggleSidebar({}));
}
- if (down && '?' === key && noModifiers) {
+ if (down && '?' === key && maybeShift) {
toggleHelp();
}
- if (down && 'enter' === key && noModifiers) {
+ if (down && 'enter' === key && maybeShift) {
e.preventDefault();
executeSearch(e.shiftKey);
}
diff --git a/ui/src/frontend/slice_panel.ts b/ui/src/frontend/slice_panel.ts
index 85dbff1..a1b3428 100644
--- a/ui/src/frontend/slice_panel.ts
+++ b/ui/src/frontend/slice_panel.ts
@@ -32,7 +32,10 @@
['Process name', sliceInfo.processName],
['User ID', sliceInfo.uid ? String(sliceInfo.uid) : undefined],
['Package name', sliceInfo.packageName],
- ['Version code', sliceInfo.versionCode]
+ [
+ 'Version code',
+ sliceInfo.versionCode ? String(sliceInfo.versionCode) : undefined
+ ]
]);
}
}
\ No newline at end of file