Perfprofd: Add general event config to perf invoke

Add code to the perf invoke to handle event sets in the configuration.
Add a simple live test.

Bug: 110555909
Test: mmma system/extras/perfprofd
Test: perfprofd_test
Change-Id: Iaf6eca63638ee3295328def81a0db286942c491b
diff --git a/perfprofd/perfprofd_perf.cc b/perfprofd/perfprofd_perf.cc
index 0e7b595..2ba59d4 100644
--- a/perfprofd/perfprofd_perf.cc
+++ b/perfprofd/perfprofd_perf.cc
@@ -33,6 +33,7 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 
 #include "config.h"
 
@@ -75,6 +76,23 @@
       add(android::base::StringPrintf("%u", config.sampling_period));
     }
 
+    if (!config.event_config.empty()) {
+      for (const auto& event_set : config.event_config) {
+        if (event_set.events.empty()) {
+          LOG(WARNING) << "Unexpected empty event set";
+          continue;
+        }
+
+        if (event_set.sampling_period > 0) {
+          add("-c");
+          add(std::to_string(event_set.sampling_period));
+        }
+        add(event_set.group ? "--group" : "-e");
+
+        add(android::base::Join(event_set.events, ','));
+      }
+    }
+
     // -g if desired
     if (stack_profile_opt != nullptr) {
       add(stack_profile_opt);
diff --git a/perfprofd/tests/perfprofd_test.cc b/perfprofd/tests/perfprofd_test.cc
index 0d72c90..467bea4 100644
--- a/perfprofd/tests/perfprofd_test.cc
+++ b/perfprofd/tests/perfprofd_test.cc
@@ -1189,6 +1189,130 @@
   EXPECT_TRUE(CompareLogMessages(expandVars(expected), true));
 }
 
+TEST_F(PerfProfdTest, BasicRunWithLivePerf_Events)
+{
+  //
+  // Basic test to check that the event set functionality works.
+  //
+  // Note: this is brittle, as we do not really know which events the hardware
+  //       supports. Use "cpu-cycles" and "page-faults" as something likely.
+  //
+  PerfProfdRunner runner(conf_dir);
+  runner.addToConfig("only_debug_build=0");
+  std::string ddparam("destination_directory="); ddparam += dest_dir;
+  runner.addToConfig(ddparam);
+  std::string cfparam("config_directory="); cfparam += conf_dir;
+  runner.addToConfig(cfparam);
+  runner.addToConfig("main_loop_iterations=1");
+  runner.addToConfig("use_fixed_seed=12345678");
+  runner.addToConfig("max_unprocessed_profiles=100");
+  runner.addToConfig("collection_interval=9999");
+  runner.addToConfig("sample_duration=2");
+  // Avoid the symbolizer for spurious messages.
+  runner.addToConfig("use_elf_symbolizer=0");
+
+  // Disable compression.
+  runner.addToConfig("compress=0");
+
+  // Set event set.
+  runner.addToConfig("-e_cpu-cycles,page-faults@100000=dummy");
+
+  // Create semaphore file
+  runner.create_semaphore_file();
+
+  // Kick off daemon
+  int daemon_main_return_code = runner.invoke();
+
+  // Check return code from daemon
+  ASSERT_EQ(0, daemon_main_return_code);
+
+  // Read and decode the resulting perf.data.encoded file
+  android::perfprofd::PerfprofdRecord encodedProfile;
+  readEncodedProfile(dest_dir, false, encodedProfile);
+
+  // Examine what we get back. Since it's a live profile, we can't
+  // really do much in terms of verifying the contents.
+  EXPECT_LT(0, encodedProfile.events_size());
+
+  // Verify log contents
+  const std::string expected = std::string(
+      "I: starting Android Wide Profiling daemon ") +
+      "I: config file path set to " + conf_dir + "/perfprofd.conf " +
+      RAW_RESULT(
+      I: random seed set to 12345678
+      I: sleep 674 seconds
+      I: initiating profile collection
+      I: sleep 2 seconds
+      I: profile collection complete
+      I: sleep 9325 seconds
+      I: finishing Android Wide Profiling daemon
+                                          );
+  // check to make sure log excerpt matches
+  EXPECT_TRUE(CompareLogMessages(expandVars(expected), true));
+}
+
+TEST_F(PerfProfdTest, BasicRunWithLivePerf_EventsGroup)
+{
+  //
+  // Basic test to check that the event set functionality works.
+  //
+  // Note: this is brittle, as we do not really know which events the hardware
+  //       supports. Use "cpu-cycles" and "page-faults" as something likely.
+  //
+  PerfProfdRunner runner(conf_dir);
+  runner.addToConfig("only_debug_build=0");
+  std::string ddparam("destination_directory="); ddparam += dest_dir;
+  runner.addToConfig(ddparam);
+  std::string cfparam("config_directory="); cfparam += conf_dir;
+  runner.addToConfig(cfparam);
+  runner.addToConfig("main_loop_iterations=1");
+  runner.addToConfig("use_fixed_seed=12345678");
+  runner.addToConfig("max_unprocessed_profiles=100");
+  runner.addToConfig("collection_interval=9999");
+  runner.addToConfig("sample_duration=2");
+  // Avoid the symbolizer for spurious messages.
+  runner.addToConfig("use_elf_symbolizer=0");
+
+  // Disable compression.
+  runner.addToConfig("compress=0");
+
+  // Set event set.
+  runner.addToConfig("-g_cpu-cycles,page-faults@100000=dummy");
+
+  // Create semaphore file
+  runner.create_semaphore_file();
+
+  // Kick off daemon
+  int daemon_main_return_code = runner.invoke();
+
+  // Check return code from daemon
+  ASSERT_EQ(0, daemon_main_return_code);
+
+  // Read and decode the resulting perf.data.encoded file
+  android::perfprofd::PerfprofdRecord encodedProfile;
+  readEncodedProfile(dest_dir, false, encodedProfile);
+
+  // Examine what we get back. Since it's a live profile, we can't
+  // really do much in terms of verifying the contents.
+  EXPECT_LT(0, encodedProfile.events_size());
+
+  // Verify log contents
+  const std::string expected = std::string(
+      "I: starting Android Wide Profiling daemon ") +
+      "I: config file path set to " + conf_dir + "/perfprofd.conf " +
+      RAW_RESULT(
+      I: random seed set to 12345678
+      I: sleep 674 seconds
+      I: initiating profile collection
+      I: sleep 2 seconds
+      I: profile collection complete
+      I: sleep 9325 seconds
+      I: finishing Android Wide Profiling daemon
+                                          );
+  // check to make sure log excerpt matches
+  EXPECT_TRUE(CompareLogMessages(expandVars(expected), true));
+}
+
 TEST_F(PerfProfdTest, MultipleRunWithLivePerf)
 {
   //