ART: Use libbase logging

Move most of our logging infrastructure over to system/core/base.
Retain VLOG.

Using unified Android infrastructure has two main advantages. First,
it reduces the complexity/maintenance burden in ART. Second, it
allows to detach logging for the cases where we do not want or need
a runtime, e.g., dexdump, the disassembler, etc. As a part of the
latter, libbase is also supported for all hosts (including Windows).

From a developer viewpoint, there are minor behavior changes for the
LOG statements (see above), but otherwise usage is the same. Explicit
severity enum items are in the android::base namespace now.

Bug: 31338270
Test: m test-art-host
Change-Id: I5abcb2f45f5b03d49951874c48544f72a283a91b
diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc
index e00e62d..17873b5 100644
--- a/runtime/base/logging.cc
+++ b/runtime/base/logging.cc
@@ -28,6 +28,7 @@
 // Headers for LogMessage::LogLine.
 #ifdef ART_TARGET_ANDROID
 #include "cutils/log.h"
+#include <android/set_abort_message.h>
 #else
 #include <sys/types.h>
 #include <unistd.h>
@@ -39,24 +40,10 @@
 
 unsigned int gAborting = 0;
 
-static LogSeverity gMinimumLogSeverity = INFO;
 static std::unique_ptr<std::string> gCmdLine;
 static std::unique_ptr<std::string> gProgramInvocationName;
 static std::unique_ptr<std::string> gProgramInvocationShortName;
 
-// Print INTERNAL_FATAL messages directly instead of at destruction time. This only works on the
-// host right now: for the device, a stream buf collating output into lines and calling LogLine or
-// lower-level logging is necessary.
-#ifdef ART_TARGET_ANDROID
-static constexpr bool kPrintInternalFatalDirectly = false;
-#else
-static constexpr bool kPrintInternalFatalDirectly = !kIsTargetBuild;
-#endif
-
-static bool PrintDirectly(LogSeverity severity) {
-  return kPrintInternalFatalDirectly && severity == INTERNAL_FATAL;
-}
-
 const char* GetCmdLine() {
   return (gCmdLine.get() != nullptr) ? gCmdLine->c_str() : nullptr;
 }
@@ -70,6 +57,16 @@
                                                         : "art";
 }
 
+NO_RETURN
+static void RuntimeAborter(const char* abort_message) {
+#ifdef __ANDROID__
+  android_set_abort_message(abort_message);
+#else
+  UNUSED(abort_message);
+#endif
+  Runtime::Abort();
+}
+
 void InitLogging(char* argv[]) {
   if (gCmdLine.get() != nullptr) {
     return;
@@ -94,150 +91,14 @@
     // TODO: fall back to /proc/self/cmdline when argv is null on Linux.
     gCmdLine.reset(new std::string("<unset>"));
   }
-  const char* tags = getenv("ANDROID_LOG_TAGS");
-  if (tags == nullptr) {
-    return;
-  }
 
-  std::vector<std::string> specs;
-  Split(tags, ' ', &specs);
-  for (size_t i = 0; i < specs.size(); ++i) {
-    // "tag-pattern:[vdiwefs]"
-    std::string spec(specs[i]);
-    if (spec.size() == 3 && StartsWith(spec, "*:")) {
-      switch (spec[2]) {
-        case 'v':
-          gMinimumLogSeverity = VERBOSE;
-          continue;
-        case 'd':
-          gMinimumLogSeverity = DEBUG;
-          continue;
-        case 'i':
-          gMinimumLogSeverity = INFO;
-          continue;
-        case 'w':
-          gMinimumLogSeverity = WARNING;
-          continue;
-        case 'e':
-          gMinimumLogSeverity = ERROR;
-          continue;
-        case 'f':
-          gMinimumLogSeverity = FATAL;
-          continue;
-        // liblog will even suppress FATAL if you say 's' for silent, but that's crazy!
-        case 's':
-          gMinimumLogSeverity = FATAL;
-          continue;
-      }
-    }
-    LOG(FATAL) << "unsupported '" << spec << "' in ANDROID_LOG_TAGS (" << tags << ")";
-  }
-}
-
-// This indirection greatly reduces the stack impact of having
-// lots of checks/logging in a function.
-class LogMessageData {
- public:
-  LogMessageData(const char* file, unsigned int line, LogSeverity severity, int error)
-      : file_(GetFilenameBase(file)),
-        line_number_(line),
-        severity_(severity),
-        error_(error) {}
-
-  const char * GetFile() const {
-    return file_;
-  }
-
-  unsigned int GetLineNumber() const {
-    return line_number_;
-  }
-
-  LogSeverity GetSeverity() const {
-    return severity_;
-  }
-
-  int GetError() const {
-    return error_;
-  }
-
-  std::ostream& GetBuffer() {
-    return buffer_;
-  }
-
-  std::string ToString() const {
-    return buffer_.str();
-  }
-
- private:
-  std::ostringstream buffer_;
-  const char* const file_;
-  const unsigned int line_number_;
-  const LogSeverity severity_;
-  const int error_;
-
-  static const char* GetFilenameBase(const char* file) {
-    const char* last_slash = strrchr(file, '/');
-    return (last_slash == nullptr) ? file : last_slash + 1;
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(LogMessageData);
-};
-
-
-LogMessage::LogMessage(const char* file, unsigned int line, LogSeverity severity, int error)
-  : data_(new LogMessageData(file, line, severity, error)) {
-  if (PrintDirectly(severity)) {
-    static constexpr char kLogCharacters[] = { 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
-    static_assert(arraysize(kLogCharacters) == static_cast<size_t>(INTERNAL_FATAL) + 1,
-                  "Wrong character array size");
-    stream() << ProgramInvocationShortName() << " " << kLogCharacters[static_cast<size_t>(severity)]
-             << " " << getpid() << " " << ::art::GetTid() << " " << file << ":" <<  line << "]";
-  }
-}
-LogMessage::~LogMessage() {
-  if (PrintDirectly(data_->GetSeverity())) {
-    // Add newline at the end to match the not printing directly behavior.
-    std::cerr << '\n';
-  } else {
-    if (data_->GetSeverity() < gMinimumLogSeverity) {
-      return;  // No need to format something we're not going to output.
-    }
-
-    // Finish constructing the message.
-    if (data_->GetError() != -1) {
-      data_->GetBuffer() << ": " << strerror(data_->GetError());
-    }
-    std::string msg(data_->ToString());
-
-    // Do the actual logging with the lock held.
-    {
-      MutexLock mu(Thread::Current(), *Locks::logging_lock_);
-      if (msg.find('\n') == std::string::npos) {
-        LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(), msg.c_str());
-      } else {
-        msg += '\n';
-        size_t i = 0;
-        while (i < msg.size()) {
-          size_t nl = msg.find('\n', i);
-          msg[nl] = '\0';
-          LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(), &msg[i]);
-          i = nl + 1;
-        }
-      }
-    }
-  }
-
-  // Abort if necessary.
-  if (data_->GetSeverity() == FATAL) {
-    Runtime::Abort();
-  }
-}
-
-std::ostream& LogMessage::stream() {
-  if (PrintDirectly(data_->GetSeverity())) {
-    return std::cerr;
-  }
-  return data_->GetBuffer();
+#ifdef __ANDROID__
+#define INIT_LOGGING_DEFAULT_LOGGER android::base::LogdLogger()
+#else
+#define INIT_LOGGING_DEFAULT_LOGGER android::base::StderrLogger
+#endif
+  android::base::InitLogging(argv, INIT_LOGGING_DEFAULT_LOGGER, RuntimeAborter);
+#undef INIT_LOGGING_DEFAULT_LOGGER
 }
 
 #ifdef ART_TARGET_ANDROID
