Perfetto: Add game mode intervention data source
Bug: 219543620
Doc: go/game-dashboard-information-to-perfetto
Test: tools/run_android_test out/android perfetto_unittests
Change-Id: I5d2a10d5f6da384d9d9941f4a05f7dbf32fe3827
diff --git a/Android.bp b/Android.bp
index 4cb171f..448e0d3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -534,6 +534,7 @@
":perfetto_src_protozero_filtering_bytecode_parser",
":perfetto_src_protozero_filtering_message_filter",
":perfetto_src_protozero_protozero",
+ ":perfetto_src_traced_probes_android_game_intervention_list_android_game_intervention_list",
":perfetto_src_traced_probes_android_log_android_log",
":perfetto_src_traced_probes_common_common",
":perfetto_src_traced_probes_data_source",
@@ -1097,6 +1098,7 @@
":perfetto_src_protozero_filtering_bytecode_parser",
":perfetto_src_protozero_filtering_message_filter",
":perfetto_src_protozero_protozero",
+ ":perfetto_src_traced_probes_android_game_intervention_list_android_game_intervention_list",
":perfetto_src_traced_probes_android_log_android_log",
":perfetto_src_traced_probes_common_common",
":perfetto_src_traced_probes_data_source",
@@ -1358,6 +1360,7 @@
":perfetto_src_protozero_filtering_bytecode_parser",
":perfetto_src_protozero_filtering_message_filter",
":perfetto_src_protozero_protozero",
+ ":perfetto_src_traced_probes_android_game_intervention_list_android_game_intervention_list",
":perfetto_src_traced_probes_android_log_android_log",
":perfetto_src_traced_probes_common_common",
":perfetto_src_traced_probes_data_source",
@@ -1839,6 +1842,7 @@
":perfetto_src_trace_processor_util_protozero_to_text",
":perfetto_src_trace_processor_util_util",
":perfetto_src_trace_processor_views_views",
+ ":perfetto_src_traced_probes_android_game_intervention_list_android_game_intervention_list",
":perfetto_src_traced_probes_android_log_android_log",
":perfetto_src_traced_probes_common_common",
":perfetto_src_traced_probes_data_source",
@@ -8996,6 +9000,22 @@
],
}
+// GN: //src/traced/probes/android_game_intervention_list:android_game_intervention_list
+filegroup {
+ name: "perfetto_src_traced_probes_android_game_intervention_list_android_game_intervention_list",
+ srcs: [
+ "src/traced/probes/android_game_intervention_list/android_game_intervention_list_data_source.cc",
+ ],
+}
+
+// GN: //src/traced/probes/android_game_intervention_list:unittests
+filegroup {
+ name: "perfetto_src_traced_probes_android_game_intervention_list_unittests",
+ srcs: [
+ "src/traced/probes/android_game_intervention_list/android_game_intervention_list_unittest.cc",
+ ],
+}
+
// GN: //src/traced/probes/android_log:android_log
filegroup {
name: "perfetto_src_traced_probes_android_log_android_log",
@@ -10148,6 +10168,8 @@
":perfetto_src_trace_processor_util_util",
":perfetto_src_trace_processor_views_unittests",
":perfetto_src_trace_processor_views_views",
+ ":perfetto_src_traced_probes_android_game_intervention_list_android_game_intervention_list",
+ ":perfetto_src_traced_probes_android_game_intervention_list_unittests",
":perfetto_src_traced_probes_android_log_android_log",
":perfetto_src_traced_probes_android_log_unittests",
":perfetto_src_traced_probes_common_common",
diff --git a/BUILD b/BUILD
index 608dd87..d293f71 100644
--- a/BUILD
+++ b/BUILD
@@ -227,6 +227,7 @@
":src_protozero_filtering_bytecode_common",
":src_protozero_filtering_bytecode_parser",
":src_protozero_filtering_message_filter",
+ ":src_traced_probes_android_game_intervention_list_android_game_intervention_list",
":src_traced_probes_android_log_android_log",
":src_traced_probes_common_common",
":src_traced_probes_data_source",
@@ -1722,6 +1723,15 @@
],
)
+# GN target: //src/traced/probes/android_game_intervention_list:android_game_intervention_list
+perfetto_filegroup(
+ name = "src_traced_probes_android_game_intervention_list_android_game_intervention_list",
+ srcs = [
+ "src/traced/probes/android_game_intervention_list/android_game_intervention_list_data_source.cc",
+ "src/traced/probes/android_game_intervention_list/android_game_intervention_list_data_source.h",
+ ],
+)
+
# GN target: //src/traced/probes/android_log:android_log
perfetto_filegroup(
name = "src_traced_probes_android_log_android_log",
diff --git a/src/traced/probes/BUILD.gn b/src/traced/probes/BUILD.gn
index 039f6e6..c60ba95 100644
--- a/src/traced/probes/BUILD.gn
+++ b/src/traced/probes/BUILD.gn
@@ -57,6 +57,7 @@
"../../base",
"../../tracing/core",
"../../tracing/ipc/producer",
+ "android_game_intervention_list",
"android_log",
"common",
"filesystem",
@@ -96,6 +97,7 @@
"../../../gn:default_deps",
"../../../gn:gtest_and_gmock",
"../../tracing/test:test_support",
+ "android_game_intervention_list:unittests",
"android_log:unittests",
"common:unittests",
"filesystem:unittests",
diff --git a/src/traced/probes/android_game_intervention_list/BUILD.gn b/src/traced/probes/android_game_intervention_list/BUILD.gn
new file mode 100644
index 0000000..0827b66
--- /dev/null
+++ b/src/traced/probes/android_game_intervention_list/BUILD.gn
@@ -0,0 +1,48 @@
+# 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.
+
+import("../../../../gn/test.gni")
+
+source_set("android_game_intervention_list") {
+ public_deps = [ "../../../tracing/core" ]
+ deps = [
+ "..:data_source",
+ "../../../../gn:default_deps",
+ "../../../../include/perfetto/ext/traced",
+ "../../../../protos/perfetto/common:zero",
+ "../../../../protos/perfetto/config/android:zero",
+ "../../../../protos/perfetto/trace:zero",
+ "../../../../protos/perfetto/trace/android:zero",
+ "../../../base",
+ ]
+ sources = [
+ "android_game_intervention_list_data_source.cc",
+ "android_game_intervention_list_data_source.h",
+ ]
+}
+
+perfetto_unittest_source_set("unittests") {
+ testonly = true
+ deps = [
+ ":android_game_intervention_list",
+ "../../../../gn:default_deps",
+ "../../../../gn:gtest_and_gmock",
+ "../../../../protos/perfetto/config/android:cpp",
+ "../../../../protos/perfetto/trace/android:cpp",
+ "../../../../protos/perfetto/trace/android:zero",
+ "../../../../src/base:test_support",
+ "../../../../src/tracing/test:test_support",
+ ]
+ sources = [ "android_game_intervention_list_unittest.cc" ]
+}
diff --git a/src/traced/probes/android_game_intervention_list/android_game_intervention_list_data_source.cc b/src/traced/probes/android_game_intervention_list/android_game_intervention_list_data_source.cc
new file mode 100644
index 0000000..5d8f6c4
--- /dev/null
+++ b/src/traced/probes/android_game_intervention_list/android_game_intervention_list_data_source.cc
@@ -0,0 +1,225 @@
+/*
+ * 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/traced/probes/android_game_intervention_list/android_game_intervention_list_data_source.h"
+
+#include <stddef.h>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/optional.h"
+#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/ext/base/string_splitter.h"
+#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/ext/tracing/core/trace_writer.h"
+
+#include "perfetto/tracing/core/data_source_config.h"
+#include "protos/perfetto/config/android/android_game_intervention_list_config.pbzero.h"
+#include "protos/perfetto/trace/android/android_game_intervention_list.pbzero.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+
+const char kAndroidGameInterventionListFileName[] =
+ "/data/system/game_mode_intervention.list";
+
+// making the descriptor static
+const ProbesDataSource::Descriptor
+ AndroidGameInterventionListDataSource::descriptor = {
+ /* name */ "android.game_interventions",
+ /* flags */ Descriptor::kFlagsNone,
+ /* fill_descriptor_func */ nullptr,
+};
+
+AndroidGameInterventionListDataSource::AndroidGameInterventionListDataSource(
+ const DataSourceConfig& ds_config,
+ TracingSessionID session_id,
+ std::unique_ptr<TraceWriter> trace_writer)
+ : ProbesDataSource(session_id, &descriptor),
+ trace_writer_(std::move(trace_writer)) {
+ perfetto::protos::pbzero::AndroidGameInterventionListConfig::Decoder cfg(
+ ds_config.android_game_intervention_list_config_raw());
+ for (auto name = cfg.package_name_filter(); name; ++name) {
+ package_name_filter_.emplace_back((*name).ToStdString());
+ }
+}
+
+AndroidGameInterventionListDataSource::
+ ~AndroidGameInterventionListDataSource() = default;
+
+void AndroidGameInterventionListDataSource::Start() {
+ auto trace_packet = trace_writer_->NewTracePacket();
+ auto* android_game_intervention_list_packet =
+ trace_packet->set_android_game_intervention_list();
+
+ base::ScopedFstream fs(fopen(kAndroidGameInterventionListFileName, "r"));
+ if (!fs) {
+ PERFETTO_ELOG("Failed to open %s", kAndroidGameInterventionListFileName);
+ android_game_intervention_list_packet->set_read_error(true);
+ } else {
+ bool is_parsed_fully = ParseAndroidGameInterventionListStream(
+ android_game_intervention_list_packet, fs, package_name_filter_);
+ if (!is_parsed_fully) {
+ android_game_intervention_list_packet->set_parse_error(true);
+ }
+ if (ferror(*fs)) {
+ android_game_intervention_list_packet->set_read_error(true);
+ }
+ }
+
+ trace_packet->Finalize();
+ trace_writer_->Flush();
+}
+
+void AndroidGameInterventionListDataSource::Flush(
+ FlushRequestID,
+ std::function<void()> callback) {
+ callback();
+}
+
+bool AndroidGameInterventionListDataSource::
+ ParseAndroidGameInterventionListStream(
+ protos::pbzero::AndroidGameInterventionList* packet,
+ const base::ScopedFstream& fs,
+ const std::vector<std::string>& package_name_filter) {
+ bool is_parsed_fully = true;
+ char line_buf[2048];
+ while (fgets(line_buf, sizeof(line_buf), *fs) != nullptr) {
+ // removing trailing '\n'
+ // for processing fields with CStringTo* functions
+ line_buf[strlen(line_buf) - 1] = '\0';
+
+ if (!ParseAndroidGameInterventionListLine(line_buf, package_name_filter,
+ packet)) {
+ // marking parsed with error and continue with this line skipped
+ is_parsed_fully = false;
+ }
+ }
+ return is_parsed_fully;
+}
+
+bool AndroidGameInterventionListDataSource::
+ ParseAndroidGameInterventionListLine(
+ char* line,
+ const std::vector<std::string>& package_name_filter,
+ protos::pbzero::AndroidGameInterventionList* packet) {
+ size_t idx = 0;
+ perfetto::protos::pbzero::AndroidGameInterventionList_GamePackageInfo*
+ package = nullptr;
+ perfetto::protos::pbzero::AndroidGameInterventionList_GameModeInfo*
+ game_mode_info = nullptr;
+ for (base::StringSplitter string_splitter(line, ' '); string_splitter.Next();
+ ++idx) {
+ // check if package name is in the name filter
+ // if not we skip parsing this line.
+ if (idx == 0) {
+ if (!package_name_filter.empty() &&
+ std::count(package_name_filter.begin(), package_name_filter.end(),
+ string_splitter.cur_token()) == 0) {
+ return true;
+ }
+ package = packet->add_game_packages();
+ }
+
+ switch (idx) {
+ case 0: {
+ package->set_name(string_splitter.cur_token(),
+ string_splitter.cur_token_size());
+ break;
+ }
+ case 1: {
+ base::Optional<uint64_t> uid =
+ base::CStringToUInt64(string_splitter.cur_token());
+ if (uid == base::nullopt) {
+ PERFETTO_DLOG("Failed to parse game_mode_intervention.list uid.");
+ return false;
+ }
+ package->set_uid(uid.value());
+ break;
+ }
+ case 2: {
+ base::Optional<uint32_t> cur_mode =
+ base::CStringToUInt32(string_splitter.cur_token());
+ if (cur_mode == base::nullopt) {
+ PERFETTO_DLOG(
+ "Failed to parse game_mode_intervention.list cur_mode.");
+ return false;
+ }
+ package->set_current_mode(cur_mode.value());
+ break;
+ }
+ case 3:
+ case 5: {
+ base::Optional<uint32_t> game_mode =
+ base::CStringToUInt32(string_splitter.cur_token());
+ if (game_mode == base::nullopt) {
+ PERFETTO_DLOG(
+ "Failed to parse game_mode_intervention.list game_mode.");
+ return false;
+ }
+ game_mode_info = package->add_game_mode_info();
+ game_mode_info->set_mode(game_mode.value());
+ break;
+ }
+ case 4:
+ case 6: {
+ for (base::StringSplitter intervention_splitter(
+ string_splitter.cur_token(), ',');
+ intervention_splitter.Next();) {
+ base::StringSplitter value_splitter(intervention_splitter.cur_token(),
+ '=');
+ value_splitter.Next();
+ char* key = value_splitter.cur_token();
+ if (strcmp(key, "angle") == 0) {
+ value_splitter.Next();
+ base::Optional<uint32_t> use_angle =
+ base::CStringToUInt32(value_splitter.cur_token());
+ if (use_angle == base::nullopt) {
+ PERFETTO_DLOG(
+ "Failed to parse game_mode_intervention.list use_angle.");
+ return false;
+ }
+ game_mode_info->set_use_angle(use_angle.value());
+ } else if (strcmp(key, "scaling") == 0) {
+ value_splitter.Next();
+ base::Optional<double> resolution_downscale =
+ base::CStringToDouble(value_splitter.cur_token());
+ if (resolution_downscale == base::nullopt) {
+ PERFETTO_DLOG(
+ "Failed to parse game_mode_intervention.list "
+ "resolution_downscale.");
+ return false;
+ }
+ game_mode_info->set_resolution_downscale(
+ static_cast<float>(resolution_downscale.value()));
+ } else if (strcmp(key, "fps") == 0) {
+ value_splitter.Next();
+ base::Optional<double> fps =
+ base::CStringToDouble(value_splitter.cur_token());
+ if (fps == base::nullopt) {
+ PERFETTO_DLOG("Failed to parse game_mode_intervention.list fps.");
+ return false;
+ }
+ game_mode_info->set_fps(static_cast<float>(fps.value()));
+ }
+ }
+ break;
+ }
+ }
+ }
+ return true;
+}
+
+} // namespace perfetto
diff --git a/src/traced/probes/android_game_intervention_list/android_game_intervention_list_data_source.h b/src/traced/probes/android_game_intervention_list/android_game_intervention_list_data_source.h
new file mode 100644
index 0000000..94189eb
--- /dev/null
+++ b/src/traced/probes/android_game_intervention_list/android_game_intervention_list_data_source.h
@@ -0,0 +1,76 @@
+/*
+ * 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_TRACED_PROBES_ANDROID_GAME_INTERVENTION_LIST_ANDROID_GAME_INTERVENTION_LIST_DATA_SOURCE_H_
+#define SRC_TRACED_PROBES_ANDROID_GAME_INTERVENTION_LIST_ANDROID_GAME_INTERVENTION_LIST_DATA_SOURCE_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "perfetto/base/task_runner.h"
+#include "perfetto/ext/base/pipe.h"
+#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/ext/tracing/core/basic_types.h"
+
+#include "src/traced/probes/probes_data_source.h"
+
+namespace perfetto {
+
+// forward declaration of protos to be loaded
+namespace protos {
+namespace pbzero {
+class AndroidGameInterventionList;
+class AndroidGameInterventionList_GamePackageInfo;
+} // namespace pbzero
+} // namespace protos
+
+class TraceWriter;
+
+class AndroidGameInterventionListDataSource : public ProbesDataSource {
+ public:
+ static const ProbesDataSource::Descriptor descriptor;
+
+ AndroidGameInterventionListDataSource(
+ const DataSourceConfig& ds_config,
+ TracingSessionID session_id,
+ std::unique_ptr<TraceWriter> trace_writer);
+
+ ~AndroidGameInterventionListDataSource() override;
+
+ // ProbesDataSource implementaion.
+ void Start() override;
+ void Flush(FlushRequestID, std::function<void()> callback) override;
+
+ bool ParseAndroidGameInterventionListStream(
+ protos::pbzero::AndroidGameInterventionList*
+ android_game_intervention_list,
+ const base::ScopedFstream& fs,
+ const std::vector<std::string>& package_name_filter);
+
+ private:
+ bool ParseAndroidGameInterventionListLine(
+ char* line,
+ const std::vector<std::string>& package_name_filter,
+ protos::pbzero::AndroidGameInterventionList* packet);
+
+ std::vector<std::string> package_name_filter_;
+ std::unique_ptr<TraceWriter> trace_writer_;
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACED_PROBES_ANDROID_GAME_INTERVENTION_LIST_ANDROID_GAME_INTERVENTION_LIST_DATA_SOURCE_H_
diff --git a/src/traced/probes/android_game_intervention_list/android_game_intervention_list_unittest.cc b/src/traced/probes/android_game_intervention_list/android_game_intervention_list_unittest.cc
new file mode 100644
index 0000000..7c78384
--- /dev/null
+++ b/src/traced/probes/android_game_intervention_list/android_game_intervention_list_unittest.cc
@@ -0,0 +1,129 @@
+/*
+ * 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/traced/probes/android_game_intervention_list/android_game_intervention_list_data_source.h"
+
+#include <stdio.h>
+
+#include <string>
+#include <vector>
+
+#include "perfetto/ext/base/pipe.h"
+#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "perfetto/tracing/core/data_source_config.h"
+
+#include "protos/perfetto/config/android/android_game_intervention_list_config.gen.h"
+#include "protos/perfetto/trace/android/android_game_intervention_list.gen.h"
+#include "protos/perfetto/trace/android/android_game_intervention_list.pbzero.h"
+
+#include "src/tracing/core/trace_writer_for_testing.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace {
+
+class TestAndroidGameInterventionDataSource
+ : public AndroidGameInterventionListDataSource {
+ public:
+ TestAndroidGameInterventionDataSource(
+ const DataSourceConfig& ds_config,
+ TracingSessionID session_id,
+ std::unique_ptr<TraceWriter> trace_writer)
+ : AndroidGameInterventionListDataSource(ds_config,
+ session_id,
+ std::move(trace_writer)) {}
+};
+
+class AndroidGameInterventionListDataSourceTest : public ::testing::Test {
+ protected:
+ AndroidGameInterventionListDataSourceTest() {}
+
+ void CreateInstance(const DataSourceConfig& config) {
+ auto writer =
+ std::unique_ptr<TraceWriterForTesting>(new TraceWriterForTesting());
+ trace_writer_ = writer.get();
+ data_source_.reset(new TestAndroidGameInterventionDataSource(
+ config, /* id */ 0, std::move(writer)));
+ }
+
+ std::unique_ptr<TestAndroidGameInterventionDataSource> data_source_;
+ TraceWriterForTesting* trace_writer_;
+};
+
+TEST_F(AndroidGameInterventionListDataSourceTest, NonEmptyNameFilter) {
+ static constexpr char kValidInterventionLines[] =
+ "com.test.one 1234 0 2 "
+ "angle=0,scaling=1.0,fps=60\n"
+ "com.test.two 1235 1 3 "
+ "angle=1,scaling=0.6,fps=45\n"
+ "com.test.three 1236 2 3 "
+ "angle=1,scaling=0.85,fps=30 "
+ "2 angle=0,scaling=0.75,fps=120\n";
+
+ CreateInstance(DataSourceConfig());
+
+ auto pipe = base::Pipe::Create();
+ PERFETTO_CHECK(write(pipe.wr.get(), kValidInterventionLines,
+ sizeof(kValidInterventionLines) - 1) ==
+ sizeof(kValidInterventionLines) - 1);
+ pipe.wr.reset();
+ auto file_stream = base::ScopedFstream(fdopen(pipe.rd.get(), "r"));
+ pipe.rd.release();
+
+ protozero::HeapBuffered<protos::pbzero::AndroidGameInterventionList>
+ android_game_intervention_list;
+ std::vector<std::string> name_filter = {"com.test.one", "com.test.three"};
+
+ ASSERT_TRUE(data_source_->ParseAndroidGameInterventionListStream(
+ android_game_intervention_list.get(), file_stream, name_filter));
+ protos::gen::AndroidGameInterventionList parsed;
+ parsed.ParseFromString(android_game_intervention_list.SerializeAsString());
+
+ EXPECT_FALSE(parsed.read_error());
+ EXPECT_FALSE(parsed.parse_error());
+
+ EXPECT_EQ(parsed.game_packages_size(), 2);
+ EXPECT_EQ(parsed.game_packages()[0].name(), "com.test.one");
+ EXPECT_EQ(parsed.game_packages()[0].uid(), 1234ul);
+ EXPECT_EQ(parsed.game_packages()[0].current_mode(), 0u);
+ EXPECT_EQ(parsed.game_packages()[0].game_mode_info_size(), 1);
+ EXPECT_EQ(parsed.game_packages()[0].game_mode_info()[0].mode(), 2u);
+ EXPECT_EQ(parsed.game_packages()[0].game_mode_info()[0].use_angle(), false);
+ EXPECT_EQ(
+ parsed.game_packages()[0].game_mode_info()[0].resolution_downscale(),
+ 1.0f);
+ EXPECT_EQ(parsed.game_packages()[0].game_mode_info()[0].fps(), 60.0f);
+
+ EXPECT_EQ(parsed.game_packages()[1].name(), "com.test.three");
+ EXPECT_EQ(parsed.game_packages()[1].uid(), 1236ul);
+ EXPECT_EQ(parsed.game_packages()[1].current_mode(), 2u);
+ EXPECT_EQ(parsed.game_packages()[1].game_mode_info_size(), 2);
+ EXPECT_EQ(parsed.game_packages()[1].game_mode_info()[0].mode(), 3u);
+ EXPECT_EQ(parsed.game_packages()[1].game_mode_info()[0].use_angle(), true);
+ EXPECT_EQ(
+ parsed.game_packages()[1].game_mode_info()[0].resolution_downscale(),
+ 0.85f);
+ EXPECT_EQ(parsed.game_packages()[1].game_mode_info()[0].fps(), 30.0f);
+ EXPECT_EQ(parsed.game_packages()[1].game_mode_info()[1].mode(), 2u);
+ EXPECT_EQ(parsed.game_packages()[1].game_mode_info()[1].use_angle(), false);
+ EXPECT_EQ(
+ parsed.game_packages()[1].game_mode_info()[1].resolution_downscale(),
+ 0.75f);
+ EXPECT_EQ(parsed.game_packages()[1].game_mode_info()[1].fps(), 120.0f);
+}
+
+} // namespace
+} // namespace perfetto
diff --git a/src/traced/probes/probes_producer.cc b/src/traced/probes/probes_producer.cc
index 8b9fc46..702168d 100644
--- a/src/traced/probes/probes_producer.cc
+++ b/src/traced/probes/probes_producer.cc
@@ -35,6 +35,7 @@
#include "perfetto/tracing/core/forward_decls.h"
#include "perfetto/tracing/core/trace_config.h"
#include "src/android_stats/statsd_logging_helper.h"
+#include "src/traced/probes/android_game_intervention_list/android_game_intervention_list_data_source.h"
#include "src/traced/probes/android_log/android_log_data_source.h"
#include "src/traced/probes/common/cpu_freq_info.h"
#include "src/traced/probes/filesystem/inode_file_data_source.h"
@@ -221,6 +222,17 @@
template <>
std::unique_ptr<ProbesDataSource>
+ProbesProducer::CreateDSInstance<AndroidGameInterventionListDataSource>(
+ TracingSessionID session_id,
+ const DataSourceConfig& config) {
+ auto buffer_id = static_cast<BufferID>(config.target_buffer());
+ return std::unique_ptr<ProbesDataSource>(
+ new AndroidGameInterventionListDataSource(
+ config, session_id, endpoint_->CreateTraceWriter(buffer_id)));
+}
+
+template <>
+std::unique_ptr<ProbesDataSource>
ProbesProducer::CreateDSInstance<SysStatsDataSource>(
TracingSessionID session_id,
const DataSourceConfig& config) {
@@ -281,11 +293,17 @@
}
const DataSourceTraits kAllDataSources[] = {
- Ds<AndroidLogDataSource>(), Ds<AndroidPowerDataSource>(),
- Ds<FtraceDataSource>(), Ds<InitialDisplayStateDataSource>(),
- Ds<InodeFileDataSource>(), Ds<LinuxPowerSysfsDataSource>(),
- Ds<MetatraceDataSource>(), Ds<PackagesListDataSource>(),
- Ds<ProcessStatsDataSource>(), Ds<SysStatsDataSource>(),
+ Ds<AndroidLogDataSource>(),
+ Ds<AndroidPowerDataSource>(),
+ Ds<FtraceDataSource>(),
+ Ds<AndroidGameInterventionListDataSource>(),
+ Ds<InitialDisplayStateDataSource>(),
+ Ds<InodeFileDataSource>(),
+ Ds<LinuxPowerSysfsDataSource>(),
+ Ds<MetatraceDataSource>(),
+ Ds<PackagesListDataSource>(),
+ Ds<ProcessStatsDataSource>(),
+ Ds<SysStatsDataSource>(),
Ds<SystemInfoDataSource>(),
};