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: #ifndef _LIBS_CUTILS_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: #include michael@0: #include 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 LOGV (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 LOGV michael@0: #if LOG_NDEBUG michael@0: #define LOGV(...) ((void)0) michael@0: #else michael@0: #define LOGV(...) ((void)LOG(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 LOGV_IF michael@0: #if LOG_NDEBUG michael@0: #define LOGV_IF(cond, ...) ((void)0) michael@0: #else michael@0: #define LOGV_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)LOG(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 LOGD michael@0: #define LOGD(...) ((void)LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef LOGD_IF michael@0: #define LOGD_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)LOG(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 LOGI michael@0: #define LOGI(...) ((void)LOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef LOGI_IF michael@0: #define LOGI_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)LOG(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 LOGW michael@0: #define LOGW(...) ((void)LOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef LOGW_IF michael@0: #define LOGW_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)LOG(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 LOGE michael@0: #define LOGE(...) ((void)LOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) michael@0: #endif michael@0: michael@0: #ifndef LOGE_IF michael@0: #define LOGE_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)LOG(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_LOGV michael@0: #if LOG_NDEBUG michael@0: #define IF_LOGV() if (false) michael@0: #else michael@0: #define IF_LOGV() IF_LOG(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_LOGD michael@0: #define IF_LOGD() IF_LOG(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_LOGI michael@0: #define IF_LOGI() IF_LOG(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_LOGW michael@0: #define IF_LOGW() IF_LOG(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_LOGE michael@0: #define IF_LOGE() IF_LOG(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: 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: #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: michael@0: #define LOG_ALWAYS_FATAL(...) \ michael@0: ( ((void)android_printAssert(NULL, LOG_TAG, __VA_ARGS__)) ) 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: #define LOG_FATAL_IF(cond, ...) ((void)0) michael@0: #define LOG_FATAL(...) ((void)0) michael@0: michael@0: #else michael@0: michael@0: #define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, __VA_ARGS__) michael@0: #define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__) 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: #define LOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), __VA_ARGS__) michael@0: //#define LOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond) michael@0: michael@0: // --------------------------------------------------------------------- michael@0: michael@0: /* michael@0: * Basic log message macro. michael@0: * michael@0: * Example: michael@0: * LOG(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 LOG michael@0: #define LOG(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_LOG michael@0: #define IF_LOG(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: #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: #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: #define LOG_EVENT_STRING(_tag, _value) \ michael@0: ((void) 0) /* not implemented -- must combine len with string */ 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: #define android_printAssert(cond, tag, fmt...) \ michael@0: __android_log_assert(cond, tag, 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