Merge changes I1bdeffc6,I3e13db97

* changes:
  Perfprofd: Clean up test logging helper
  Perfprofd: Backport elf symbolizer config to ConfigReader
diff --git a/perfprofd/configreader.cc b/perfprofd/configreader.cc
index 4fcd5ce..f8fb3d6 100644
--- a/perfprofd/configreader.cc
+++ b/perfprofd/configreader.cc
@@ -124,6 +124,9 @@
   addUnsignedEntry("collect_charging_state", 1, 0, 1);
   addUnsignedEntry("collect_booting", 1, 0, 1);
   addUnsignedEntry("collect_camera_active", 0, 0, 1);
+
+  // If true, use an ELF symbolizer to on-device symbolize.
+  addUnsignedEntry("use_elf_symbolizer", 1, 0, 1);
 }
 
 void ConfigReader::addUnsignedEntry(const char *key,
@@ -321,5 +324,5 @@
   config->collect_camera_active = getBoolValue("collect_camera_active");
 
   config->process = -1;
-  config->use_elf_symbolizer = true;
+  config->use_elf_symbolizer = getBoolValue("use_elf_symbolizer");
 }
diff --git a/perfprofd/tests/perfprofd_test.cc b/perfprofd/tests/perfprofd_test.cc
index 599bb50..d6a8f21 100644
--- a/perfprofd/tests/perfprofd_test.cc
+++ b/perfprofd/tests/perfprofd_test.cc
@@ -16,7 +16,9 @@
 
 #include <algorithm>
 #include <cctype>
+#include <functional>
 #include <memory>
+#include <mutex>
 #include <regex>
 #include <string>
 
@@ -33,6 +35,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/test_utils.h>
+#include <android-base/thread_annotations.h>
 #include <gtest/gtest.h>
 
 #include "config.h"
@@ -53,32 +56,37 @@
 using android::base::LogId;
 using android::base::LogSeverity;
 
-static std::vector<std::string>* gTestLogMessages = nullptr;
+class TestLogHelper {
+ public:
+  void Install() {
+    using namespace std::placeholders;
+    android::base::SetLogger(
+        std::bind(&TestLogHelper::TestLogFunction, this, _1, _2, _3, _4, _5, _6));
+  }
 
-static void TestLogFunction(LogId log_id ATTRIBUTE_UNUSED,
-                            LogSeverity severity,
-                            const char* tag,
-                            const char* file ATTRIBUTE_UNUSED,
-                            unsigned int line ATTRIBUTE_UNUSED,
-                            const char* message) {
-  constexpr char log_characters[] = "VDIWEFF";
-  char severity_char = log_characters[severity];
-  gTestLogMessages->push_back(android::base::StringPrintf("%c: %s", severity_char, message));
-}
+  std::string JoinTestLog(const char* delimiter) {
+    std::unique_lock<std::mutex> ul(lock_);
+    return android::base::Join(test_log_messages_, delimiter);
+  }
 
-static void InitTestLog() {
-  CHECK(gTestLogMessages == nullptr);
-  gTestLogMessages = new std::vector<std::string>();
-}
-static void ClearTestLog() {
-  CHECK(gTestLogMessages != nullptr);
-  delete gTestLogMessages;
-  gTestLogMessages = nullptr;
-}
-static std::string JoinTestLog(const char* delimiter) {
-  CHECK(gTestLogMessages != nullptr);
-  return android::base::Join(*gTestLogMessages, delimiter);
-}
+ private:
+  void TestLogFunction(LogId log_id ATTRIBUTE_UNUSED,
+                       LogSeverity severity,
+                       const char* tag,
+                       const char* file ATTRIBUTE_UNUSED,
+                       unsigned int line ATTRIBUTE_UNUSED,
+                       const char* message) {
+    std::unique_lock<std::mutex> ul(lock_);
+    constexpr char log_characters[] = "VDIWEFF";
+    char severity_char = log_characters[severity];
+    test_log_messages_.push_back(android::base::StringPrintf("%c: %s", severity_char, message));
+  }
+
+ private:
+  std::mutex lock_;
+
+  std::vector<std::string> test_log_messages_;
+};
 
 }  // namespace
 
@@ -88,57 +96,6 @@
 // Temporary config file that we will emit for the daemon to read
 #define CONFIGFILE "perfprofd.conf"
 
