Perfprofd: Read config proto values

Refactor and add code to translate a config proto to a config
instance.

Bug: 110555909
Test: mmma system/extras/perfprofd
Test: perfprofd_test
Change-Id: I31cc2170a5c898e3fc40a8bbaf25efd32831e0b5
diff --git a/perfprofd/Android.bp b/perfprofd/Android.bp
index ba66a4c..628cff7 100644
--- a/perfprofd/Android.bp
+++ b/perfprofd/Android.bp
@@ -152,6 +152,7 @@
 
     static_libs: [
         "libbase",
+        "libperfprofd_proto_config",
         "libprotobuf-cpp-lite",
         "libsimpleperf_elf_read",
     ],
diff --git a/perfprofd/binder_interface/perfprofd_binder.cc b/perfprofd/binder_interface/perfprofd_binder.cc
index a00ca14..247f66e 100644
--- a/perfprofd/binder_interface/perfprofd_binder.cc
+++ b/perfprofd/binder_interface/perfprofd_binder.cc
@@ -186,39 +186,11 @@
 Status PerfProfdNativeService::StartProfilingProtobuf(ProtoLoaderFn fn) {
   ProfilingConfig proto_config;
   if (!fn(proto_config)) {
-    return binder::Status::fromExceptionCode(2);
+    return binder::Status::fromExceptionCode(2, "Could not read protobuf");
   }
   auto config_fn = [&proto_config](ThreadedConfig& config) {
     config = ThreadedConfig();  // Reset to a default config.
-
-    // Copy proto values.
-#define CHECK_AND_COPY_FROM_PROTO(name)      \
-    if (proto_config.has_ ## name ()) {      \
-      config. name = proto_config. name ();  \
-    }
-    CHECK_AND_COPY_FROM_PROTO(collection_interval_in_s)
-    CHECK_AND_COPY_FROM_PROTO(use_fixed_seed)
-    CHECK_AND_COPY_FROM_PROTO(main_loop_iterations)
-    CHECK_AND_COPY_FROM_PROTO(destination_directory)
-    CHECK_AND_COPY_FROM_PROTO(config_directory)
-    CHECK_AND_COPY_FROM_PROTO(perf_path)
-    CHECK_AND_COPY_FROM_PROTO(sampling_period)
-    CHECK_AND_COPY_FROM_PROTO(sampling_frequency)
-    CHECK_AND_COPY_FROM_PROTO(sample_duration_in_s)
-    CHECK_AND_COPY_FROM_PROTO(only_debug_build)
-    CHECK_AND_COPY_FROM_PROTO(hardwire_cpus)
-    CHECK_AND_COPY_FROM_PROTO(hardwire_cpus_max_duration_in_s)
-    CHECK_AND_COPY_FROM_PROTO(max_unprocessed_profiles)
-    CHECK_AND_COPY_FROM_PROTO(stack_profile)
-    CHECK_AND_COPY_FROM_PROTO(collect_cpu_utilization)
-    CHECK_AND_COPY_FROM_PROTO(collect_charging_state)
-    CHECK_AND_COPY_FROM_PROTO(collect_booting)
-    CHECK_AND_COPY_FROM_PROTO(collect_camera_active)
-    CHECK_AND_COPY_FROM_PROTO(process)
-    CHECK_AND_COPY_FROM_PROTO(use_elf_symbolizer)
-    CHECK_AND_COPY_FROM_PROTO(send_to_dropbox)
-    CHECK_AND_COPY_FROM_PROTO(compress)
-#undef CHECK_AND_COPY_FROM_PROTO
+    ConfigReader::ProtoToConfig(proto_config, &config);
   };
   std::string error_msg;
   if (!StartProfiling(config_fn, &error_msg)) {
diff --git a/perfprofd/configreader.cc b/perfprofd/configreader.cc
index 6f6c717..6485acd 100644
--- a/perfprofd/configreader.cc
+++ b/perfprofd/configreader.cc
@@ -33,6 +33,10 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 
+#include "perfprofd_config.pb.h"
+
+#include "perfprofd_counters.h"
+
 using android::base::StringPrintf;
 
 //
@@ -453,3 +457,57 @@
     config->event_config.push_back(std::move(elem));
   }
 }
