| /* |
| * Copyright (c) 2017 rxi |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy |
| * of this software and associated documentation files (the "Software"), to |
| * deal in the Software without restriction, including without limitation the |
| * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
| * sell copies of the Software, and to permit persons to whom the Software is |
| * furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in |
| * all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| * IN THE SOFTWARE. |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <stdarg.h> |
| #include <string.h> |
| #include <time.h> |
| #include <sys/time.h> |
| #ifdef ENABLE_SYSLOG |
| #include <syslog.h> |
| #elif ENABLE_LOGCAT |
| #define LOG_TAG "avs" |
| #include <cutils/log.h> |
| #endif |
| |
| #include "aml_avsync_log.h" |
| |
| static struct { |
| void *udata; |
| log_LockFn lock; |
| FILE *fp; |
| int level; |
| int quiet; |
| } L = {0}; |
| |
| |
| static const char *level_names[] = { |
| "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" |
| }; |
| |
| #ifdef LOG_USE_COLOR |
| static const char *level_colors[] = { |
| "\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m" |
| }; |
| #endif |
| |
| |
| static void lock(void) { |
| if (L.lock) { |
| L.lock(L.udata, 1); |
| } |
| } |
| |
| |
| static void unlock(void) { |
| if (L.lock) { |
| L.lock(L.udata, 0); |
| } |
| } |
| |
| |
| void log_set_udata(void *udata) { |
| L.udata = udata; |
| } |
| |
| |
| void log_set_lock(log_LockFn fn) { |
| L.lock = fn; |
| } |
| |
| |
| void log_set_fp(FILE *fp) { |
| L.fp = fp; |
| } |
| |
| |
| void log_set_level(int level) { |
| L.level = level; |
| } |
| |
| |
| void log_set_quiet(int enable) { |
| L.quiet = enable ? 1 : 0; |
| } |
| |
| |
| void log_log(int level, const char *file, int line, const char *fmt, ...) { |
| if (level < L.level) { |
| return; |
| } |
| |
| /* Acquire lock */ |
| lock(); |
| |
| /* Get current time */ |
| struct timespec tm; |
| long second, usec; |
| |
| clock_gettime( CLOCK_MONOTONIC_RAW, &tm ); |
| second = tm.tv_sec; |
| usec = tm.tv_nsec/1000LL; |
| |
| #if defined(ENABLE_SYSLOG) |
| { |
| va_list args; |
| int l; |
| char content[512]; |
| switch (level) { |
| case AVS_LOG_FATAL: |
| l = LOG_CRIT; |
| break; |
| case AVS_LOG_ERROR: |
| l = LOG_ERR; |
| break; |
| case AVS_LOG_WARN: |
| l = LOG_WARNING; |
| break; |
| case AVS_LOG_INFO: |
| l = LOG_NOTICE; |
| break; |
| case AVS_LOG_DEBUG: |
| l = LOG_INFO; |
| break; |
| case AVS_LOG_TRACE: |
| default: |
| l = LOG_DEBUG; |
| break; |
| } |
| va_start(args, fmt); |
| vsnprintf(content, 512, fmt, args); |
| va_end(args); |
| syslog(l, "[%ld.%06ld]: %-5s %s:%d: %s", second, usec, level_names[level], file, line, content); |
| |
| unlock(); |
| return; |
| } |
| #elif defined(ENABLE_LOGCAT) |
| { |
| va_list args; |
| int l; |
| char content[512]; |
| switch (level) { |
| case AVS_LOG_FATAL: |
| l = ANDROID_LOG_ERROR; |
| break; |
| case AVS_LOG_ERROR: |
| l = ANDROID_LOG_ERROR; |
| break; |
| case AVS_LOG_WARN: |
| l = ANDROID_LOG_WARN; |
| break; |
| case AVS_LOG_INFO: |
| l = ANDROID_LOG_INFO; |
| break; |
| case AVS_LOG_DEBUG: |
| l = ANDROID_LOG_DEBUG; |
| break; |
| case AVS_LOG_TRACE: |
| default: |
| l = ANDROID_LOG_VERBOSE; |
| break; |
| } |
| va_start(args, fmt); |
| vsnprintf(content, 512, fmt, args); |
| va_end(args); |
| LOG_PRI(l, LOG_TAG, "[%ld.%06ld]: %-5s %s:%d: %s", second, usec, level_names[level], file, line, content); |
| |
| unlock(); |
| return; |
| } |
| #endif |
| /* Log to stderr */ |
| if (!L.quiet) { |
| va_list args; |
| #ifdef LOG_USE_COLOR |
| fprintf( |
| stderr, "[%ld.%06ld]: %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ", |
| second, usec, level_colors[level], level_names[level], file, line); |
| #else |
| fprintf(stderr, "[%ld.%06ld]: %-5s %s:%d: ", second, usec, level_names[level], file, line); |
| #endif |
| va_start(args, fmt); |
| vfprintf(stderr, fmt, args); |
| va_end(args); |
| fprintf(stderr, "\n"); |
| fflush(stderr); |
| } |
| |
| /* Log to file */ |
| if (L.fp) { |
| va_list args; |
| fprintf(L.fp, "[%ld.%06ld]: %-5s %s:%d: ", second, usec, level_names[level], file, line); |
| va_start(args, fmt); |
| vfprintf(L.fp, fmt, args); |
| va_end(args); |
| fprintf(L.fp, "\n"); |
| fflush(L.fp); |
| } |
| /* Release lock */ |
| unlock(); |
| } |