-class PerfProfdTest : public testing::Test {
- protected:
-  void SetUp() override {
-    InitTestLog();
-    android::base::SetLogger(TestLogFunction);
-    create_dirs();
-  }
-
-  void TearDown() override {
-    android::base::SetLogger(android::base::StderrLogger);
-    ClearTestLog();
-
-    // TODO: proper management of test files. For now, use old system() code.
-    if (!HasFailure()) {
-      for (const auto dir : { &dest_dir, &conf_dir }) {
-        std::string cmd("rm -rf ");
-        cmd += *dir;
-        int ret = system(cmd.c_str());
-        CHECK_EQ(0, ret);
-      }
-    } else {
-      std::cerr << "Failed test: conf_dir=" << conf_dir << " dest_dir=" << dest_dir;
-    }
-  }
-
- protected:
-  // test_dir is the directory containing the test executable and
-  // any files associated with the test (will be created by the harness).
-  std::string test_dir;
-
-  // dest_dir is a temporary directory that we're using as the destination directory.
-  // It is backed by temp_dir1.
-  std::string dest_dir;
-
-  // conf_dir is a temporary directory that we're using as the configuration directory.
-  // It is backed by temp_dir2.
-  std::string conf_dir;
-
- private:
-  void create_dirs() {
-    temp_dir1.reset(new TemporaryDir());
-    temp_dir2.reset(new TemporaryDir());
-    dest_dir = temp_dir1->path;
-    conf_dir = temp_dir2->path;
-    test_dir = android::base::Dirname(gExecutableRealpath);
-  }
-
-  std::unique_ptr<TemporaryDir> temp_dir1;
-  std::unique_ptr<TemporaryDir> temp_dir2;
-};
-
 static bool bothWhiteSpace(char lhs, char rhs)
 {
   return (std::isspace(lhs) && std::isspace(rhs));
@@ -195,6 +152,79 @@
 #endif
 }
 
+class PerfProfdTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    test_logger.Install();
+    create_dirs();
+  }
+
+  virtual void TearDown() {
+    android::base::SetLogger(android::base::StderrLogger);
+
+    // TODO: proper management of test files. For now, use old system() code.
+    for (const auto dir : { &dest_dir, &conf_dir }) {
+      std::string cmd("rm -rf ");
+      cmd += *dir;
+      int ret = system(cmd.c_str());
+      CHECK_EQ(0, ret);
+    }
+  }
+
+ protected:
+  //
+  // Check to see if the log messages emitted by the daemon
+  // match the expected result. By default we use a partial
+  // match, e.g. if we see the expected excerpt anywhere in the
+  // result, it's a match (for exact match, set exact to true)
+  //
+  void CompareLogMessages(const std::string& expected,
+                          const char* testpoint,
+                          bool exactMatch = false) {
+     std::string sqexp = squeezeWhite(expected, "expected");
+     std::string sqact = squeezeWhite(test_logger.JoinTestLog(" "), "actual");
+     if (exactMatch) {
+       EXPECT_STREQ(sqexp.c_str(), sqact.c_str());
+     } else {
+       std::size_t foundpos = sqact.find(sqexp);
+       bool wasFound = true;
+       if (foundpos == std::string::npos) {
+         std::cerr << testpoint << ": expected result not found\n";
+         std::cerr << " Actual: \"" << sqact << "\"\n";
+         std::cerr << " Expected: \"" << sqexp << "\"\n";
+         wasFound = false;
+       }
+       EXPECT_TRUE(wasFound);
+     }
+  }
+
+  // test_dir is the directory containing the test executable and
+  // any files associated with the test (will be created by the harness).
+  std::string test_dir;
+
+  // dest_dir is a temporary directory that we're using as the destination directory.
+  // It is backed by temp_dir1.
+  std::string dest_dir;
+
+  // conf_dir is a temporary directory that we're using as the configuration directory.
+  // It is backed by temp_dir2.
+  std::string conf_dir;
+
+  TestLogHelper test_logger;
+
+ private:
+  void create_dirs() {
+    temp_dir1.reset(new TemporaryDir());
+    temp_dir2.reset(new TemporaryDir());
+    dest_dir = temp_dir1->path;
+    conf_dir = temp_dir2->path;
+    test_dir = android::base::Dirname(gExecutableRealpath);
+  }
+
+  std::unique_ptr<TemporaryDir> temp_dir1;
+  std::unique_ptr<TemporaryDir> temp_dir2;
+};
+
 ///
 /// Helper class to kick off a run of the perfprofd daemon with a specific
 /// config file.
@@ -364,34 +394,6 @@
 
 #define RAW_RESULT(x) #x
 
-//
-// Check to see if the log messages emitted by the daemon
-// match the expected result. By default we use a partial
-// match, e.g. if we see the expected excerpt anywhere in the
-// result, it's a match (for exact match, set exact to true)
-//
-static void compareLogMessages(const std::string &actual,
-                               const std::string &expected,
-                               const char *testpoint,
-                               bool exactMatch=false)
-{
-   std::string sqexp = squeezeWhite(expected, "expected");
-   std::string sqact = squeezeWhite(actual, "actual");
-   if (exactMatch) {
-     EXPECT_STREQ(sqexp.c_str(), sqact.c_str());
-   } else {
-     std::size_t foundpos = sqact.find(sqexp);
-     bool wasFound = true;
-     if (foundpos == std::string::npos) {
-       std::cerr << testpoint << ": expected result not found\n";
-       std::cerr << " Actual: \"" << sqact << "\"\n";
-       std::cerr << " Expected: \"" << sqexp << "\"\n";
-       wasFound = false;
-     }
-     EXPECT_TRUE(wasFound);
-   }
-}
-
 TEST_F(PerfProfdTest, TestUtil)
 {
   EXPECT_EQ("", replaceAll("", "", ""));
@@ -432,7 +434,7 @@
                                           );
 
   // check to make sure entire log matches