+
+void ConfigReader::ProtoToConfig(const android::perfprofd::ProfilingConfig& in, Config* out) {
+  // Copy base proto values.
+#define CHECK_AND_COPY_FROM_PROTO(name)      \
+  if (in.has_ ## name()) {      \
+    out->name = in.name();  \
+  }
+  CHECK_AND_COPY_FROM_PROTO(collection_interval_in_s)
+  CHECK_AND_COPY_FROM_PROTO(use_fixed_seed)
+  CHECK_AND_COPY_FROM_PROTO(main_loop_iterations)
+  CHECK_AND_COPY_FROM_PROTO(destination_directory)
+  CHECK_AND_COPY_FROM_PROTO(config_directory)
+  CHECK_AND_COPY_FROM_PROTO(perf_path)
+  CHECK_AND_COPY_FROM_PROTO(sampling_period)
+  CHECK_AND_COPY_FROM_PROTO(sampling_frequency)
+  CHECK_AND_COPY_FROM_PROTO(sample_duration_in_s)
+  CHECK_AND_COPY_FROM_PROTO(only_debug_build)
+  CHECK_AND_COPY_FROM_PROTO(hardwire_cpus)
+  CHECK_AND_COPY_FROM_PROTO(hardwire_cpus_max_duration_in_s)
+  CHECK_AND_COPY_FROM_PROTO(max_unprocessed_profiles)
+  CHECK_AND_COPY_FROM_PROTO(stack_profile)
+  CHECK_AND_COPY_FROM_PROTO(collect_cpu_utilization)
+  CHECK_AND_COPY_FROM_PROTO(collect_charging_state)
+  CHECK_AND_COPY_FROM_PROTO(collect_booting)
+  CHECK_AND_COPY_FROM_PROTO(collect_camera_active)
+  CHECK_AND_COPY_FROM_PROTO(process)
+  CHECK_AND_COPY_FROM_PROTO(use_elf_symbolizer)
+  CHECK_AND_COPY_FROM_PROTO(send_to_dropbox)
+  CHECK_AND_COPY_FROM_PROTO(compress)
+#undef CHECK_AND_COPY_FROM_PROTO
+
+  // Convert counters.
+  for (const auto& event_config : in.event_config()) {
+    if (event_config.has_counter_set()) {
+      Config::PerfCounterConfigElem config_elem;
+      std::vector<const char*> counters_char = android::perfprofd::GenerateEventsString(
+          event_config.counter_set());
+      if (counters_char.empty()) {
+        LOG(WARNING) << "Could not generate counter names for config element";
+        continue;
+      }
+      config_elem.events.resize(counters_char.size());
+      std::transform(counters_char.begin(),
+                     counters_char.end(),
+                     config_elem.events.begin(),
+                     [](const char* in) -> std::string { return in; });
+      config_elem.group = event_config.has_as_group() ? event_config.as_group() : false;
+      config_elem.sampling_period = event_config.has_sampling_period()
+                                              ? event_config.sampling_period()
+                                                  : 0;
+      out->event_config.push_back(std::move(config_elem));
+    }
+  }
+}
diff --git a/perfprofd/configreader.h b/perfprofd/configreader.h
index 732998a..180e537 100644
--- a/perfprofd/configreader.h
+++ b/perfprofd/configreader.h
@@ -23,6 +23,12 @@
 
 #include "config.h"
 
+namespace android {
+namespace perfprofd {
+class ProfilingConfig;  // Config proto.
+}  // namespace perfprofd
+}  // namespace android
+
 //
 // This table describes the perfprofd config file syntax in terms of
 // key/value pairs.  Values come in two flavors: strings, or unsigned
@@ -55,6 +61,8 @@
 
   void FillConfig(Config* config);
 
+  static void ProtoToConfig(const android::perfprofd::ProfilingConfig& in, Config* out);
+
  private:
   void addUnsignedEntry(const char *key,
                         unsigned default_value,
diff --git a/perfprofd/tests/Android.bp b/perfprofd/tests/Android.bp
index feee844..00b0c8d 100644
--- a/perfprofd/tests/Android.bp
+++ b/perfprofd/tests/Android.bp
@@ -26,6 +26,7 @@
     stl: "libc++",
     static_libs: [
         "libperfprofdcored",
+        "libperfprofd_proto_config",
         "libsimpleperf_elf_read",
         "libbase",
         "libutils",