traced_probes: Auto discovery of vendor tracepoints
Change-Id: Idc0aa1e2fc0298e38858ea6815f71bbc0f49c26b
diff --git a/Android.bp b/Android.bp
index fd0c8c8..12a9318 100644
--- a/Android.bp
+++ b/Android.bp
@@ -6445,6 +6445,7 @@
"src/traced/probes/ftrace/compact_sched.cc",
"src/traced/probes/ftrace/cpu_reader.cc",
"src/traced/probes/ftrace/cpu_stats_parser.cc",
+ "src/traced/probes/ftrace/discover_vendor_tracepoints.cc",
"src/traced/probes/ftrace/event_info.cc",
"src/traced/probes/ftrace/event_info_constants.cc",
"src/traced/probes/ftrace/ftrace_config_muxer.cc",
@@ -6601,6 +6602,7 @@
srcs: [
"src/traced/probes/ftrace/cpu_reader_unittest.cc",
"src/traced/probes/ftrace/cpu_stats_parser_unittest.cc",
+ "src/traced/probes/ftrace/discover_vendor_tracepoints_unittest.cc",
"src/traced/probes/ftrace/event_info_unittest.cc",
"src/traced/probes/ftrace/format_parser_unittest.cc",
"src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc",
diff --git a/BUILD b/BUILD
index 427b2c1..8cb412c 100644
--- a/BUILD
+++ b/BUILD
@@ -1059,6 +1059,8 @@
"src/traced/probes/ftrace/cpu_reader.h",
"src/traced/probes/ftrace/cpu_stats_parser.cc",
"src/traced/probes/ftrace/cpu_stats_parser.h",
+ "src/traced/probes/ftrace/discover_vendor_tracepoints.cc",
+ "src/traced/probes/ftrace/discover_vendor_tracepoints.h",
"src/traced/probes/ftrace/event_info.cc",
"src/traced/probes/ftrace/event_info.h",
"src/traced/probes/ftrace/event_info_constants.cc",
diff --git a/src/android_internal/atrace_hal.cc b/src/android_internal/atrace_hal.cc
index 67e445d..486a44a 100644
--- a/src/android_internal/atrace_hal.cc
+++ b/src/android_internal/atrace_hal.cc
@@ -22,10 +22,11 @@
namespace perfetto {
namespace android_internal {
-using android::hardware::atrace::V1_0::IAtraceDevice;
-using android::hardware::atrace::V1_0::TracingCategory;
+using android::hardware::hidl_string;
using android::hardware::hidl_vec;
using android::hardware::Return;
+using android::hardware::atrace::V1_0::IAtraceDevice;
+using android::hardware::atrace::V1_0::TracingCategory;
namespace {
@@ -40,7 +41,7 @@
} // namespace
-bool GetCategories(TracingVendorCategory* categories, size_t* size_of_arr) {
+bool ListCategories(TracingVendorCategory* categories, size_t* size_of_arr) {
const size_t in_array_size = *size_of_arr;
*size_of_arr = 0;
if (!GetService())
@@ -64,5 +65,30 @@
return true;
}
+bool EnableCategories(const char** categories, size_t categories_count) {
+ if (!GetService())
+ return false;
+ std::vector<hidl_string> args;
+ args.resize(categories_count);
+ for (size_t i = 0; i < categories_count; ++i) {
+ args[i] = categories[i];
+ }
+ g_atraceHal->enableCategories(args);
+ // TODO(hjd): Check status.
+ return true;
+}
+
+bool DisableAllCategories() {
+ if (!GetService())
+ return false;
+ g_atraceHal->disableAllCategories();
+ // TODO(hjd): Check status.
+ return true;
+}
+
+void ForgetService() {
+ g_atraceHal = nullptr;
+}
+
} // namespace android_internal
} // namespace perfetto
diff --git a/src/android_internal/atrace_hal.h b/src/android_internal/atrace_hal.h
index 18d099d..782f800 100644
--- a/src/android_internal/atrace_hal.h
+++ b/src/android_internal/atrace_hal.h
@@ -42,7 +42,14 @@
// These functions are not thread safe unless specified otherwise.
bool __attribute__((visibility("default")))
-GetCategories(TracingVendorCategory*, size_t* size_of_arr);
+ListCategories(TracingVendorCategory*, size_t* size_of_arr);
+
+bool __attribute__((visibility("default")))
+EnableCategories(const char** categories, size_t categories_count);
+
+bool __attribute__((visibility("default"))) DisableAllCategories();
+
+void __attribute__((visibility("default"))) ForgetService();
} // extern "C"
diff --git a/src/traced/probes/ftrace/BUILD.gn b/src/traced/probes/ftrace/BUILD.gn
index 5d9cd70..0ffd645 100644
--- a/src/traced/probes/ftrace/BUILD.gn
+++ b/src/traced/probes/ftrace/BUILD.gn
@@ -60,6 +60,7 @@
sources = [
"cpu_reader_unittest.cc",
"cpu_stats_parser_unittest.cc",
+ "discover_vendor_tracepoints_unittest.cc",
"event_info_unittest.cc",
"format_parser_unittest.cc",
"ftrace_config_muxer_unittest.cc",
@@ -122,6 +123,8 @@
"cpu_reader.h",
"cpu_stats_parser.cc",
"cpu_stats_parser.h",
+ "discover_vendor_tracepoints.cc",
+ "discover_vendor_tracepoints.h",
"event_info.cc",
"event_info.h",
"event_info_constants.cc",
diff --git a/src/traced/probes/ftrace/atrace_hal_wrapper.cc b/src/traced/probes/ftrace/atrace_hal_wrapper.cc
index 11cdd89..48cf8f2 100644
--- a/src/traced/probes/ftrace/atrace_hal_wrapper.cc
+++ b/src/traced/probes/ftrace/atrace_hal_wrapper.cc
@@ -13,8 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#include "src/traced/probes/ftrace/atrace_hal_wrapper.h"
+#include "perfetto/base/build_config.h"
#include "src/android_internal/atrace_hal.h"
#include "src/android_internal/lazy_library_loader.h"
@@ -25,38 +27,83 @@
}
struct AtraceHalWrapper::DynamicLibLoader {
- PERFETTO_LAZY_LOAD(android_internal::GetCategories, get_categories_);
+ PERFETTO_LAZY_LOAD(android_internal::ForgetService, forget_service_);
+ PERFETTO_LAZY_LOAD(android_internal::ListCategories, list_categories_);
+ PERFETTO_LAZY_LOAD(android_internal::EnableCategories, enable_categories_);
+ PERFETTO_LAZY_LOAD(android_internal::DisableAllCategories,
+ disable_all_categories_);
- std::vector<android_internal::TracingVendorCategory> GetCategories() {
- if (!get_categories_)
- return std::vector<android_internal::TracingVendorCategory>();
+ std::vector<std::string> ListCategories() {
+ std::vector<std::string> results;
+ if (!list_categories_)
+ return results;
std::vector<android_internal::TracingVendorCategory> categories(
kMaxNumCategories);
size_t num_cat = categories.size();
- get_categories_(&categories[0], &num_cat);
+ bool success = list_categories_(&categories[0], &num_cat);
+ if (!success)
+ return results;
categories.resize(num_cat);
- return categories;
+
+ for (const auto& category : categories) {
+ results.push_back(category.name);
+ }
+
+ return results;
+ }
+
+ bool EnableCategories(const std::vector<std::string>& categories) {
+ if (!enable_categories_)
+ return false;
+ std::vector<const char*> args;
+ for (const std::string& category : categories) {
+ args.push_back(category.c_str());
+ }
+ return enable_categories_(&args[0], args.size());
+ }
+
+ bool DisableAllCategories() {
+ if (!disable_all_categories_)
+ return false;
+ return disable_all_categories_();
+ }
+
+ void ForgetService() {
+ if (!forget_service_)
+ return;
+ forget_service_();
}
};
AtraceHalWrapper::AtraceHalWrapper() {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
lib_.reset(new DynamicLibLoader());
+#endif
}
-AtraceHalWrapper::~AtraceHalWrapper() = default;
+AtraceHalWrapper::~AtraceHalWrapper() {
+ if (lib_)
+ lib_->ForgetService();
+};
-std::vector<AtraceHalWrapper::TracingVendorCategory>
-AtraceHalWrapper::GetAvailableCategories() {
- auto details = lib_->GetCategories();
- std::vector<AtraceHalWrapper::TracingVendorCategory> result;
- for (size_t i = 0; i < details.size(); i++) {
- AtraceHalWrapper::TracingVendorCategory cat;
- cat.name = details[i].name;
- cat.description = details[i].description;
- result.emplace_back(cat);
- }
- return result;
+std::vector<std::string> AtraceHalWrapper::ListCategories() {
+ if (!lib_)
+ return {};
+ return lib_->ListCategories();
+}
+
+bool AtraceHalWrapper::EnableCategories(
+ const std::vector<std::string>& categories) {
+ if (!lib_)
+ return true;
+ return lib_->EnableCategories(categories);
+}
+
+bool AtraceHalWrapper::DisableAllCategories() {
+ if (!lib_)
+ return true;
+ return lib_->DisableAllCategories();
}
} // namespace perfetto
diff --git a/src/traced/probes/ftrace/atrace_hal_wrapper.h b/src/traced/probes/ftrace/atrace_hal_wrapper.h
index db215ae..6f95fdf 100644
--- a/src/traced/probes/ftrace/atrace_hal_wrapper.h
+++ b/src/traced/probes/ftrace/atrace_hal_wrapper.h
@@ -28,17 +28,11 @@
class AtraceHalWrapper {
public:
AtraceHalWrapper();
- ~AtraceHalWrapper();
+ virtual ~AtraceHalWrapper();
- struct TracingVendorCategory {
- // The name identifying the category.
- std::string name;
-
- // A longer description of the category.
- std::string description;
- };
-
- std::vector<TracingVendorCategory> GetAvailableCategories();
+ virtual std::vector<std::string> ListCategories();
+ virtual bool EnableCategories(const std::vector<std::string>& categories);
+ virtual bool DisableAllCategories();
private:
struct DynamicLibLoader;
diff --git a/src/traced/probes/ftrace/discover_vendor_tracepoints.cc b/src/traced/probes/ftrace/discover_vendor_tracepoints.cc
new file mode 100644
index 0000000..68625c0
--- /dev/null
+++ b/src/traced/probes/ftrace/discover_vendor_tracepoints.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2020 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/traced/probes/ftrace/discover_vendor_tracepoints.h"
+
+#include "perfetto/ext/base/string_splitter.h"
+#include "perfetto/ext/base/string_utils.h"
+#include "src/traced/probes/ftrace/atrace_wrapper.h"
+
+namespace perfetto {
+namespace vendor_tracepoints {
+
+std::vector<GroupAndName> DiscoverTracepoints(AtraceHalWrapper* hal,
+ FtraceProcfs* ftrace,
+ const std::string& category) {
+ ftrace->DisableAllEvents();
+ hal->EnableCategories({category});
+
+ std::vector<GroupAndName> events;
+ for (const std::string& group_name : ftrace->ReadEnabledEvents()) {
+ size_t pos = group_name.find('/');
+ PERFETTO_CHECK(pos != std::string::npos);
+ events.push_back(
+ GroupAndName(group_name.substr(0, pos), group_name.substr(pos + 1)));
+ }
+
+ hal->DisableAllCategories();
+ ftrace->DisableAllEvents();
+ return events;
+}
+
+std::map<std::string, std::vector<GroupAndName>> DiscoverVendorTracepoints(
+ AtraceHalWrapper* hal,
+ FtraceProcfs* ftrace) {
+ std::map<std::string, std::vector<GroupAndName>> results;
+ for (const auto& category : hal->ListCategories()) {
+ results.emplace(category, DiscoverTracepoints(hal, ftrace, category));
+ }
+ return results;
+}
+
+} // namespace vendor_tracepoints
+} // namespace perfetto
diff --git a/src/traced/probes/ftrace/discover_vendor_tracepoints.h b/src/traced/probes/ftrace/discover_vendor_tracepoints.h
new file mode 100644
index 0000000..f5d791b
--- /dev/null
+++ b/src/traced/probes/ftrace/discover_vendor_tracepoints.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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_TRACED_PROBES_FTRACE_DISCOVER_VENDOR_TRACEPOINTS_H_
+#define SRC_TRACED_PROBES_FTRACE_DISCOVER_VENDOR_TRACEPOINTS_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "src/traced/probes/ftrace/atrace_hal_wrapper.h"
+#include "src/traced/probes/ftrace/ftrace_procfs.h"
+#include "src/traced/probes/ftrace/proto_translation_table.h"
+
+namespace perfetto {
+namespace vendor_tracepoints {
+
+// Exposed for testing.
+std::vector<GroupAndName> DiscoverTracepoints(AtraceHalWrapper* hal,
+ FtraceProcfs* ftrace,
+ const std::string& category);
+
+// Returns a map from vendor category to events we should enable
+std::map<std::string, std::vector<GroupAndName>> DiscoverVendorTracepoints(
+ AtraceHalWrapper* hal,
+ FtraceProcfs* ftrace);
+
+} // namespace vendor_tracepoints
+} // namespace perfetto
+
+#endif // SRC_TRACED_PROBES_FTRACE_DISCOVER_VENDOR_TRACEPOINTS_H_
diff --git a/src/traced/probes/ftrace/discover_vendor_tracepoints_unittest.cc b/src/traced/probes/ftrace/discover_vendor_tracepoints_unittest.cc
new file mode 100644
index 0000000..a859c15
--- /dev/null
+++ b/src/traced/probes/ftrace/discover_vendor_tracepoints_unittest.cc
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 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/traced/probes/ftrace/discover_vendor_tracepoints.h"
+
+#include <vector>
+
+#include "test/gtest_and_gmock.h"
+
+#include "src/traced/probes/ftrace/atrace_hal_wrapper.h"
+#include "src/traced/probes/ftrace/atrace_wrapper.h"
+#include "src/traced/probes/ftrace/ftrace_procfs.h"
+
+using testing::_;
+using testing::AnyNumber;
+using testing::ElementsAre;
+using testing::NiceMock;
+using testing::Return;
+using testing::Sequence;
+
+namespace perfetto {
+namespace vendor_tracepoints {
+namespace {
+
+class MockHal : public AtraceHalWrapper {
+ public:
+ MockHal() : AtraceHalWrapper() {}
+ MOCK_METHOD0(ListCategories, std::vector<std::string>());
+ MOCK_METHOD1(EnableCategories, bool(const std::vector<std::string>&));
+ MOCK_METHOD0(DisableAllCategories, bool());
+};
+
+class MockFtraceProcfs : public FtraceProcfs {
+ public:
+ MockFtraceProcfs() : FtraceProcfs("/root/") {
+ ON_CALL(*this, NumberOfCpus()).WillByDefault(Return(1));
+ ON_CALL(*this, WriteToFile(_, _)).WillByDefault(Return(true));
+ ON_CALL(*this, ClearFile(_)).WillByDefault(Return(true));
+ EXPECT_CALL(*this, NumberOfCpus()).Times(AnyNumber());
+ }
+
+ MOCK_METHOD2(WriteToFile,
+ bool(const std::string& path, const std::string& str));
+ MOCK_METHOD2(AppendToFile,
+ bool(const std::string& path, const std::string& str));
+ MOCK_METHOD1(ReadOneCharFromFile, char(const std::string& path));
+ MOCK_METHOD1(ClearFile, bool(const std::string& path));
+ MOCK_CONST_METHOD1(ReadFileIntoString, std::string(const std::string& path));
+ MOCK_METHOD0(ReadEnabledEvents, std::vector<std::string>());
+ MOCK_CONST_METHOD0(NumberOfCpus, size_t());
+ MOCK_CONST_METHOD1(GetEventNamesForGroup,
+ const std::set<std::string>(const std::string& path));
+};
+
+TEST(DiscoverVendorTracepointsTest, DiscoverTracepointsTest) {
+ MockHal hal;
+ MockFtraceProcfs ftrace;
+ Sequence s;
+
+ EXPECT_CALL(ftrace, WriteToFile("/root/events/enable", "0"))
+ .InSequence(s)
+ .WillOnce(Return(true));
+ EXPECT_CALL(hal, EnableCategories(ElementsAre("gfx")))
+ .InSequence(s)
+ .WillOnce(Return(true));
+ EXPECT_CALL(ftrace, ReadEnabledEvents())
+ .InSequence(s)
+ .WillOnce(Return(std::vector<std::string>({"foo/bar", "a/b"})));
+ EXPECT_CALL(hal, DisableAllCategories()).InSequence(s).WillOnce(Return(true));
+ EXPECT_CALL(ftrace, WriteToFile("/root/events/enable", "0"))
+ .InSequence(s)
+ .WillOnce(Return(true));
+
+ EXPECT_THAT(DiscoverTracepoints(&hal, &ftrace, "gfx"),
+ ElementsAre(GroupAndName("foo", "bar"), GroupAndName("a", "b")));
+}
+
+} // namespace
+} // namespace vendor_tracepoints
+} // namespace perfetto
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer.cc b/src/traced/probes/ftrace/ftrace_config_muxer.cc
index 2907e95..596c5c9 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer.cc
+++ b/src/traced/probes/ftrace/ftrace_config_muxer.cc
@@ -152,6 +152,7 @@
events.insert(GroupAndName("mdss", "mdp_sspp_change"));
events.insert(GroupAndName("mdss", "mdp_sspp_set"));
AddEventGroup(table, "mali_systrace", &events);
+
AddEventGroup(table, "sde", &events);
events.insert(GroupAndName("sde", "tracing_mark_write"));
events.insert(GroupAndName("sde", "sde_perf_update_bus"));
@@ -417,9 +418,15 @@
return pages;
}
-FtraceConfigMuxer::FtraceConfigMuxer(FtraceProcfs* ftrace,
- ProtoTranslationTable* table)
- : ftrace_(ftrace), table_(table), current_state_(), ds_configs_() {}
+FtraceConfigMuxer::FtraceConfigMuxer(
+ FtraceProcfs* ftrace,
+ ProtoTranslationTable* table,
+ std::map<std::string, std::vector<GroupAndName>> vendor_events)
+ : ftrace_(ftrace),
+ table_(table),
+ current_state_(),
+ ds_configs_(),
+ vendor_events_(vendor_events) {}
FtraceConfigMuxer::~FtraceConfigMuxer() = default;
FtraceConfigId FtraceConfigMuxer::SetupConfig(const FtraceConfig& request) {
@@ -450,6 +457,18 @@
std::set<GroupAndName> events = GetFtraceEvents(request, table_);
+ // Vendors can provide a set of extra ftrace categories to be enabled when a
+ // specific atrace category is used (e.g. "gfx" -> ["my_hw/my_custom_event",
+ // "my_hw/my_special_gpu"]). Merge them with the hard coded events for each
+ // categories.
+ for (const std::string& category : request.atrace_categories()) {
+ if (vendor_events_.count(category)) {
+ for (const GroupAndName& event : vendor_events_[category]) {
+ events.insert(event);
+ }
+ }
+ }
+
if (RequiresAtrace(request))
UpdateAtrace(request);
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer.h b/src/traced/probes/ftrace/ftrace_config_muxer.h
index 16883c4..4c4ab02 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer.h
+++ b/src/traced/probes/ftrace/ftrace_config_muxer.h
@@ -68,7 +68,10 @@
public:
// The FtraceConfigMuxer and ProtoTranslationTable
// should outlive this instance.
- FtraceConfigMuxer(FtraceProcfs* ftrace, ProtoTranslationTable* table);
+ FtraceConfigMuxer(
+ FtraceProcfs* ftrace,
+ ProtoTranslationTable* table,
+ std::map<std::string, std::vector<GroupAndName>> vendor_events);
virtual ~FtraceConfigMuxer();
// Ask FtraceConfigMuxer to adjust ftrace procfs settings to
@@ -154,6 +157,8 @@
// sizes and events, but don't enable ftrace (i.e. tracing_on).
std::map<FtraceConfigId, FtraceDataSourceConfig> ds_configs_;
+ std::map<std::string, std::vector<GroupAndName>> vendor_events_;
+
// Subset of |ds_configs_| that are currently active. At any time ftrace is
// enabled iff |active_configs_| is not empty.
std::set<FtraceConfigId> active_configs_;
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc b/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
index 0b069c2..d9b5911 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
@@ -197,7 +197,7 @@
FtraceConfig config = CreateFtraceConfig({"power/cpu_frequency"});
- FtraceConfigMuxer model(&ftrace, mock_table.get());
+ FtraceConfigMuxer model(&ftrace, mock_table.get(), {});
ON_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
.WillByDefault(Return("[local] global boot"));
@@ -244,7 +244,7 @@
FtraceConfig config = CreateFtraceConfig({"group_one/foo", "group_two/foo"});
- FtraceConfigMuxer model(&ftrace, mock_table.get());
+ FtraceConfigMuxer model(&ftrace, mock_table.get(), {});
static constexpr int kEventId1 = 1;
Event event1;
@@ -298,7 +298,7 @@
EXPECT_CALL(ftrace,
WriteToFile("/root/events/sched/sched_new_event/enable", "1"));
- FtraceConfigMuxer model(&ftrace, mock_table.get());
+ FtraceConfigMuxer model(&ftrace, mock_table.get(), {});
std::set<std::string> n = {"sched_switch", "sched_new_event"};
ON_CALL(ftrace, GetEventNamesForGroup("events/sched"))
.WillByDefault(Return(n));
@@ -346,7 +346,7 @@
FtraceConfig config = CreateFtraceConfig({"group_one/*", "group_two/*"});
- FtraceConfigMuxer model(&ftrace, mock_table.get());
+ FtraceConfigMuxer model(&ftrace, mock_table.get(), {});
std::set<std::string> event_names = {"foo"};
ON_CALL(ftrace, GetEventNamesForGroup("events/group_one"))
@@ -395,7 +395,7 @@
FtraceConfig config = CreateFtraceConfig({"sched_switch", "foo"});
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
ON_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
.WillByDefault(Return("[local] global boot"));
@@ -445,7 +445,7 @@
FtraceConfig config = CreateFtraceConfig({"sched/sched_switch"});
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
// If someone is using ftrace already don't stomp on what they are doing.
EXPECT_CALL(ftrace, ReadOneCharFromFile("/root/tracing_on"))
@@ -461,7 +461,7 @@
FtraceConfig config = CreateFtraceConfig({"sched/sched_switch"});
*config.add_atrace_categories() = "sched";
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
EXPECT_CALL(ftrace, ReadOneCharFromFile("/root/tracing_on"))
.WillOnce(Return('0'));
@@ -501,7 +501,7 @@
*config.add_atrace_apps() = "com.google.android.gms.persistent";
*config.add_atrace_apps() = "com.google.android.gms";
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
EXPECT_CALL(ftrace, ReadOneCharFromFile("/root/tracing_on"))
.WillOnce(Return('0'));
@@ -542,7 +542,7 @@
*config_c.add_atrace_apps() = "app_c";
*config_c.add_atrace_categories() = "cat_c";
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
EXPECT_CALL(atrace, RunAtrace(ElementsAreArray({"atrace", "--async_start",
"--only_userspace", "cat_a",
@@ -606,7 +606,7 @@
*config_c.add_atrace_categories() = "cat_1";
*config_c.add_atrace_categories() = "cat_3";
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
EXPECT_CALL(
atrace,
@@ -661,7 +661,7 @@
*config_b.add_atrace_apps() = "app_1";
*config_b.add_atrace_categories() = "cat_1";
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
EXPECT_CALL(atrace, RunAtrace(ElementsAreArray({"atrace", "--async_start",
"--only_userspace", "cat_1",
@@ -695,7 +695,7 @@
FtraceConfig config_d = CreateFtraceConfig({"sched/sched_cpu_hotplug"});
*config_d.add_atrace_categories() = "d";
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
FtraceConfigId id_a = model.SetupConfig(config_a);
ASSERT_TRUE(id_a);
@@ -735,7 +735,7 @@
MockFtraceProcfs ftrace;
FtraceConfig config;
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
EXPECT_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
.Times(AnyNumber());
@@ -761,7 +761,7 @@
TEST_F(FtraceConfigMuxerTest, GetFtraceEvents) {
MockFtraceProcfs ftrace;
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
FtraceConfig config = CreateFtraceConfig({"sched/sched_switch"});
std::set<GroupAndName> events =
@@ -773,7 +773,7 @@
TEST_F(FtraceConfigMuxerTest, GetFtraceEventsAtrace) {
MockFtraceProcfs ftrace;
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
FtraceConfig config = CreateFtraceConfig({});
*config.add_atrace_categories() = "sched";
@@ -787,7 +787,7 @@
TEST_F(FtraceConfigMuxerTest, GetFtraceEventsAtraceCategories) {
MockFtraceProcfs ftrace;
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
FtraceConfig config = CreateFtraceConfig({});
*config.add_atrace_categories() = "sched";
@@ -811,7 +811,7 @@
MockFtraceProcfs ftrace;
FtraceConfig config =
CreateFtraceConfig({"sched/sched_switch", "cgroup/cgroup_mkdir"});
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
ON_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
.WillByDefault(Return("[local] global boot"));
@@ -872,7 +872,7 @@
NiceMock<MockFtraceProcfs> ftrace;
table_ = CreateFakeTable(valid_compact_format);
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
// First data source - request compact encoding.
FtraceConfig config_enabled = CreateFtraceConfig({"sched/sched_switch"});
@@ -903,7 +903,7 @@
TEST_F(FtraceConfigMuxerTest, CompactSchedConfigWithInvalidFormat) {
NiceMock<MockFtraceProcfs> ftrace;
- FtraceConfigMuxer model(&ftrace, table_.get());
+ FtraceConfigMuxer model(&ftrace, table_.get(), {});
// Request compact encoding.
FtraceConfig config = CreateFtraceConfig({"sched/sched_switch"});
diff --git a/src/traced/probes/ftrace/ftrace_controller.cc b/src/traced/probes/ftrace/ftrace_controller.cc
index a66ed05..c5a6851 100644
--- a/src/traced/probes/ftrace/ftrace_controller.cc
+++ b/src/traced/probes/ftrace/ftrace_controller.cc
@@ -34,8 +34,10 @@
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/metatrace.h"
#include "perfetto/ext/tracing/core/trace_writer.h"
+#include "src/traced/probes/ftrace/atrace_hal_wrapper.h"
#include "src/traced/probes/ftrace/cpu_reader.h"
#include "src/traced/probes/ftrace/cpu_stats_parser.h"
+#include "src/traced/probes/ftrace/discover_vendor_tracepoints.h"
#include "src/traced/probes/ftrace/event_info.h"
#include "src/traced/probes/ftrace/ftrace_config_muxer.h"
#include "src/traced/probes/ftrace/ftrace_data_source.h"
@@ -136,8 +138,12 @@
if (!table)
return nullptr;
+ AtraceHalWrapper hal;
+ auto vendor_evts =
+ vendor_tracepoints::DiscoverVendorTracepoints(&hal, ftrace_procfs.get());
+
std::unique_ptr<FtraceConfigMuxer> model = std::unique_ptr<FtraceConfigMuxer>(
- new FtraceConfigMuxer(ftrace_procfs.get(), table.get()));
+ new FtraceConfigMuxer(ftrace_procfs.get(), table.get(), vendor_evts));
return std::unique_ptr<FtraceController>(
new FtraceController(std::move(ftrace_procfs), std::move(table),
std::move(model), runner, observer));
diff --git a/src/traced/probes/ftrace/ftrace_controller_unittest.cc b/src/traced/probes/ftrace/ftrace_controller_unittest.cc
index 1f40c83..dca24c8 100644
--- a/src/traced/probes/ftrace/ftrace_controller_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_controller_unittest.cc
@@ -93,7 +93,7 @@
std::unique_ptr<FtraceConfigMuxer> FakeModel(FtraceProcfs* ftrace,
ProtoTranslationTable* table) {
return std::unique_ptr<FtraceConfigMuxer>(
- new FtraceConfigMuxer(ftrace, table));
+ new FtraceConfigMuxer(ftrace, table, {}));
}
class MockFtraceProcfs : public FtraceProcfs {
diff --git a/src/traced/probes/ftrace/ftrace_procfs.cc b/src/traced/probes/ftrace/ftrace_procfs.cc
index 060f4cd..7cfcf2f 100644
--- a/src/traced/probes/ftrace/ftrace_procfs.cc
+++ b/src/traced/probes/ftrace/ftrace_procfs.cc
@@ -27,6 +27,8 @@
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/file_utils.h"
+#include "perfetto/ext/base/string_splitter.h"
+#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/utils.h"
namespace perfetto {
@@ -107,6 +109,20 @@
return ReadFileIntoString(path);
}
+std::vector<std::string> FtraceProcfs::ReadEnabledEvents() {
+ std::string path = root_ + "set_event";
+ std::string s = ReadFileIntoString(path);
+ base::StringSplitter ss(s, '\n');
+ std::vector<std::string> events;
+ while (ss.Next()) {
+ std::string event = ss.cur_token();
+ if (event.size() == 0)
+ continue;
+ events.push_back(base::StripChars(event, ":", '/'));
+ }
+ return events;
+}
+
std::string FtraceProcfs::ReadPageHeaderFormat() const {
std::string path = root_ + "events/header_page";
return ReadFileIntoString(path);
diff --git a/src/traced/probes/ftrace/ftrace_procfs.h b/src/traced/probes/ftrace/ftrace_procfs.h
index cd05adb..3d8186f 100644
--- a/src/traced/probes/ftrace/ftrace_procfs.h
+++ b/src/traced/probes/ftrace/ftrace_procfs.h
@@ -20,6 +20,7 @@
#include <memory>
#include <set>
#include <string>
+#include <vector>
#include "perfetto/ext/base/scoped_file.h"
@@ -91,6 +92,9 @@
// Get all the available clocks.
std::set<std::string> AvailableClocks();
+ // Get all the enabled events.
+ virtual std::vector<std::string> ReadEnabledEvents();
+
// Open the raw pipe for |cpu|.
virtual base::ScopedFile OpenPipeForCpu(size_t cpu);
@@ -98,7 +102,7 @@
const std::string& path) const;
protected:
- // virtual and public for testing.
+ // virtual and protected for testing.
virtual bool WriteToFile(const std::string& path, const std::string& str);
virtual bool AppendToFile(const std::string& path, const std::string& str);
virtual bool ClearFile(const std::string& path);
diff --git a/src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc b/src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc
index b8bf269..8dd848f 100644
--- a/src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc
+++ b/src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc
@@ -24,9 +24,11 @@
#include "src/traced/probes/ftrace/ftrace_procfs.h"
#include "test/gtest_and_gmock.h"
-using testing::HasSubstr;
-using testing::Not;
using testing::Contains;
+using testing::HasSubstr;
+using testing::IsEmpty;
+using testing::Not;
+using testing::UnorderedElementsAre;
namespace perfetto {
namespace {
@@ -223,4 +225,27 @@
EXPECT_THAT(GetTraceOutput(), Not(HasSubstr("Hello")));
}
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#define MAYBE_ReadEnabledEvents ReadEnabledEvents
+#else
+#define MAYBE_ReadEnabledEvents DISABLED_ReadEnabledEvents
+#endif
+TEST(FtraceProcfsIntegrationTest, MAYBE_ReadEnabledEvents) {
+ FtraceProcfs ftrace(GetFtracePath());
+ ResetFtrace(&ftrace);
+
+ EXPECT_THAT(ftrace.ReadEnabledEvents(), IsEmpty());
+
+ ftrace.EnableEvent("sched", "sched_switch");
+ ftrace.EnableEvent("kmem", "kmalloc");
+
+ EXPECT_THAT(ftrace.ReadEnabledEvents(),
+ UnorderedElementsAre("sched/sched_switch", "kmem/kmalloc"));
+
+ ftrace.DisableEvent("sched", "sched_switch");
+ ftrace.DisableEvent("kmem", "kmalloc");
+
+ EXPECT_THAT(ftrace.ReadEnabledEvents(), IsEmpty());
+}
+
} // namespace perfetto
diff --git a/src/traced/probes/ftrace/proto_translation_table.h b/src/traced/probes/ftrace/proto_translation_table.h
index f9c5be6..83dd19d 100644
--- a/src/traced/probes/ftrace/proto_translation_table.h
+++ b/src/traced/probes/ftrace/proto_translation_table.h
@@ -19,6 +19,7 @@
#include <stdint.h>
+#include <iostream>
#include <map>
#include <memory>
#include <set>
@@ -65,6 +66,10 @@
std::string name_;
};
+inline void PrintTo(const GroupAndName& event, ::std::ostream* os) {
+ *os << "GroupAndName(" << event.group() << ", " << event.name() << ")";
+}
+
bool InferFtraceType(const std::string& type_and_name,
size_t size,
bool is_signed,