michael@0: /* michael@0: * Copyright (C) 2005 The Android Open Source Project michael@0: * michael@0: * Licensed under the Apache License, Version 2.0 (the "License"); michael@0: * you may not use this file except in compliance with the License. michael@0: * You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: michael@0: // michael@0: // C/C++ logging functions. See the logging documentation for API details. michael@0: // michael@0: // We'd like these to be available from C code (in case we import some from michael@0: // somewhere), so this has a C interface. michael@0: // michael@0: // The output will be correct when the log file is shared between multiple michael@0: // threads and/or multiple processes so long as the operating system michael@0: // supports O_APPEND. These calls have mutex-protected data structures michael@0: // and so are NOT reentrant. Do not use LOG in a signal handler. michael@0: // michael@0: #if !defined(_LIBS_CUTILS_LOG_H) && !defined(_LIBS_LOG_LOG_H) michael@0: #define _LIBS_LOG_LOG_H michael@0: #define _LIBS_CUTILS_LOG_H michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #ifdef HAVE_PTHREADS michael@0: #include michael@0: #endif michael@0: #include michael@0: michael@0: #if ANDROID_VERSION >= 19 michael@0: #include michael@0: #include michael@0: #else michael@0: #include michael@0: #include michael@0: #endif michael@0: michael@0: #ifdef __cplusplus michael@0: extern "C" { michael@0: #endif michael@0: michael@0: // --------------------------------------------------------------------- michael@0: michael@0: /* michael@0: * Normally we strip ALOGV (VERBOSE messages) from release builds. michael@0: * You can modify this (for example with "#define LOG_NDEBUG 0" michael@0: * at the top of your source file) to change that behavior. michael@0: */ michael@0: #ifndef LOG_NDEBUG michael@0: #ifdef NDEBUG michael@0: #define LOG_NDEBUG 1 michael@0: #else michael@0: #define LOG_NDEBUG 0 michael@0: #endif michael@0: #endif michael@0: michael@0: /* michael@0: * This is the local tag used for the following simplified michael@0: * logging macros. You can change this preprocessor definition michael@0: * before using the other macros to change the tag. michael@0: */ michael@0: #ifndef LOG_TAG michael@0: #define LOG_TAG NULL michael@0: #endif michael@0: michael@0: // --------------------------------------------------------------------- michael@0: michael@0: /* michael@0: * Simplified macro to send a verbose log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef ALOGV michael@0: #if LOG_NDEBUG michael@0: #define ALOGV(...) ((void)0) michael@0: #else michael@0: #define ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: #endif michael@0: michael@0: #define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) michael@0: michael@0: #ifndef ALOGV_IF michael@0: #if LOG_NDEBUG michael@0: #define ALOGV_IF(cond, ...) ((void)0) michael@0: #else michael@0: #define ALOGV_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: #endif michael@0: michael@0: /* michael@0: * Simplified macro to send a debug log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef ALOGD michael@0: #define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef ALOGD_IF michael@0: #define ALOGD_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: michael@0: /* michael@0: * Simplified macro to send an info log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef ALOGI michael@0: #define ALOGI(...) ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef ALOGI_IF michael@0: #define ALOGI_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: michael@0: /* michael@0: * Simplified macro to send a warning log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef ALOGW michael@0: #define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef ALOGW_IF michael@0: #define ALOGW_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: michael@0: /* michael@0: * Simplified macro to send an error log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef ALOGE michael@0: #define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef ALOGE_IF michael@0: #define ALOGE_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: michael@0: // --------------------------------------------------------------------- michael@0: michael@0: /* michael@0: * Conditional based on whether the current LOG_TAG is enabled at michael@0: * verbose priority. michael@0: */ michael@0: #ifndef IF_ALOGV michael@0: #if LOG_NDEBUG michael@0: #define IF_ALOGV() if (false) michael@0: #else michael@0: #define IF_ALOGV() IF_ALOG(LOG_VERBOSE, LOG_TAG) michael@0: #endif michael@0: #endif michael@0: michael@0: /* michael@0: * Conditional based on whether the current LOG_TAG is enabled at michael@0: * debug priority. michael@0: */ michael@0: #ifndef IF_ALOGD michael@0: #define IF_ALOGD() IF_ALOG(LOG_DEBUG, LOG_TAG) michael@0: #endif michael@0: michael@0: /* michael@0: * Conditional based on whether the current LOG_TAG is enabled at michael@0: * info priority. michael@0: */ michael@0: #ifndef IF_ALOGI michael@0: #define IF_ALOGI() IF_ALOG(LOG_INFO, LOG_TAG) michael@0: #endif michael@0: michael@0: /* michael@0: * Conditional based on whether the current LOG_TAG is enabled at michael@0: * warn priority. michael@0: */ michael@0: #ifndef IF_ALOGW michael@0: #define IF_ALOGW() IF_ALOG(LOG_WARN, LOG_TAG) michael@0: #endif michael@0: michael@0: /* michael@0: * Conditional based on whether the current LOG_TAG is enabled at michael@0: * error priority. michael@0: */ michael@0: #ifndef IF_ALOGE michael@0: #define IF_ALOGE() IF_ALOG(LOG_ERROR, LOG_TAG) michael@0: #endif michael@0: michael@0: michael@0: // --------------------------------------------------------------------- michael@0: michael@0: /* michael@0: * Simplified macro to send a verbose system log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef SLOGV michael@0: #if LOG_NDEBUG michael@0: #define SLOGV(...) ((void)0) michael@0: #else michael@0: #define SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: #endif michael@0: michael@0: #define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) michael@0: michael@0: #ifndef SLOGV_IF michael@0: #if LOG_NDEBUG michael@0: #define SLOGV_IF(cond, ...) ((void)0) michael@0: #else michael@0: #define SLOGV_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: #endif michael@0: michael@0: /* michael@0: * Simplified macro to send a debug system log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef SLOGD michael@0: #define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef SLOGD_IF michael@0: #define SLOGD_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: michael@0: /* michael@0: * Simplified macro to send an info system log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef SLOGI michael@0: #define SLOGI(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef SLOGI_IF michael@0: #define SLOGI_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: michael@0: /* michael@0: * Simplified macro to send a warning system log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef SLOGW michael@0: #define SLOGW(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef SLOGW_IF michael@0: #define SLOGW_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: michael@0: /* michael@0: * Simplified macro to send an error system log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef SLOGE michael@0: #define SLOGE(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef SLOGE_IF michael@0: #define SLOGE_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: michael@0: // --------------------------------------------------------------------- michael@0: michael@0: /* michael@0: * Simplified macro to send a verbose radio log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef RLOGV michael@0: #if LOG_NDEBUG michael@0: #define RLOGV(...) ((void)0) michael@0: #else michael@0: #define RLOGV(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: #endif michael@0: michael@0: #define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) michael@0: michael@0: #ifndef RLOGV_IF michael@0: #if LOG_NDEBUG michael@0: #define RLOGV_IF(cond, ...) ((void)0) michael@0: #else michael@0: #define RLOGV_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: #endif michael@0: michael@0: /* michael@0: * Simplified macro to send a debug radio log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef RLOGD michael@0: #define RLOGD(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef RLOGD_IF michael@0: #define RLOGD_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: michael@0: /* michael@0: * Simplified macro to send an info radio log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef RLOGI michael@0: #define RLOGI(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef RLOGI_IF michael@0: #define RLOGI_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: michael@0: /* michael@0: * Simplified macro to send a warning radio log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef RLOGW michael@0: #define RLOGW(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef RLOGW_IF michael@0: #define RLOGW_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: michael@0: /* michael@0: * Simplified macro to send an error radio log message using the current LOG_TAG. michael@0: */ michael@0: #ifndef RLOGE michael@0: #define RLOGE(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef RLOGE_IF michael@0: #define RLOGE_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: michael@0: michael@0: // --------------------------------------------------------------------- michael@0: michael@0: /* michael@0: * Log a fatal error. If the given condition fails, this stops program michael@0: * execution like a normal assertion, but also generating the given message. michael@0: * It is NOT stripped from release builds. Note that the condition test michael@0: * is -inverted- from the normal assert() semantics. michael@0: */ michael@0: #ifndef LOG_ALWAYS_FATAL_IF michael@0: #define LOG_ALWAYS_FATAL_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: #endif michael@0: michael@0: #ifndef LOG_ALWAYS_FATAL michael@0: #define LOG_ALWAYS_FATAL(...) \ michael@0: ( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) ) michael@0: #endif michael@0: michael@0: /* michael@0: * Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that michael@0: * are stripped out of release builds. michael@0: */ michael@0: #if LOG_NDEBUG michael@0: michael@0: #ifndef LOG_FATAL_IF michael@0: #define LOG_FATAL_IF(cond, ...) ((void)0) michael@0: #endif michael@0: #ifndef LOG_FATAL michael@0: #define LOG_FATAL(...) ((void)0) michael@0: #endif michael@0: michael@0: #else michael@0: michael@0: #ifndef LOG_FATAL_IF michael@0: #define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__) michael@0: #endif michael@0: #ifndef LOG_FATAL michael@0: #define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__) michael@0: #endif michael@0: michael@0: #endif michael@0: michael@0: /* michael@0: * Assertion that generates a log message when the assertion fails. michael@0: * Stripped out of release builds. Uses the current LOG_TAG. michael@0: */ michael@0: #ifndef ALOG_ASSERT michael@0: #define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__) michael@0: //#define ALOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond) michael@0: #endif michael@0: michael@0: // --------------------------------------------------------------------- michael@0: michael@0: /* michael@0: * Basic log message macro. michael@0: * michael@0: * Example: michael@0: * ALOG(LOG_WARN, NULL, "Failed with error %d", errno); michael@0: * michael@0: * The second argument may be NULL or "" to indicate the "global" tag. michael@0: */ michael@0: #ifndef ALOG michael@0: #define ALOG(priority, tag, ...) \ michael@0: LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__) michael@0: #endif michael@0: michael@0: /* michael@0: * Log macro that allows you to specify a number for the priority. michael@0: */ michael@0: #ifndef LOG_PRI michael@0: #define LOG_PRI(priority, tag, ...) \ michael@0: android_printLog(priority, tag, __VA_ARGS__) michael@0: #endif michael@0: michael@0: /* michael@0: * Log macro that allows you to pass in a varargs ("args" is a va_list). michael@0: */ michael@0: #ifndef LOG_PRI_VA michael@0: #define LOG_PRI_VA(priority, tag, fmt, args) \ michael@0: android_vprintLog(priority, NULL, tag, fmt, args) michael@0: #endif michael@0: michael@0: /* michael@0: * Conditional given a desired logging priority and tag. michael@0: */ michael@0: #ifndef IF_ALOG michael@0: #define IF_ALOG(priority, tag) \ michael@0: if (android_testLog(ANDROID_##priority, tag)) michael@0: #endif michael@0: michael@0: // --------------------------------------------------------------------- michael@0: michael@0: /* michael@0: * Event logging. michael@0: */ michael@0: michael@0: /* michael@0: * Event log entry types. These must match up with the declarations in michael@0: * java/android/android/util/EventLog.java. michael@0: */ michael@0: typedef enum { michael@0: EVENT_TYPE_INT = 0, michael@0: EVENT_TYPE_LONG = 1, michael@0: EVENT_TYPE_STRING = 2, michael@0: EVENT_TYPE_LIST = 3, michael@0: } AndroidEventLogType; michael@0: michael@0: michael@0: #ifndef LOG_EVENT_INT michael@0: #define LOG_EVENT_INT(_tag, _value) { \ michael@0: int intBuf = _value; \ michael@0: (void) android_btWriteLog(_tag, EVENT_TYPE_INT, &intBuf, \ michael@0: sizeof(intBuf)); \ michael@0: } michael@0: #endif michael@0: #ifndef LOG_EVENT_LONG michael@0: #define LOG_EVENT_LONG(_tag, _value) { \ michael@0: long long longBuf = _value; \ michael@0: (void) android_btWriteLog(_tag, EVENT_TYPE_LONG, &longBuf, \ michael@0: sizeof(longBuf)); \ michael@0: } michael@0: #endif michael@0: #ifndef LOG_EVENT_STRING michael@0: #define LOG_EVENT_STRING(_tag, _value) \ michael@0: ((void) 0) /* not implemented -- must combine len with string */ michael@0: #endif michael@0: /* TODO: something for LIST */ michael@0: michael@0: /* michael@0: * =========================================================================== michael@0: * michael@0: * The stuff in the rest of this file should not be used directly. michael@0: */ michael@0: michael@0: #define android_printLog(prio, tag, fmt...) \ michael@0: __android_log_print(prio, tag, fmt) michael@0: michael@0: #define android_vprintLog(prio, cond, tag, fmt...) \ michael@0: __android_log_vprint(prio, tag, fmt) michael@0: michael@0: /* XXX Macros to work around syntax errors in places where format string michael@0: * arg is not passed to ALOG_ASSERT, LOG_ALWAYS_FATAL or LOG_ALWAYS_FATAL_IF michael@0: * (happens only in debug builds). michael@0: */ michael@0: michael@0: /* Returns 2nd arg. Used to substitute default value if caller's vararg list michael@0: * is empty. michael@0: */ michael@0: #define __android_second(dummy, second, ...) second michael@0: michael@0: /* If passed multiple args, returns ',' followed by all but 1st arg, otherwise michael@0: * returns nothing. michael@0: */ michael@0: #define __android_rest(first, ...) , ## __VA_ARGS__ michael@0: michael@0: #define android_printAssert(cond, tag, fmt...) \ michael@0: __android_log_assert(cond, tag, \ michael@0: __android_second(0, ## fmt, NULL) __android_rest(fmt)) michael@0: michael@0: #define android_writeLog(prio, tag, text) \ michael@0: __android_log_write(prio, tag, text) michael@0: michael@0: #define android_bWriteLog(tag, payload, len) \ michael@0: __android_log_bwrite(tag, payload, len) michael@0: #define android_btWriteLog(tag, type, payload, len) \ michael@0: __android_log_btwrite(tag, type, payload, len) michael@0: michael@0: // TODO: remove these prototypes and their users michael@0: #define android_testLog(prio, tag) (1) michael@0: #define android_writevLog(vec,num) do{}while(0) michael@0: #define android_write1Log(str,len) do{}while (0) michael@0: #define android_setMinPriority(tag, prio) do{}while(0) michael@0: //#define android_logToCallback(func) do{}while(0) michael@0: #define android_logToFile(tag, file) (0) michael@0: #define android_logToFd(tag, fd) (0) michael@0: michael@0: typedef enum { michael@0: LOG_ID_MAIN = 0, michael@0: LOG_ID_RADIO = 1, michael@0: LOG_ID_EVENTS = 2, michael@0: LOG_ID_SYSTEM = 3, michael@0: michael@0: LOG_ID_MAX michael@0: } log_id_t; michael@0: michael@0: /* michael@0: * Send a simple string to the log. michael@0: */ michael@0: int __android_log_buf_write(int bufID, int prio, const char *tag, const char *text); michael@0: int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...); michael@0: michael@0: michael@0: #ifdef __cplusplus michael@0: } michael@0: #endif michael@0: michael@0: #endif // _LIBS_CUTILS_LOG_H