@@ -245,31 +106,14 @@
   ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
   ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, ANDROID_LOG_FATAL
 };
-static_assert(arraysize(kLogSeverityToAndroidLogPriority) == INTERNAL_FATAL + 1,
+static_assert(arraysize(kLogSeverityToAndroidLogPriority) == ::android::base::FATAL + 1,
               "Mismatch in size of kLogSeverityToAndroidLogPriority and values in LogSeverity");
 #endif
 
-void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity log_severity,
-                         const char* message) {
-#ifdef ART_TARGET_ANDROID
-  const char* tag = ProgramInvocationShortName();
-  int priority = kLogSeverityToAndroidLogPriority[static_cast<size_t>(log_severity)];
-  if (priority == ANDROID_LOG_FATAL) {
-    LOG_PRI(priority, tag, "%s:%u] %s", file, line, message);
-  } else {
-    LOG_PRI(priority, tag, "%s", message);
-  }
-#else
-  static const char* log_characters = "VDIWEFF";
-  CHECK_EQ(strlen(log_characters), INTERNAL_FATAL + 1U);
-  char severity = log_characters[log_severity];
-  fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n",
-          ProgramInvocationShortName(), severity, getpid(), ::art::GetTid(), file, line, message);
-#endif
-}
-
-void LogMessage::LogLineLowStack(const char* file, unsigned int line, LogSeverity log_severity,
-                                 const char* message) {
+void LogHelper::LogLineLowStack(const char* file,
+                                unsigned int line,
+                                LogSeverity log_severity,
+                                const char* message) {
 #ifdef ART_TARGET_ANDROID
   // Use android_writeLog() to avoid stack-based buffers used by android_printLog().
   const char* tag = ProgramInvocationShortName();
@@ -292,8 +136,9 @@
   }
 #else
   static constexpr char kLogCharacters[] = { 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
-  static_assert(arraysize(kLogCharacters) == static_cast<size_t>(INTERNAL_FATAL) + 1,
-                "Wrong character array size");
+  static_assert(
+      arraysize(kLogCharacters) == static_cast<size_t>(::android::base::FATAL) + 1,
+      "Wrong character array size");
 
   const char* program_name = ProgramInvocationShortName();
   TEMP_FAILURE_RETRY(write(STDERR_FILENO, program_name, strlen(program_name)));
@@ -310,13 +155,4 @@
 #endif  // ART_TARGET_ANDROID
 }
 
-ScopedLogSeverity::ScopedLogSeverity(LogSeverity level) {
-  old_ = gMinimumLogSeverity;
-  gMinimumLogSeverity = level;
-}
-
-ScopedLogSeverity::~ScopedLogSeverity() {
-  gMinimumLogSeverity = old_;
-}
-
 }  // namespace art