Move init's kernel logging into libbase.
This will let other stuff (such as adbd and recovery) use it too.
Bug: http://b/28467098
Change-Id: Idab51f438ed3edd6fe65a56c4b396eaff5f3833e
diff --git a/base/logging.cpp b/base/logging.cpp
index 959bb8b..1f47a9f 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-#ifdef _WIN32
+#if defined(_WIN32)
#include <windows.h>
#endif
#include "android-base/logging.h"
+#include <fcntl.h>
#include <libgen.h>
#include <time.h>
@@ -30,6 +31,10 @@
#include <errno.h>
#endif
+#if defined(__linux__)
+#include <sys/uio.h>
+#endif
+
#include <iostream>
#include <limits>
#include <sstream>
@@ -172,10 +177,6 @@
static LogSeverity gMinimumLogSeverity = INFO;
static auto& gProgramInvocationName = *new std::unique_ptr<std::string>();
-LogSeverity GetMinimumLogSeverity() {
- return gMinimumLogSeverity;
-}
-
static const char* ProgramInvocationName() {
if (gProgramInvocationName == nullptr) {
gProgramInvocationName.reset(new std::string(getprogname()));
@@ -184,6 +185,42 @@
return gProgramInvocationName->c_str();
}
+#if defined(__linux__)
+void KernelLogger(android::base::LogId, android::base::LogSeverity severity,
+ const char* tag, const char*, unsigned int, const char* msg) {
+ static constexpr int kLogSeverityToKernelLogLevel[] = {
+ [android::base::VERBOSE] = 7, // KERN_DEBUG (there is no verbose kernel log level)
+ [android::base::DEBUG] = 7, // KERN_DEBUG
+ [android::base::INFO] = 6, // KERN_INFO
+ [android::base::WARNING] = 4, // KERN_WARNING
+ [android::base::ERROR] = 3, // KERN_ERROR
+ [android::base::FATAL] = 2, // KERN_CRIT
+ };
+ static_assert(arraysize(kLogSeverityToKernelLogLevel) == android::base::FATAL + 1,
+ "Mismatch in size of kLogSeverityToKernelLogLevel and values in LogSeverity");
+
+ static int klog_fd = TEMP_FAILURE_RETRY(open("/dev/kmsg", O_WRONLY | O_CLOEXEC));
+ if (klog_fd == -1) return;
+
+ int level = kLogSeverityToKernelLogLevel[severity];
+
+ // The kernel's printk buffer is only 1024 bytes.
+ // TODO: should we automatically break up long lines into multiple lines?
+ // Or we could log but with something like "..." at the end?
+ char buf[1024];
+ size_t size = snprintf(buf, sizeof(buf), "<%d>%s: %s\n", level, tag, msg);
+ if (size > sizeof(buf)) {
+ size = snprintf(buf, sizeof(buf), "<%d>%s: %zu-byte message too long for printk\n",
+ level, tag, size);
+ }
+
+ iovec iov[1];
+ iov[0].iov_base = buf;
+ iov[0].iov_len = size;
+ TEMP_FAILURE_RETRY(writev(klog_fd, iov, 1));
+}
+#endif
+
void StderrLogger(LogId, LogSeverity severity, const char*, const char* file,
unsigned int line, const char* message) {
struct tm now;
@@ -211,28 +248,26 @@
LogdLogger::LogdLogger(LogId default_log_id) : default_log_id_(default_log_id) {
}
-static const android_LogPriority kLogSeverityToAndroidLogPriority[] = {
- ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO,
- ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL,
-};
-static_assert(arraysize(kLogSeverityToAndroidLogPriority) == FATAL + 1,
- "Mismatch in size of kLogSeverityToAndroidLogPriority and values "
- "in LogSeverity");
-
-static const 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");
-
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,
+ };
+ static_assert(arraysize(kLogSeverityToAndroidLogPriority) == FATAL + 1,
+ "Mismatch in size of kLogSeverityToAndroidLogPriority and values in LogSeverity");
+
int priority = kLogSeverityToAndroidLogPriority[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];
if (priority == ANDROID_LOG_FATAL) {
@@ -427,13 +462,22 @@
gLogger(id, severity, tag, file, line, message);
}
-ScopedLogSeverity::ScopedLogSeverity(LogSeverity level) {
- old_ = gMinimumLogSeverity;
- gMinimumLogSeverity = level;
+LogSeverity GetMinimumLogSeverity() {
+ return gMinimumLogSeverity;
+}
+
+LogSeverity SetMinimumLogSeverity(LogSeverity new_severity) {
+ LogSeverity old_severity = gMinimumLogSeverity;
+ gMinimumLogSeverity = new_severity;
+ return old_severity;
+}
+
+ScopedLogSeverity::ScopedLogSeverity(LogSeverity new_severity) {
+ old_ = SetMinimumLogSeverity(new_severity);
}
ScopedLogSeverity::~ScopedLogSeverity() {
- gMinimumLogSeverity = old_;
+ SetMinimumLogSeverity(old_);
}
} // namespace base