Support perfetto track_event prefer
Trace.java now supports per-category tracing to perfetto if specified
in the config. When we trace to perfetto, the event will be missing from
the ftrace buffer. This means that a concurrent session that has the
same category enabled for atrace will be missing the atrace event.
To avoid this, the config can specify that the perfetto event can be
preferred. This means that despite the category being enabled for
atrace, we will trace to perfetto if the category is enabled there.
By default, the perfetto event is not preferred, but it can be preferred
explicitly in the config with atrace_categories_prefer_track_event.
Bug: 303199244
Test: atest libtracing_perfetto_tests
Flag: android.os.flags.perfetto_sdk_tracing
Change-Id: Idf7cfc7c7f9c8ac4191cabff3d958926606f564b
diff --git a/libs/tracing_perfetto/tests/Android.bp b/libs/tracing_perfetto/tests/Android.bp
index a35b0e0..d203467 100644
--- a/libs/tracing_perfetto/tests/Android.bp
+++ b/libs/tracing_perfetto/tests/Android.bp
@@ -26,6 +26,7 @@
static_libs: [
"libflagtest",
"libgmock",
+ "perfetto_trace_protos",
],
cflags: [
"-Wall",
@@ -35,6 +36,8 @@
"android.os.flags-aconfig-cc-host",
"libbase",
"libperfetto_c",
+ "liblog",
+ "libprotobuf-cpp-lite",
"libtracing_perfetto",
],
srcs: [
diff --git a/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp b/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp
index 7716b9a..e9fee2e 100644
--- a/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp
+++ b/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp
@@ -16,10 +16,10 @@
#include "tracing_perfetto.h"
-#include <thread>
-
#include <android_os.h>
#include <flag_macros.h>
+#include <thread>
+#include <unistd.h>
#include "gtest/gtest.h"
#include "perfetto/public/abi/data_source_abi.h"
@@ -45,67 +45,182 @@
#include "trace_categories.h"
#include "utils.h"
+#include "protos/perfetto/trace/trace.pb.h"
+#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "protos/perfetto/trace/interned_data/interned_data.pb.h"
+
+#include <fstream>
+#include <iterator>
namespace tracing_perfetto {
-using ::perfetto::shlib::test_utils::AllFieldsWithId;
-using ::perfetto::shlib::test_utils::FieldView;
-using ::perfetto::shlib::test_utils::IdFieldView;
-using ::perfetto::shlib::test_utils::MsgField;
-using ::perfetto::shlib::test_utils::PbField;
-using ::perfetto::shlib::test_utils::StringField;
+using ::perfetto::protos::Trace;
+using ::perfetto::protos::TracePacket;
+using ::perfetto::protos::EventCategory;
+using ::perfetto::protos::EventName;
+using ::perfetto::protos::FtraceEvent;
+using ::perfetto::protos::FtraceEventBundle;
+using ::perfetto::protos::InternedData;
+
using ::perfetto::shlib::test_utils::TracingSession;
-using ::perfetto::shlib::test_utils::VarIntField;
-using ::testing::_;
-using ::testing::ElementsAre;
-using ::testing::UnorderedElementsAre;
const auto PERFETTO_SDK_TRACING = ACONFIG_FLAG(android::os, perfetto_sdk_tracing);
+// TODO(b/303199244): Add tests for all the library functions.
class TracingPerfettoTest : public testing::Test {
protected:
void SetUp() override {
- tracing_perfetto::registerWithPerfetto(true /* test */);
+ tracing_perfetto::registerWithPerfetto(false /* test */);
}
};
-// TODO(b/303199244): Add tests for all the library functions.
-
-TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstant,
- REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) {
- TracingSession tracing_session =
- TracingSession::Builder().set_data_source_name("track_event").Build();
- tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, "");
-
+Trace stopSession(TracingSession& tracing_session) {
+ tracing_session.FlushBlocking(5000);
tracing_session.StopBlocking();
std::vector<uint8_t> data = tracing_session.ReadBlocking();
+ std::string data_string(data.begin(), data.end());
+
+ perfetto::protos::Trace trace;
+ trace.ParseFromString(data_string);
+
+ return trace;
+}
+
+void verifyTrackEvent(const Trace& trace, const std::string expected_category,
+ const std::string& expected_name) {
bool found = false;
- for (struct PerfettoPbDecoderField trace_field : FieldView(data)) {
- ASSERT_THAT(trace_field, PbField(perfetto_protos_Trace_packet_field_number,
- MsgField(_)));
- IdFieldView track_event(
- trace_field, perfetto_protos_TracePacket_track_event_field_number);
- if (track_event.size() == 0) {
- continue;
+ for (const TracePacket& packet: trace.packet()) {
+ if (packet.has_track_event() && packet.has_interned_data()) {
+
+ const InternedData& interned_data = packet.interned_data();
+ if (interned_data.event_categories_size() > 0) {
+ const EventCategory& event_category = packet.interned_data().event_categories(0);
+ if (event_category.name() == expected_category) {
+ found = true;
+ }
+ }
+
+ if (interned_data.event_names_size() > 0) {
+ const EventName& event_name = packet.interned_data().event_names(0);
+ if (event_name.name() == expected_name) {
+ found &= true;
+ }
+ }
+
+ if (found) {
+ break;
+ }
}
- found = true;
- IdFieldView cat_iid_fields(
- track_event.front(),
- perfetto_protos_TrackEvent_category_iids_field_number);
- ASSERT_THAT(cat_iid_fields, ElementsAre(VarIntField(_)));
- uint64_t cat_iid = cat_iid_fields.front().value.integer64;
- EXPECT_THAT(
- trace_field,
- AllFieldsWithId(
- perfetto_protos_TracePacket_interned_data_field_number,
- ElementsAre(AllFieldsWithId(
- perfetto_protos_InternedData_event_categories_field_number,
- ElementsAre(MsgField(UnorderedElementsAre(
- PbField(perfetto_protos_EventCategory_iid_field_number,
- VarIntField(cat_iid)),
- PbField(perfetto_protos_EventCategory_name_field_number,
- StringField("input")))))))));
}
EXPECT_TRUE(found);
}
-} // namespace tracing_perfetto
\ No newline at end of file
+void verifyAtraceEvent(const Trace& trace, const std::string& expected_name) {
+ std::string expected_print_buf = "I|" + std::to_string(gettid()) + "|" + expected_name + "\n";
+
+ bool found = false;
+ for (const TracePacket& packet: trace.packet()) {
+ if (packet.has_ftrace_events()) {
+ const FtraceEventBundle& ftrace_events_bundle = packet.ftrace_events();
+
+ if (ftrace_events_bundle.event_size() > 0) {
+ const FtraceEvent& ftrace_event = ftrace_events_bundle.event(0);
+ if (ftrace_event.has_print() && (ftrace_event.print().buf() == expected_print_buf)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ EXPECT_TRUE(found);
+}
+
+TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithPerfetto,
+ REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) {
+ std::string event_category = "input";
+ std::string event_name = "traceInstantWithPerfetto";
+
+ TracingSession tracing_session =
+ TracingSession::Builder().add_enabled_category(event_category).Build();
+
+ tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str());
+
+ Trace trace = stopSession(tracing_session);
+
+ verifyTrackEvent(trace, event_category, event_name);
+}
+
+TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithAtrace,
+ REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) {
+ std::string event_category = "input";
+ std::string event_name = "traceInstantWithAtrace";
+
+ TracingSession tracing_session =
+ TracingSession::Builder().add_atrace_category(event_category).Build();
+
+ tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str());
+
+ Trace trace = stopSession(tracing_session);
+
+ verifyAtraceEvent(trace, event_name);
+}
+
+TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithPerfettoAndAtrace,
+ REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) {
+ std::string event_category = "input";
+ std::string event_name = "traceInstantWithPerfettoAndAtrace";
+
+ TracingSession tracing_session =
+ TracingSession::Builder()
+ .add_atrace_category(event_category)
+ .add_enabled_category(event_category).Build();
+
+ tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str());
+
+ Trace trace = stopSession(tracing_session);
+
+ verifyAtraceEvent(trace, event_name);
+}
+
+TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithPerfettoAndAtraceAndPreferTrackEvent,
+ REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) {
+ std::string event_category = "input";
+ std::string event_name = "traceInstantWithPerfettoAndAtraceAndPreferTrackEvent";
+
+ TracingSession tracing_session =
+ TracingSession::Builder()
+ .add_atrace_category(event_category)
+ .add_atrace_category_prefer_sdk(event_category)
+ .add_enabled_category(event_category).Build();
+
+ tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str());
+
+ Trace trace = stopSession(tracing_session);
+
+ verifyTrackEvent(trace, event_category, event_name);
+}
+
+TEST_F_WITH_FLAGS(TracingPerfettoTest, traceInstantWithPerfettoAndAtraceConcurrently,
+ REQUIRES_FLAGS_ENABLED(PERFETTO_SDK_TRACING)) {
+ std::string event_category = "input";
+ std::string event_name = "traceInstantWithPerfettoAndAtraceConcurrently";
+
+ TracingSession perfetto_tracing_session =
+ TracingSession::Builder()
+ .add_atrace_category(event_category)
+ .add_atrace_category_prefer_sdk(event_category)
+ .add_enabled_category(event_category).Build();
+
+ TracingSession atrace_tracing_session =
+ TracingSession::Builder()
+ .add_atrace_category(event_category)
+ .add_enabled_category(event_category).Build();
+
+ tracing_perfetto::traceInstant(TRACE_CATEGORY_INPUT, event_name.c_str());
+
+ Trace atrace_trace = stopSession(atrace_tracing_session);
+ Trace perfetto_trace = stopSession(perfetto_tracing_session);
+
+ verifyAtraceEvent(atrace_trace, event_name);
+ verifyAtraceEvent(perfetto_trace, event_name);
+}
+} // namespace tracing_perfetto
diff --git a/libs/tracing_perfetto/tests/utils.cpp b/libs/tracing_perfetto/tests/utils.cpp
index 9c42028..8c4d4a8 100644
--- a/libs/tracing_perfetto/tests/utils.cpp
+++ b/libs/tracing_perfetto/tests/utils.cpp
@@ -26,6 +26,11 @@
#include "perfetto/public/protos/config/track_event/track_event_config.pzc.h"
#include "perfetto/public/tracing_session.h"
+#include "protos/perfetto/config/ftrace/ftrace_config.pb.h"
+#include "protos/perfetto/config/track_event/track_event_config.pb.h"
+#include "protos/perfetto/config/data_source_config.pb.h"
+#include "protos/perfetto/config/trace_config.pb.h"
+
namespace perfetto {
namespace shlib {
namespace test_utils {
@@ -44,63 +49,54 @@
} // namespace
TracingSession TracingSession::Builder::Build() {
- struct PerfettoPbMsgWriter writer;
- struct PerfettoHeapBuffer* hb = PerfettoHeapBufferCreate(&writer.writer);
+ perfetto::protos::TraceConfig trace_config;
+ trace_config.add_buffers()->set_size_kb(1024);
- struct perfetto_protos_TraceConfig cfg;
- PerfettoPbMsgInit(&cfg.msg, &writer);
+ auto* track_event_ds_config = trace_config.add_data_sources()->mutable_config();
+ auto* ftrace_ds_config = trace_config.add_data_sources()->mutable_config();
+
+ track_event_ds_config->set_name("track_event");
+ track_event_ds_config->set_target_buffer(0);
+
+ ftrace_ds_config->set_name("linux.ftrace");
+ ftrace_ds_config->set_target_buffer(0);
{
- struct perfetto_protos_TraceConfig_BufferConfig buffers;
- perfetto_protos_TraceConfig_begin_buffers(&cfg, &buffers);
-
- perfetto_protos_TraceConfig_BufferConfig_set_size_kb(&buffers, 1024);
-
- perfetto_protos_TraceConfig_end_buffers(&cfg, &buffers);
- }
-
- {
- struct perfetto_protos_TraceConfig_DataSource data_sources;
- perfetto_protos_TraceConfig_begin_data_sources(&cfg, &data_sources);
-
- {
- struct perfetto_protos_DataSourceConfig ds_cfg;
- perfetto_protos_TraceConfig_DataSource_begin_config(&data_sources,
- &ds_cfg);
-
- perfetto_protos_DataSourceConfig_set_cstr_name(&ds_cfg,
- data_source_name_.c_str());
- if (!enabled_categories_.empty() && !disabled_categories_.empty()) {
- perfetto_protos_TrackEventConfig te_cfg;
- perfetto_protos_DataSourceConfig_begin_track_event_config(&ds_cfg,
- &te_cfg);
- for (const std::string& cat : enabled_categories_) {
- perfetto_protos_TrackEventConfig_set_enabled_categories(
- &te_cfg, cat.data(), cat.size());
- }
- for (const std::string& cat : disabled_categories_) {
- perfetto_protos_TrackEventConfig_set_disabled_categories(
- &te_cfg, cat.data(), cat.size());
- }
- perfetto_protos_DataSourceConfig_end_track_event_config(&ds_cfg,
- &te_cfg);
+ auto* ftrace_config = ftrace_ds_config->mutable_ftrace_config();
+ if (!atrace_categories_.empty()) {
+ ftrace_config->add_ftrace_events("ftrace/print");
+ for (const std::string& cat : atrace_categories_) {
+ ftrace_config->add_atrace_categories(cat);
}
- perfetto_protos_TraceConfig_DataSource_end_config(&data_sources, &ds_cfg);
+ for (const std::string& cat : atrace_categories_prefer_sdk_) {
+ ftrace_config->add_atrace_categories_prefer_sdk(cat);
+ }
}
-
- perfetto_protos_TraceConfig_end_data_sources(&cfg, &data_sources);
}
- size_t cfg_size = PerfettoStreamWriterGetWrittenSize(&writer.writer);
- std::unique_ptr<uint8_t[]> ser(new uint8_t[cfg_size]);
- PerfettoHeapBufferCopyInto(hb, &writer.writer, ser.get(), cfg_size);
- PerfettoHeapBufferDestroy(hb, &writer.writer);
+
+ {
+ auto* track_event_config = track_event_ds_config->mutable_track_event_config();
+ if (!enabled_categories_.empty() || !disabled_categories_.empty()) {
+ for (const std::string& cat : enabled_categories_) {
+ track_event_config->add_enabled_categories(cat);
+ }
+
+ for (const std::string& cat : disabled_categories_) {
+ track_event_config->add_disabled_categories(cat);
+ }
+ }
+ }
struct PerfettoTracingSessionImpl* ts =
- PerfettoTracingSessionCreate(PERFETTO_BACKEND_IN_PROCESS);
+ PerfettoTracingSessionCreate(PERFETTO_BACKEND_SYSTEM);
- PerfettoTracingSessionSetup(ts, ser.get(), cfg_size);
+ std::string trace_config_string;
+ trace_config.SerializeToString(&trace_config_string);
+ PerfettoTracingSessionSetup(ts, trace_config_string.data(), trace_config_string.length());
+
+ // Fails to start here
PerfettoTracingSessionStartBlocking(ts);
return TracingSession::Adopt(ts);
diff --git a/libs/tracing_perfetto/tests/utils.h b/libs/tracing_perfetto/tests/utils.h
index 4353554..8edb414 100644
--- a/libs/tracing_perfetto/tests/utils.h
+++ b/libs/tracing_perfetto/tests/utils.h
@@ -74,10 +74,6 @@
class Builder {
public:
Builder() = default;
- Builder& set_data_source_name(std::string data_source_name) {
- data_source_name_ = std::move(data_source_name);
- return *this;
- }
Builder& add_enabled_category(std::string category) {
enabled_categories_.push_back(std::move(category));
return *this;
@@ -86,12 +82,21 @@
disabled_categories_.push_back(std::move(category));
return *this;
}
+ Builder& add_atrace_category(std::string category) {
+ atrace_categories_.push_back(std::move(category));
+ return *this;
+ }
+ Builder& add_atrace_category_prefer_sdk(std::string category) {
+ atrace_categories_prefer_sdk_.push_back(std::move(category));
+ return *this;
+ }
TracingSession Build();
private:
- std::string data_source_name_;
std::vector<std::string> enabled_categories_;
std::vector<std::string> disabled_categories_;
+ std::vector<std::string> atrace_categories_;
+ std::vector<std::string> atrace_categories_prefer_sdk_;
};
static TracingSession Adopt(struct PerfettoTracingSessionImpl*);