blob: bac8222ab563f0d0dc4f4cf4d7f99d9efe01a79d [file] [log] [blame]
diff --git a/system/core/liblog/logger_write.c b/system/core/liblog/logger_write.c
index b802ed7..3061862 100644
--- a/system/core/liblog/logger_write.c
+++ b/system/core/liblog/logger_write.c
@@ -31,6 +31,14 @@
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
+#define __REDIRECT_TO_SYSLOGD__
+
+#if defined(__REDIRECT_TO_SYSLOGD__)
+#include <syslog.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#endif
+
#include "config_write.h"
#include "log_portability.h"
#include "logger.h"
@@ -186,8 +194,187 @@ static inline uint32_t get4LE(const uint8_t* src)
return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
}
+#if defined(__REDIRECT_TO_SYSLOGD__)
+static int filterPriAndSysPri (android_LogPriority pri, int *sys_pri)
+{
+ switch (pri) {
+ case ANDROID_LOG_DEBUG:
+ *sys_pri = LOG_DEBUG;
+ return 3;
+ case ANDROID_LOG_INFO:
+ *sys_pri = LOG_INFO;
+ return 4;
+ case ANDROID_LOG_WARN:
+ *sys_pri = LOG_WARNING;
+ return 5;
+ case ANDROID_LOG_ERROR:
+ *sys_pri = LOG_ERR;
+ return 6;
+ case ANDROID_LOG_FATAL:
+ *sys_pri = LOG_CRIT;
+ return 7;
+ case ANDROID_LOG_SILENT:
+ *sys_pri = LOG_EMERG;
+ return 8;
+
+ case ANDROID_LOG_DEFAULT:
+ case ANDROID_LOG_UNKNOWN:
+ default:
+ *sys_pri = LOG_INFO;
+ return 1;
+ }
+}
+
+static char *filterLogId(log_id_t log_id)
+{
+ switch (log_id) {
+ case LOG_ID_MAIN:
+ return "MAIN";
+ case LOG_ID_RADIO :
+ return "RADIO";
+ case LOG_ID_EVENTS:
+ return "EVENT";
+ case LOG_ID_SYSTEM:
+ return "SYSTEM";
+ default:
+ return "UNKOWN";
+ }
+}
+
+/*
+ * Extract an 8-byte value from a byte stream.
+ */
+static inline uint64_t get8LE(const uint8_t* src)
+{
+ uint32_t low, high;
+
+ low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
+ high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
+ return ((long long) high << 32) | (long long) low;
+}
+
+static char filterEvtType(char type, char *buf, void *payload, ssize_t len)
+{
+ switch(type) {
+ case EVENT_TYPE_INT:
+ sprintf(buf, "%d", get4LE(payload));
+ return 'I';
+ case EVENT_TYPE_LONG:
+ sprintf(buf, "%lld", get8LE(payload));
+ return 'L';
+ case EVENT_TYPE_STRING:
+ snprintf(buf, len, "%s", payload);
+ buf[len] = '\0';
+ return 'S';
+ default: /* not support */
+ sprintf(buf, "?");
+ return '?';
+ }
+}
+#endif
+
+
static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
{
+#if defined(__REDIRECT_TO_SYSLOGD__)
+ int ret;
+ size_t totalLen = 0, defaultLen = 512, prefixLen;
+ int write_allocate = 0;
+ int sys_pri = LOG_INFO;
+ char *writeBuf = NULL;
+ char defaultBuf[512];
+ char prefixBuf[128];
+ char *idChar;
+ int priChar;
+
+ // for main, system, radio
+ ssize_t msg_len = 0;
+ int priority = ANDROID_LOG_INFO;
+ char *tag, *msg;
+
+ // for event
+ int32_t etag;
+ char type;
+ void *payload;
+
+ // ------------------------------------------------------------------
+ // get log id
+ idChar = filterLogId(log_id);
+
+#if 0 //disable event logid
+ if(log_id == LOG_ID_EVENTS) { /* event type */
+ if(nr == 2) { // __android_log_bwrite
+ etag = *((int32_t *)vec[0].iov_base);
+ type = EVENT_TYPE_INT;
+ payload = (void *)vec[1].iov_base;
+ msg_len = vec[1].iov_len;
+ } else { // __android_log_btwrite
+ etag = *((int32_t *)vec[0].iov_base);
+ type = *((char *)vec[1].iov_base);
+
+ if(!strcmp(&type, ""))
+ type = EVENT_TYPE_STRING;
+
+ payload = (void *)vec[2].iov_base;
+ msg_len = vec[2].iov_len;
+ }
+
+ // get type char
+ priChar = filterEvtType(type, prefixBuf, payload, msg_len);
+
+ // format prefix (brief format)
+ snprintf(defaultBuf, sizeof(defaultBuf),
+ "<%c>/%c/%d(%5d): %s\n",
+ idChar, priChar, etag, getpid(), prefixBuf);
+ // log to syslog
+ syslog(sys_pri, "%s", defaultBuf);
+ ret = strlen(defaultBuf);
+ }
+ else
+#endif
+ { /* radio, system, main */
+ // get messages and tag from io vector
+ msg_len = vec[2].iov_len;
+ priority = *((int *)vec[0].iov_base);
+ tag = (char *)vec[1].iov_base;
+ msg = (char *)vec[2].iov_base;
+
+ /* disable Android VERBOSE log */
+ if (priority == ANDROID_LOG_VERBOSE) {
+ return -EINVAL;
+ }
+
+ // get priority and logid char
+ priChar = filterPriAndSysPri(priority, &sys_pri);
+
+ // format prefix (brief format)
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
+ "(%5d, %5d),[%s],[%d],[Tag]%s[TAG]: ", getpid(), syscall(SYS_gettid), idChar, priChar, tag);
+
+ // compute size
+ totalLen = prefixLen + msg_len + 1 + 1;
+ if(totalLen <= defaultLen) {
+ writeBuf = defaultBuf;
+ } else {
+ write_allocate = 1;
+ writeBuf = (char *)malloc(totalLen);
+ if(writeBuf == NULL)
+ return 0;
+ }
+
+ // combine final string
+ writeBuf[0] = '\0';
+ strncat(writeBuf, prefixBuf, prefixLen);
+ strncat(writeBuf, msg, msg_len);
+ strcat(writeBuf, "\n");
+
+ // log to syslog
+ syslog(sys_pri, "%s", writeBuf);
+ ret = strlen(writeBuf);
+
+ if(write_allocate) free(writeBuf);
+ }
+#else
struct android_log_transport_write *node;
int ret;
struct timespec ts;
@@ -316,6 +503,7 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
(void)(*node->write)(log_id, &ts, vec, nr);
}
}
+#endif
return ret;
}
@@ -327,6 +515,27 @@ static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
if (write_to_log == __write_to_log_init) {
int ret;
+#if defined(__REDIRECT_TO_SYSLOGD__)
+ // open syslogd
+ if (access("/etc/configs/syslog_split", F_OK) == 0) {
+ switch (log_id) {
+ case LOG_ID_MAIN:
+ openlog("ALOG", 0, LOG_LOCAL0);
+ break;
+ case LOG_ID_SYSTEM:
+ openlog("SLOG", 0, LOG_LOCAL1);
+ break;
+ case LOG_ID_RADIO:
+ openlog("RLOG", 0, LOG_LOCAL2);
+ break;
+ default:
+ openlog("ALOG", 0, LOG_LOCAL0);
+ break;
+ }
+ } else {
+ openlog("ALOG", 0, LOG_USER);
+ }
+#else
ret = __write_to_log_initialize();
if (ret < 0) {
__android_log_unlock();
@@ -335,7 +544,7 @@ static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
}
return ret;
}
-
+#endif
write_to_log = __write_to_log_daemon;
}