From c79ac621dbb7e774c90079ee1682857b4b0a2cfa Mon Sep 17 00:00:00 2001 From: Felix Herrmann Date: Fri, 10 Jan 2020 16:03:07 +0100 Subject: android logd forwarder Signed-off-by: Felix Herrmann --- .gitignore | 4 + Android.bp | 30 ++++- src/android/dlt-logd-converter.cpp | 236 +++++++++++++++++++++++++++++++++++++ src/android/dlt-logd-converter.rc | 4 + src/daemon/dlt-daemon.rc | 4 + 5 files changed, 276 insertions(+), 2 deletions(-) create mode 100644 src/android/dlt-logd-converter.cpp create mode 100644 src/android/dlt-logd-converter.rc create mode 100644 src/daemon/dlt-daemon.rc diff --git a/.gitignore b/.gitignore index 4178bd7..9268a3c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,8 @@ include/dlt/dlt_version.h .cproject .settings .idea/ +*~ +*.o +*.out +*.swp cmake-build-debug/ diff --git a/Android.bp b/Android.bp index b50115a..54ef69e 100644 --- a/Android.bp +++ b/Android.bp @@ -52,11 +52,9 @@ cc_binary { name: "dlt-daemon", defaults: ["dlt_defaults"], - /* init_rc: [ "src/daemon/dlt-daemon.rc", ], - */ local_include_dirs: [ "src/daemon", @@ -151,4 +149,32 @@ cc_binary { ], } +cc_binary { + + name: "dlt-logd-converter", + vendor: true, + + srcs: [ + "src/android/dlt-logd-converter.cpp", + ], + init_rc: [ + "src/android/dlt-logd-converter.rc", + ], + + cflags: [ + "-Wall", + "-Wextra", + "-Wpedantic", + "-std=c++14", + + ], + shared_libs: [ + "libdlt", + "liblog", + ], + include_dirs: [ + "system/core/include", + ], +} + // vim: ft=python diff --git a/src/android/dlt-logd-converter.cpp b/src/android/dlt-logd-converter.cpp new file mode 100644 index 0000000..509ea81 --- /dev/null +++ b/src/android/dlt-logd-converter.cpp @@ -0,0 +1,236 @@ +/** + * @licence app begin@ + * Copyright (C) 2019 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * DLT logd converter: Retrieve log entries from logd and forward them to DLT. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * \file: dlt-logd-convert + * For further information see http://www.genivi.org/. + * @licence end@ + */ +#include +#include +#include +#include +#include + +#include +#include + +#include + +DLT_DECLARE_CONTEXT(dlt_ctx_self) +DLT_DECLARE_CONTEXT(dlt_ctx_main) +DLT_DECLARE_CONTEXT(dlt_ctx_rdio) +DLT_DECLARE_CONTEXT(dlt_ctx_evnt) /* Binary Buffer */ +DLT_DECLARE_CONTEXT(dlt_ctx_syst) +DLT_DECLARE_CONTEXT(dlt_ctx_crsh) /* Binary Buffer */ +DLT_DECLARE_CONTEXT(dlt_ctx_stat) /* Binary Buffer */ +DLT_DECLARE_CONTEXT(dlt_ctx_secu) /* Binary Buffer */ +DLT_DECLARE_CONTEXT(dlt_ctx_krnl) + +volatile sig_atomic_t exit_parser_loop = false; + +static inline struct logger *init_logger(struct logger_list *logger_list, log_id_t log_id) +{ + struct logger *logger; + logger = android_logger_open(logger_list, log_id); + if (logger == nullptr) { + DLT_LOG(dlt_ctx_self, DLT_LOG_WARN, DLT_STRING("could not open logd buffer id="), DLT_INT64(log_id)); + } + return logger; +} + +static struct logger_list *init_logger_list(bool skip_binary_buffers) +{ + struct logger_list *logger_list; + logger_list = android_logger_list_alloc(ANDROID_LOG_RDONLY, 0, 0); + if (logger_list == nullptr) { + DLT_LOG(dlt_ctx_self, DLT_LOG_FATAL, DLT_STRING("could not allocate logger list")); + return nullptr; + } + + /** + * logd buffer types are defined in: + * system/core/include/log/android/log.h + */ + init_logger(logger_list, LOG_ID_MAIN); + init_logger(logger_list, LOG_ID_RADIO); + init_logger(logger_list, LOG_ID_SYSTEM); + init_logger(logger_list, LOG_ID_KERNEL); + + if (!skip_binary_buffers) { + init_logger(logger_list, LOG_ID_CRASH); + init_logger(logger_list, LOG_ID_EVENTS); + init_logger(logger_list, LOG_ID_STATS); + init_logger(logger_list, LOG_ID_SECURITY); + } + + return logger_list; +} + +static DltContext *get_log_context_from_log_msg(struct log_msg *log_msg) +{ + switch (log_msg->id()) { + case LOG_ID_MAIN: + return &dlt_ctx_main; + case LOG_ID_RADIO: + return &dlt_ctx_rdio; + case LOG_ID_EVENTS: + return &dlt_ctx_evnt; + case LOG_ID_SYSTEM: + return &dlt_ctx_syst; + case LOG_ID_CRASH: + return &dlt_ctx_crsh; + case LOG_ID_STATS: + return &dlt_ctx_stat; + case LOG_ID_SECURITY: + return &dlt_ctx_secu; + case LOG_ID_KERNEL: + return &dlt_ctx_krnl; + default: + return &dlt_ctx_self; + } +} + +static uint32_t get_timestamp_from_log_msg(struct log_msg *log_msg) +{ + /* in 0.1 ms = 100 us */ + return (uint32_t)log_msg->entry.sec * 10000 + (uint32_t)log_msg->entry.nsec / 100000; +} + +static DltLogLevelType get_log_level_from_log_msg(struct log_msg *log_msg) +{ + android_LogPriority priority = static_cast(log_msg->buf[0]); + switch (priority) { + case ANDROID_LOG_VERBOSE: + return DLT_LOG_VERBOSE; + case ANDROID_LOG_DEBUG: + return DLT_LOG_DEBUG; + case ANDROID_LOG_INFO: + return DLT_LOG_INFO; + case ANDROID_LOG_WARN: + return DLT_LOG_WARN; + case ANDROID_LOG_ERROR: + return DLT_LOG_ERROR; + case ANDROID_LOG_FATAL: + return DLT_LOG_FATAL; + case ANDROID_LOG_SILENT: + return DLT_LOG_OFF; + case ANDROID_LOG_UNKNOWN: + case ANDROID_LOG_DEFAULT: + default: + return DLT_LOG_DEFAULT; + } +} + +void signal_handler(int signal) +{ + (void) signal; + if (signal == SIGTERM) { + exit_parser_loop = true; + } +} + +static int logd_parser_loop(struct logger_list *logger_list) +{ + struct log_msg log_msg; + int ret; + + DLT_LOG(dlt_ctx_self, DLT_LOG_VERBOSE, DLT_STRING("Entering parsing loop")); + + while (!exit_parser_loop) { + ret = android_logger_list_read(logger_list, &log_msg); + if (ret == -EAGAIN || ret == -EINTR) { + if (exit_parser_loop == true) { + break; + } + continue; + } else if (ret == -EINVAL || ret == -ENOMEM || ret == -ENODEV || ret == -EIO) { + DLT_LOG(dlt_ctx_self, DLT_LOG_FATAL, DLT_STRING("Could not cannot retrieve logs, permanent error="), DLT_INT32(ret)); + return ret; + } else if (ret <= 0) { + DLT_LOG(dlt_ctx_self, DLT_LOG_ERROR, DLT_STRING("android_logger_list_read unexpected return="), DLT_INT32(ret)); + return ret; + } + + DltContext *ctx = nullptr; + ctx = get_log_context_from_log_msg(&log_msg); + + DltLogLevelType log_level; + log_level = get_log_level_from_log_msg(&log_msg); + + /* Look into system/core/liblog/logprint.c for buffer format */ + auto tag = log_msg.msg()+1; + auto message = tag+strlen(tag)+1; + + uint32_t ts; + ts = get_timestamp_from_log_msg(&log_msg); + + /* Binary buffers are not supported by DLT_STRING DLT_RAW would need the message length */ + DLT_LOG_TS(*ctx, log_level, ts, + DLT_STRING(tag), + DLT_INT32(log_msg.entry.pid), + DLT_UINT32(log_msg.entry.tid), + DLT_STRING(message)); + } + + DLT_LOG(dlt_ctx_self, DLT_LOG_VERBOSE, DLT_STRING("Exited parsing loop")); + + return EXIT_SUCCESS; +} + +int main(int argc, char *argv[]) +{ + (void) argc; + (void) argv; + + DLT_REGISTER_APP("LOGD", "logd -> dlt adapter"); + DLT_REGISTER_CONTEXT(dlt_ctx_self, "LOGF", "logd retriever"); + DLT_REGISTER_CONTEXT(dlt_ctx_main, "MAIN", "logd type: main"); + DLT_REGISTER_CONTEXT(dlt_ctx_rdio, "RDIO", "logd type: rdio"); + DLT_REGISTER_CONTEXT(dlt_ctx_evnt, "EVNT", "logd type: evnt"); + DLT_REGISTER_CONTEXT(dlt_ctx_syst, "SYST", "logd type: syst"); + DLT_REGISTER_CONTEXT(dlt_ctx_crsh, "CRSH", "logd type: crsh"); + DLT_REGISTER_CONTEXT(dlt_ctx_stat, "STAT", "logd type: stat"); + DLT_REGISTER_CONTEXT(dlt_ctx_secu, "SECU", "logd type: secu"); + DLT_REGISTER_CONTEXT(dlt_ctx_krnl, "KRNL", "logd type: krnl"); + + struct sigaction act; + act.sa_handler = signal_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + sigaction(SIGTERM, &act, 0); + + struct logger_list *logger_list; + /* Binary buffers are currently not supported */ + logger_list = init_logger_list(true); + if (logger_list == nullptr) + return EXIT_FAILURE; + + int ret; + ret = logd_parser_loop(logger_list); /* Main loop */ + + android_logger_list_free(logger_list); + + DLT_UNREGISTER_CONTEXT(dlt_ctx_krnl); + DLT_UNREGISTER_CONTEXT(dlt_ctx_secu); + DLT_UNREGISTER_CONTEXT(dlt_ctx_stat); + DLT_UNREGISTER_CONTEXT(dlt_ctx_crsh); + DLT_UNREGISTER_CONTEXT(dlt_ctx_syst); + DLT_UNREGISTER_CONTEXT(dlt_ctx_evnt); + DLT_UNREGISTER_CONTEXT(dlt_ctx_rdio); + DLT_UNREGISTER_CONTEXT(dlt_ctx_main); + DLT_UNREGISTER_CONTEXT(dlt_ctx_self); + + DLT_UNREGISTER_APP_FLUSH_BUFFERED_LOGS(); + + return ret; +} diff --git a/src/android/dlt-logd-converter.rc b/src/android/dlt-logd-converter.rc new file mode 100644 index 0000000..7e8b0c6 --- /dev/null +++ b/src/android/dlt-logd-converter.rc @@ -0,0 +1,4 @@ +service dlt-logd-converter /vendor/bin/dlt-logd-converter + class late_start + user system + group system diff --git a/src/daemon/dlt-daemon.rc b/src/daemon/dlt-daemon.rc new file mode 100644 index 0000000..7a7bc0e --- /dev/null +++ b/src/daemon/dlt-daemon.rc @@ -0,0 +1,4 @@ +service dlt-daemon /vendor/bin/dlt-daemon + class late_start + user root + group root -- cgit v1.2.1