-  compareLogMessages(JoinTestLog(" "), expected, "MissingGMS");
+  CompareLogMessages(expected, "MissingGMS");
 }
 
 
@@ -468,7 +470,7 @@
       I: profile collection skipped (missing config directory)
                                           );
   // check to make sure log excerpt matches
-  compareLogMessages(JoinTestLog(" "), expected, "MissingOptInSemaphoreFile");
+  CompareLogMessages(expected, "MissingOptInSemaphoreFile");
 }
 
 TEST_F(PerfProfdTest, MissingPerfExecutable)
@@ -505,7 +507,7 @@
       I: profile collection skipped (missing 'perf' executable)
                                           );
   // check to make sure log excerpt matches
-  compareLogMessages(JoinTestLog(" "), expected, "MissingPerfExecutable");
+  CompareLogMessages(expected, "MissingPerfExecutable");
 }
 
 TEST_F(PerfProfdTest, BadPerfRun)
@@ -543,7 +545,7 @@
                                           );
 
   // check to make sure log excerpt matches
-  compareLogMessages(JoinTestLog(" "), expected, "BadPerfRun");
+  CompareLogMessages(expected, "BadPerfRun");
 }
 
 TEST_F(PerfProfdTest, ConfigFileParsing)
@@ -581,7 +583,7 @@
                                           );
 
   // check to make sure log excerpt matches
-  compareLogMessages(JoinTestLog(" "), expected, "ConfigFileParsing");
+  CompareLogMessages(expected, "ConfigFileParsing");
 }
 
 TEST_F(PerfProfdTest, ProfileCollectionAnnotations)
@@ -620,7 +622,7 @@
   // Kick off encoder and check return code
   PROFILE_RESULT result =
       encode_to_proto(input_perf_data, encoded_file_path(dest_dir, 0).c_str(), config, 0, nullptr);
-  ASSERT_EQ(OK_PROFILE_COLLECTION, result) << JoinTestLog(" ");
+  ASSERT_EQ(OK_PROFILE_COLLECTION, result) << test_logger.JoinTestLog(" ");
 
   // Read and decode the resulting perf.data.encoded file
   wireless_android_play_playlog::AndroidPerfProfile encodedProfile;
@@ -861,6 +863,8 @@
   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");
 
   // Create semaphore file
   runner.create_semaphore_file();
@@ -893,7 +897,7 @@
       I: finishing Android Wide Profiling daemon
                                           );
   // check to make sure log excerpt matches
-  compareLogMessages(JoinTestLog(" "), expandVars(expected), "BasicRunWithLivePerf", true);
+  CompareLogMessages(expandVars(expected), "BasicRunWithLivePerf", true);
 }
 
 TEST_F(PerfProfdTest, MultipleRunWithLivePerf)
@@ -912,6 +916,8 @@
   runner.addToConfig("use_fixed_seed=12345678");
   runner.addToConfig("collection_interval=9999");
   runner.addToConfig("sample_duration=2");
+  // Avoid the symbolizer for spurious messages.
+  runner.addToConfig("use_elf_symbolizer=0");
   runner.write_processed_file(1, 2);
 
   // Create semaphore file
@@ -960,7 +966,7 @@
       I: finishing Android Wide Profiling daemon
                                           );
   // check to make sure log excerpt matches
-  compareLogMessages(JoinTestLog(" "), expandVars(expected), "BasicRunWithLivePerf", true);
+  CompareLogMessages(expandVars(expected), "BasicRunWithLivePerf", true);
 }
 
 TEST_F(PerfProfdTest, CallChainRunWithLivePerf)
@@ -980,6 +986,8 @@
   runner.addToConfig("collection_interval=9999");
   runner.addToConfig("stack_profile=1");
   runner.addToConfig("sample_duration=2");
+  // Avoid the symbolizer for spurious messages.
+  runner.addToConfig("use_elf_symbolizer=0");
 
   // Create semaphore file
   runner.create_semaphore_file();
@@ -1012,7 +1020,7 @@
       I: finishing Android Wide Profiling daemon
                                           );
   // check to make sure log excerpt matches
-  compareLogMessages(JoinTestLog(" "), expandVars(expected), "CallChainRunWithLivePerf", true);
+  CompareLogMessages(expandVars(expected), "CallChainRunWithLivePerf", true);
 }
 
 int main(int argc, char **argv) {