summaryrefslogtreecommitdiff
path: root/base/logging.cpp
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-01-22 04:22:18 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-01-22 04:22:18 +0000
commitdd7b0034f18fe2adb98d89bc2d4eeaa7dbd099a2 (patch)
treef7681478921146427edb73e4e70162d18bdfa0b4 /base/logging.cpp
parent5e8b40f3bb00ced5da858e373345795c519e74dc (diff)
parentdaec2f4f88253e2e6c9ac38c1903e9ef0e1c07fe (diff)
Snap for 6152176 from daec2f4f88253e2e6c9ac38c1903e9ef0e1c07fe to rvc-release
Change-Id: Icf074761856709508e65f435e25a8f64aeab708d
Diffstat (limited to 'base/logging.cpp')
-rw-r--r--base/logging.cpp234
1 files changed, 196 insertions, 38 deletions
diff --git a/base/logging.cpp b/base/logging.cpp
index b46abbfe6..508871d8d 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -36,15 +36,16 @@
#include <sys/uio.h>
#endif
+#include <atomic>
#include <iostream>
#include <limits>
#include <mutex>
+#include <optional>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
-// Headers for LogMessage::LogLine.
#include <android/log.h>
#ifdef __ANDROID__
#include <android/set_abort_message.h>
@@ -59,6 +60,8 @@
#include <android-base/strings.h>
#include <android-base/threads.h>
+#include "liblog_symbols.h"
+
namespace android {
namespace base {
@@ -115,11 +118,84 @@ static int OpenKmsg() {
}
#endif
+static LogId log_id_tToLogId(int buffer_id) {
+ switch (buffer_id) {
+ case LOG_ID_MAIN:
+ return MAIN;
+ case LOG_ID_SYSTEM:
+ return SYSTEM;
+ case LOG_ID_RADIO:
+ return RADIO;
+ case LOG_ID_CRASH:
+ return CRASH;
+ case LOG_ID_DEFAULT:
+ default:
+ return DEFAULT;
+ }
+}
+
+static int LogIdTolog_id_t(LogId log_id) {
+ switch (log_id) {
+ case MAIN:
+ return LOG_ID_MAIN;
+ case SYSTEM:
+ return LOG_ID_SYSTEM;
+ case RADIO:
+ return LOG_ID_RADIO;
+ case CRASH:
+ return LOG_ID_CRASH;
+ case DEFAULT:
+ default:
+ return LOG_ID_DEFAULT;
+ }
+}
+
+static LogSeverity PriorityToLogSeverity(int priority) {
+ switch (priority) {
+ case ANDROID_LOG_DEFAULT:
+ return INFO;
+ case ANDROID_LOG_VERBOSE:
+ return VERBOSE;
+ case ANDROID_LOG_DEBUG:
+ return DEBUG;
+ case ANDROID_LOG_INFO:
+ return INFO;
+ case ANDROID_LOG_WARN:
+ return WARNING;
+ case ANDROID_LOG_ERROR:
+ return ERROR;
+ case ANDROID_LOG_FATAL:
+ return FATAL;
+ default:
+ return FATAL;
+ }
+}
+
+static android_LogPriority LogSeverityToPriority(LogSeverity severity) {
+ switch (severity) {
+ case VERBOSE:
+ return ANDROID_LOG_VERBOSE;
+ case DEBUG:
+ return ANDROID_LOG_DEBUG;
+ case INFO:
+ return ANDROID_LOG_INFO;
+ case WARNING:
+ return ANDROID_LOG_WARN;
+ case ERROR:
+ return ANDROID_LOG_ERROR;
+ case FATAL_WITHOUT_ABORT:
+ case FATAL:
+ default:
+ return ANDROID_LOG_FATAL;
+ }
+}
+
static std::mutex& LoggingLock() {
static auto& logging_lock = *new std::mutex();
return logging_lock;
}
+// Only used for Q fallback.
static LogFunction& Logger() {
#ifdef __ANDROID__
static auto& logger = *new LogFunction(LogdLogger());
@@ -129,6 +205,7 @@ static LogFunction& Logger() {
return logger;
}
+// Only used for Q fallback.
static AbortFunction& Aborter() {
static auto& aborter = *new AbortFunction(DefaultAborter);
return aborter;
@@ -158,6 +235,8 @@ void SetDefaultTag(const std::string& tag) {
}
static bool gInitialized = false;
+
+// Only used for Q fallback.
static LogSeverity gMinimumLogSeverity = INFO;
#if defined(__linux__)
@@ -218,8 +297,13 @@ void StderrLogger(LogId, LogSeverity severity, const char* tag, const char* file
static_assert(arraysize(log_characters) - 1 == FATAL + 1,
"Mismatch in size of log_characters and values in LogSeverity");
char severity_char = log_characters[severity];
- fprintf(stderr, "%s %c %s %5d %5" PRIu64 " %s:%u] %s\n", tag ? tag : "nullptr", severity_char,
- timestamp, getpid(), GetThreadId(), file, line, message);
+ if (file != nullptr) {
+ fprintf(stderr, "%s %c %s %5d %5" PRIu64 " %s:%u] %s\n", tag ? tag : "nullptr", severity_char,
+ timestamp, getpid(), GetThreadId(), file, line, message);
+ } else {
+ fprintf(stderr, "%s %c %s %5d %5" PRIu64 " %s\n", tag ? tag : "nullptr", severity_char,
+ timestamp, getpid(), GetThreadId(), message);
+ }
}
void StdioLogger(LogId, LogSeverity severity, const char* /*tag*/, const char* /*file*/,
@@ -248,29 +332,25 @@ LogdLogger::LogdLogger(LogId default_log_id) : default_log_id_(default_log_id) {
void LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag,
const char* file, unsigned int line,
const char* message) {
- static constexpr android_LogPriority kLogSeverityToAndroidLogPriority[] = {
- 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) == FATAL + 1,
- "Mismatch in size of kLogSeverityToAndroidLogPriority and values in LogSeverity");
-
- int priority = kLogSeverityToAndroidLogPriority[severity];
+ android_LogPriority priority = LogSeverityToPriority(severity);
if (id == DEFAULT) {
id = default_log_id_;
}
- static constexpr log_id kLogIdToAndroidLogId[] = {
- LOG_ID_MAX, LOG_ID_MAIN, LOG_ID_SYSTEM,
- };
- static_assert(arraysize(kLogIdToAndroidLogId) == SYSTEM + 1,
- "Mismatch in size of kLogIdToAndroidLogId and values in LogId");
- log_id lg_id = kLogIdToAndroidLogId[id];
+ int lg_id = LogIdTolog_id_t(id);
+
+ char log_message[1024];
+ if (priority == ANDROID_LOG_FATAL && file != nullptr) {
+ snprintf(log_message, sizeof(log_message), "%s:%u] %s", file, line, message);
+ } else {
+ snprintf(log_message, sizeof(log_message), "%s", message);
+ }
- if (priority == ANDROID_LOG_FATAL) {
- __android_log_buf_print(lg_id, priority, tag, "%s:%u] %s", file, line,
- message);
+ static auto& liblog_functions = GetLibLogFunctions();
+ if (liblog_functions) {
+ __android_logger_data logger_data = {sizeof(__android_logger_data), lg_id, priority, tag,
+ static_cast<const char*>(nullptr), 0};
+ liblog_functions->__android_log_logd_logger(&logger_data, log_message);
} else {
__android_log_buf_print(lg_id, priority, tag, "%s", message);
}
@@ -305,27 +385,27 @@ void InitLogging(char* argv[], LogFunction&& logger, AbortFunction&& aborter) {
if (spec.size() == 3 && StartsWith(spec, "*:")) {
switch (spec[2]) {
case 'v':
- gMinimumLogSeverity = VERBOSE;
+ SetMinimumLogSeverity(VERBOSE);
continue;
case 'd':
- gMinimumLogSeverity = DEBUG;
+ SetMinimumLogSeverity(DEBUG);
continue;
case 'i':
- gMinimumLogSeverity = INFO;
+ SetMinimumLogSeverity(INFO);
continue;
case 'w':
- gMinimumLogSeverity = WARNING;
+ SetMinimumLogSeverity(WARNING);
continue;
case 'e':
- gMinimumLogSeverity = ERROR;
+ SetMinimumLogSeverity(ERROR);
continue;
case 'f':
- gMinimumLogSeverity = FATAL_WITHOUT_ABORT;
+ SetMinimumLogSeverity(FATAL_WITHOUT_ABORT);
continue;
// liblog will even suppress FATAL if you say 's' for silent, but that's
// crazy!
case 's':
- gMinimumLogSeverity = FATAL_WITHOUT_ABORT;
+ SetMinimumLogSeverity(FATAL_WITHOUT_ABORT);
continue;
}
}
@@ -335,13 +415,46 @@ void InitLogging(char* argv[], LogFunction&& logger, AbortFunction&& aborter) {
}
void SetLogger(LogFunction&& logger) {
- std::lock_guard<std::mutex> lock(LoggingLock());
- Logger() = std::move(logger);
+ static auto& liblog_functions = GetLibLogFunctions();
+ if (liblog_functions) {
+ // We need to atomically swap the old and new pointers since other threads may be logging.
+ // We know all threads will be using the new logger after __android_log_set_logger() returns,
+ // so we can delete it then.
+ // This leaks one std::function<> per instance of libbase if multiple copies of libbase within a
+ // single process call SetLogger(). That is the same cost as having a static
+ // std::function<>, which is the not-thread-safe alternative.
+ static std::atomic<LogFunction*> logger_function(nullptr);
+ auto* old_logger_function = logger_function.exchange(new LogFunction(logger));
+ liblog_functions->__android_log_set_logger([](const struct __android_logger_data* logger_data,
+ const char* message) {
+ auto log_id = log_id_tToLogId(logger_data->buffer_id);
+ auto severity = PriorityToLogSeverity(logger_data->priority);
+
+ auto& function = *logger_function.load(std::memory_order_acquire);
+ function(log_id, severity, logger_data->tag, logger_data->file, logger_data->line, message);
+ });
+ delete old_logger_function;
+ } else {
+ std::lock_guard<std::mutex> lock(LoggingLock());
+ Logger() = std::move(logger);
+ }
}
void SetAborter(AbortFunction&& aborter) {
- std::lock_guard<std::mutex> lock(LoggingLock());
- Aborter() = std::move(aborter);
+ static auto& liblog_functions = GetLibLogFunctions();
+ if (liblog_functions) {
+ // See the comment in SetLogger().
+ static std::atomic<AbortFunction*> abort_function(nullptr);
+ auto* old_abort_function = abort_function.exchange(new AbortFunction(aborter));
+ __android_log_set_aborter([](const char* abort_message) {
+ auto& function = *abort_function.load(std::memory_order_acquire);
+ function(abort_message);
+ });
+ delete old_abort_function;
+ } else {
+ std::lock_guard<std::mutex> lock(LoggingLock());
+ Aborter() = std::move(aborter);
+ }
}
// This indirection greatly reduces the stack impact of having lots of
@@ -444,7 +557,12 @@ LogMessage::~LogMessage() {
// Abort if necessary.
if (data_->GetSeverity() == FATAL) {
- Aborter()(msg.c_str());
+ static auto& liblog_functions = GetLibLogFunctions();
+ if (liblog_functions) {
+ liblog_functions->__android_log_call_aborter(msg.c_str());
+ } else {
+ Aborter()(msg.c_str());
+ }
}
}
@@ -454,25 +572,65 @@ std::ostream& LogMessage::stream() {
void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity severity, const char* tag,
const char* message) {
+ static auto& liblog_functions = GetLibLogFunctions();
+ auto priority = LogSeverityToPriority(severity);
if (tag == nullptr) {
std::lock_guard<std::recursive_mutex> lock(TagLock());
if (gDefaultTag == nullptr) {
gDefaultTag = new std::string(getprogname());
}
- Logger()(DEFAULT, severity, gDefaultTag->c_str(), file, line, message);
+
+ if (liblog_functions) {
+ __android_logger_data logger_data = {sizeof(__android_logger_data), LOG_ID_DEFAULT, priority,
+ gDefaultTag->c_str(), file, line};
+ __android_log_write_logger_data(&logger_data, message);
+ } else {
+ Logger()(DEFAULT, severity, gDefaultTag->c_str(), file, line, message);
+ }
} else {
- Logger()(DEFAULT, severity, tag, file, line, message);
+ if (liblog_functions) {
+ __android_logger_data logger_data = {
+ sizeof(__android_logger_data), LOG_ID_DEFAULT, priority, tag, file, line};
+ __android_log_write_logger_data(&logger_data, message);
+ } else {
+ Logger()(DEFAULT, severity, tag, file, line, message);
+ }
}
}
LogSeverity GetMinimumLogSeverity() {
+ static auto& liblog_functions = GetLibLogFunctions();
+ if (liblog_functions) {
+ return PriorityToLogSeverity(liblog_functions->__android_log_get_minimum_priority());
+ } else {
return gMinimumLogSeverity;
+ }
+}
+
+bool ShouldLog(LogSeverity severity, const char* tag) {
+ static auto& liblog_functions = GetLibLogFunctions();
+ // Even though we're not using the R liblog functions in this function, if we're running on Q,
+ // we need to fall back to using gMinimumLogSeverity, since __android_log_is_loggable() will not
+ // take into consideration the value from SetMinimumLogSeverity().
+ if (liblog_functions) {
+ // TODO: It is safe to pass nullptr for tag, but it will be better to use the default log tag.
+ int priority = LogSeverityToPriority(severity);
+ return __android_log_is_loggable(priority, tag, ANDROID_LOG_INFO);
+ } else {
+ return severity >= gMinimumLogSeverity;
+ }
}
LogSeverity SetMinimumLogSeverity(LogSeverity new_severity) {
- LogSeverity old_severity = gMinimumLogSeverity;
- gMinimumLogSeverity = new_severity;
- return old_severity;
+ static auto& liblog_functions = GetLibLogFunctions();
+ if (liblog_functions) {
+ auto priority = LogSeverityToPriority(new_severity);
+ return PriorityToLogSeverity(liblog_functions->__android_log_set_minimum_priority(priority));
+ } else {
+ LogSeverity old_severity = gMinimumLogSeverity;
+ gMinimumLogSeverity = new_severity;
+ return old_severity;
+ }
}
ScopedLogSeverity::ScopedLogSeverity(LogSeverity new_severity) {