/* * Copyright (C) 2005-2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _LIBS_LOG_LOG_H #define _LIBS_LOG_LOG_H /* Too many in the ecosystem assume these are included */ #if !defined(_WIN32) #include #endif #include /* uint16_t, int32_t */ #include #include #include #include #include #include /* helper to define iovec for portability */ #ifdef __cplusplus extern "C" { #endif /* * LOG_TAG is the local tag used for the following simplified * logging macros. You can change this preprocessor definition * before using the other macros to change the tag. */ #ifndef LOG_TAG #define LOG_TAG NULL #endif /* --------------------------------------------------------------------- */ /* * This file uses ", ## __VA_ARGS__" zero-argument token pasting to * work around issues with debug-only syntax errors in assertions * that are missing format strings. See commit * 19299904343daf191267564fe32e6cd5c165cd42 */ #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" #endif /* * Send a simple string to the log. */ int __android_log_buf_write(int bufID, int prio, const char* tag, const char* text); int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...) #if defined(__GNUC__) __attribute__((__format__(printf, 4, 5))) #endif ; /* * Simplified macro to send a verbose system log message using current LOG_TAG. */ #ifndef SLOGV #define __SLOGV(...) \ ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) #if LOG_NDEBUG #define SLOGV(...) do { if (0) { __SLOGV(__VA_ARGS__); } } while (0) #else #define SLOGV(...) __SLOGV(__VA_ARGS__) #endif #endif #ifndef SLOGV_IF #if LOG_NDEBUG #define SLOGV_IF(cond, ...) ((void)0) #else #define SLOGV_IF(cond, ...) \ ( (__predict_false(cond)) \ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ : (void)0 ) #endif #endif /* * Simplified macro to send a debug system log message using current LOG_TAG. */ #ifndef SLOGD #define SLOGD(...) \ ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) #endif #ifndef SLOGD_IF #define SLOGD_IF(cond, ...) \ ( (__predict_false(cond)) \ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ : (void)0 ) #endif /* * Simplified macro to send an info system log message using current LOG_TAG. */ #ifndef SLOGI #define SLOGI(...) \ ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) #endif #ifndef SLOGI_IF #define SLOGI_IF(cond, ...) \ ( (__predict_false(cond)) \ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ : (void)0 ) #endif /* * Simplified macro to send a warning system log message using current LOG_TAG. */ #ifndef SLOGW #define SLOGW(...) \ ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) #endif #ifndef SLOGW_IF #define SLOGW_IF(cond, ...) \ ( (__predict_false(cond)) \ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ : (void)0 ) #endif /* * Simplified macro to send an error system log message using current LOG_TAG. */ #ifndef SLOGE #define SLOGE(...) \ ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) #endif #ifndef SLOGE_IF #define SLOGE_IF(cond, ...) \ ( (__predict_false(cond)) \ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ : (void)0 ) #endif /* --------------------------------------------------------------------- */ /* * Simplified macro to send a verbose radio log message using current LOG_TAG. */ #ifndef RLOGV #define __RLOGV(...) \ ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) #if LOG_NDEBUG #define RLOGV(...) do { if (0) { __RLOGV(__VA_ARGS__); } } while (0) #else #define RLOGV(...) __RLOGV(__VA_ARGS__) #endif #endif #ifndef RLOGV_IF #if LOG_NDEBUG #define RLOGV_IF(cond, ...) ((void)0) #else #define RLOGV_IF(cond, ...) \ ( (__predict_false(cond)) \ ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ : (void)0 ) #endif #endif /* * Simplified macro to send a debug radio log message using current LOG_TAG. */ #ifndef RLOGD #define RLOGD(...) \ ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) #endif #ifndef RLOGD_IF #define RLOGD_IF(cond, ...) \ ( (__predict_false(cond)) \ ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ : (void)0 ) #endif /* * Simplified macro to send an info radio log message using current LOG_TAG. */ #ifndef RLOGI #define RLOGI(...) \ ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) #endif #ifndef RLOGI_IF #define RLOGI_IF(cond, ...) \ ( (__predict_false(cond)) \ ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ : (void)0 ) #endif /* * Simplified macro to send a warning radio log message using current LOG_TAG. */ #ifndef RLOGW #define RLOGW(...) \ ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) #endif #ifndef RLOGW_IF #define RLOGW_IF(cond, ...) \ ( (__predict_false(cond)) \ ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ : (void)0 ) #endif /* * Simplified macro to send an error radio log message using current LOG_TAG. */ #ifndef RLOGE #define RLOGE(...) \ ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) #endif #ifndef RLOGE_IF #define RLOGE_IF(cond, ...) \ ( (__predict_false(cond)) \ ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ : (void)0 ) #endif /* --------------------------------------------------------------------- */ /* * Event logging. */ /* * The following should not be used directly. */ int __android_log_bwrite(int32_t tag, const void* payload, size_t len); int __android_log_btwrite(int32_t tag, char type, const void* payload, size_t len); int __android_log_bswrite(int32_t tag, const char* payload); #define android_bWriteLog(tag, payload, len) \ __android_log_bwrite(tag, payload, len) #define android_btWriteLog(tag, type, payload, len) \ __android_log_btwrite(tag, type, payload, len) /* * Event log entry types. */ #ifndef __AndroidEventLogType_defined #define __AndroidEventLogType_defined typedef enum { /* Special markers for android_log_list_element type */ EVENT_TYPE_LIST_STOP = '\n', /* declare end of list */ EVENT_TYPE_UNKNOWN = '?', /* protocol error */ /* must match with declaration in java/android/android/util/EventLog.java */ EVENT_TYPE_INT = 0, /* int32_t */ EVENT_TYPE_LONG = 1, /* int64_t */ EVENT_TYPE_STRING = 2, EVENT_TYPE_LIST = 3, EVENT_TYPE_FLOAT = 4, } AndroidEventLogType; #endif #define sizeof_AndroidEventLogType sizeof(typeof_AndroidEventLogType) #define typeof_AndroidEventLogType unsigned char #ifndef LOG_EVENT_INT #define LOG_EVENT_INT(_tag, _value) { \ int intBuf = _value; \ (void) android_btWriteLog(_tag, EVENT_TYPE_INT, &intBuf, \ sizeof(intBuf)); \ } #endif #ifndef LOG_EVENT_LONG #define LOG_EVENT_LONG(_tag, _value) { \ long long longBuf = _value; \ (void) android_btWriteLog(_tag, EVENT_TYPE_LONG, &longBuf, \ sizeof(longBuf)); \ } #endif #ifndef LOG_EVENT_FLOAT #define LOG_EVENT_FLOAT(_tag, _value) { \ float floatBuf = _value; \ (void) android_btWriteLog(_tag, EVENT_TYPE_FLOAT, &floatBuf, \ sizeof(floatBuf)); \ } #endif #ifndef LOG_EVENT_STRING #define LOG_EVENT_STRING(_tag, _value) \ (void) __android_log_bswrite(_tag, _value); #endif #ifndef log_id_t_defined #define log_id_t_defined typedef enum log_id { LOG_ID_MIN = 0, LOG_ID_MAIN = 0, LOG_ID_RADIO = 1, LOG_ID_EVENTS = 2, LOG_ID_SYSTEM = 3, LOG_ID_CRASH = 4, LOG_ID_SECURITY = 5, LOG_ID_KERNEL = 6, /* place last, third-parties can not use it */ LOG_ID_MAX } log_id_t; #endif #define sizeof_log_id_t sizeof(typeof_log_id_t) #define typeof_log_id_t unsigned char /* --------------------------------------------------------------------- */ /* * Native log reading interface section. See logcat for sample code. * * The preferred API is an exec of logcat. Likely uses of this interface * are if native code suffers from exec or filtration being too costly, * access to raw information, or parsing is an issue. */ /* * The userspace structure for version 1 of the logger_entry ABI. */ #ifndef __struct_logger_entry_defined #define __struct_logger_entry_defined struct logger_entry { uint16_t len; /* length of the payload */ uint16_t __pad; /* no matter what, we get 2 bytes of padding */ int32_t pid; /* generating process's pid */ int32_t tid; /* generating process's tid */ int32_t sec; /* seconds since Epoch */ int32_t nsec; /* nanoseconds */ #ifndef __cplusplus char msg[0]; /* the entry's payload */ #endif }; #endif /* * The userspace structure for version 2 of the logger_entry ABI. */ #ifndef __struct_logger_entry_v2_defined #define __struct_logger_entry_v2_defined struct logger_entry_v2 { uint16_t len; /* length of the payload */ uint16_t hdr_size; /* sizeof(struct logger_entry_v2) */ int32_t pid; /* generating process's pid */ int32_t tid; /* generating process's tid */ int32_t sec; /* seconds since Epoch */ int32_t nsec; /* nanoseconds */ uint32_t euid; /* effective UID of logger */ #ifndef __cplusplus char msg[0]; /* the entry's payload */ #endif } __attribute__((__packed__)); #endif /* * The userspace structure for version 3 of the logger_entry ABI. */ #ifndef __struct_logger_entry_v3_defined #define __struct_logger_entry_v3_defined struct logger_entry_v3 { uint16_t len; /* length of the payload */ uint16_t hdr_size; /* sizeof(struct logger_entry_v3) */ int32_t pid; /* generating process's pid */ int32_t tid; /* generating process's tid */ int32_t sec; /* seconds since Epoch */ int32_t nsec; /* nanoseconds */ uint32_t lid; /* log id of the payload */ #ifndef __cplusplus char msg[0]; /* the entry's payload */ #endif } __attribute__((__packed__)); #endif /* * The userspace structure for version 4 of the logger_entry ABI. */ #ifndef __struct_logger_entry_v4_defined #define __struct_logger_entry_v4_defined struct logger_entry_v4 { uint16_t len; /* length of the payload */ uint16_t hdr_size; /* sizeof(struct logger_entry_v4) */ int32_t pid; /* generating process's pid */ uint32_t tid; /* generating process's tid */ uint32_t sec; /* seconds since Epoch */ uint32_t nsec; /* nanoseconds */ uint32_t lid; /* log id of the payload, bottom 4 bits currently */ uint32_t uid; /* generating process's uid */ #ifndef __cplusplus char msg[0]; /* the entry's payload */ #endif }; #endif /* struct log_time is a wire-format variant of struct timespec */ #define NS_PER_SEC 1000000000ULL #ifndef __struct_log_time_defined #define __struct_log_time_defined #ifdef __cplusplus /* * NB: we did NOT define a copy constructor. This will result in structure * no longer being compatible with pass-by-value which is desired * efficient behavior. Also, pass-by-reference breaks C/C++ ABI. */ struct log_time { public: uint32_t tv_sec; /* good to Feb 5 2106 */ uint32_t tv_nsec; static const uint32_t tv_sec_max = 0xFFFFFFFFUL; static const uint32_t tv_nsec_max = 999999999UL; log_time(const timespec& T) { tv_sec = static_cast(T.tv_sec); tv_nsec = static_cast(T.tv_nsec); } log_time(uint32_t sec, uint32_t nsec) { tv_sec = sec; tv_nsec = nsec; } #ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_ #define __struct_log_time_private_defined static const timespec EPOCH; #endif log_time() { } #ifdef __linux__ log_time(clockid_t id) { timespec T; clock_gettime(id, &T); tv_sec = static_cast(T.tv_sec); tv_nsec = static_cast(T.tv_nsec); } #endif log_time(const char* T) { const uint8_t* c = reinterpret_cast(T); tv_sec = c[0] | (static_cast(c[1]) << 8) | (static_cast(c[2]) << 16) | (static_cast(c[3]) << 24); tv_nsec = c[4] | (static_cast(c[5]) << 8) | (static_cast(c[6]) << 16) | (static_cast(c[7]) << 24); } /* timespec */ bool operator== (const timespec& T) const { return (tv_sec == static_cast(T.tv_sec)) && (tv_nsec == static_cast(T.tv_nsec)); } bool operator!= (const timespec& T) const { return !(*this == T); } bool operator< (const timespec& T) const { return (tv_sec < static_cast(T.tv_sec)) || ((tv_sec == static_cast(T.tv_sec)) && (tv_nsec < static_cast(T.tv_nsec))); } bool operator>= (const timespec& T) const { return !(*this < T); } bool operator> (const timespec& T) const { return (tv_sec > static_cast(T.tv_sec)) || ((tv_sec == static_cast(T.tv_sec)) && (tv_nsec > static_cast(T.tv_nsec))); } bool operator<= (const timespec& T) const { return !(*this > T); } #ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_ log_time operator-= (const timespec& T); log_time operator- (const timespec& T) const { log_time local(*this); return local -= T; } log_time operator+= (const timespec& T); log_time operator+ (const timespec& T) const { log_time local(*this); return local += T; } #endif /* log_time */ bool operator== (const log_time& T) const { return (tv_sec == T.tv_sec) && (tv_nsec == T.tv_nsec); } bool operator!= (const log_time& T) const { return !(*this == T); } bool operator< (const log_time& T) const { return (tv_sec < T.tv_sec) || ((tv_sec == T.tv_sec) && (tv_nsec < T.tv_nsec)); } bool operator>= (const log_time& T) const { return !(*this < T); } bool operator> (const log_time& T) const { return (tv_sec > T.tv_sec) || ((tv_sec == T.tv_sec) && (tv_nsec > T.tv_nsec)); } bool operator<= (const log_time& T) const { return !(*this > T); } #ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_ log_time operator-= (const log_time& T); log_time operator- (const log_time& T) const { log_time local(*this); return local -= T; } log_time operator+= (const log_time& T); log_time operator+ (const log_time& T) const { log_time local(*this); return local += T; } #endif uint64_t nsec() const { return static_cast(tv_sec) * NS_PER_SEC + tv_nsec; } #ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_ static const char default_format[]; /* Add %#q for the fraction of a second to the standard library functions */ char* strptime(const char* s, const char* format = default_format); #endif } __attribute__((__packed__)); #else typedef struct log_time { uint32_t tv_sec; uint32_t tv_nsec; } __attribute__((__packed__)) log_time; #endif #endif /* * The maximum size of the log entry payload that can be * written to the logger. An attempt to write more than * this amount will result in a truncated log entry. */ #define LOGGER_ENTRY_MAX_PAYLOAD 4068 /* * The maximum size of a log entry which can be read from the * kernel logger driver. An attempt to read less than this amount * may result in read() returning EINVAL. */ #define LOGGER_ENTRY_MAX_LEN (5*1024) #ifndef __struct_log_msg_defined #define __struct_log_msg_defined struct log_msg { union { unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1]; struct logger_entry_v4 entry; struct logger_entry_v4 entry_v4; struct logger_entry_v3 entry_v3; struct logger_entry_v2 entry_v2; struct logger_entry entry_v1; } __attribute__((aligned(4))); #ifdef __cplusplus /* Matching log_time operators */ bool operator== (const log_msg& T) const { return (entry.sec == T.entry.sec) && (entry.nsec == T.entry.nsec); } bool operator!= (const log_msg& T) const { return !(*this == T); } bool operator< (const log_msg& T) const { return (entry.sec < T.entry.sec) || ((entry.sec == T.entry.sec) && (entry.nsec < T.entry.nsec)); } bool operator>= (const log_msg& T) const { return !(*this < T); } bool operator> (const log_msg& T) const { return (entry.sec > T.entry.sec) || ((entry.sec == T.entry.sec) && (entry.nsec > T.entry.nsec)); } bool operator<= (const log_msg& T) const { return !(*this > T); } uint64_t nsec() const { return static_cast(entry.sec) * NS_PER_SEC + entry.nsec; } /* packet methods */ log_id_t id() { return static_cast(entry.lid); } char* msg() { unsigned short hdr_size = entry.hdr_size; if (!hdr_size) { hdr_size = sizeof(entry_v1); } if ((hdr_size < sizeof(entry_v1)) || (hdr_size > sizeof(entry))) { return NULL; } return reinterpret_cast(buf) + hdr_size; } unsigned int len() { return (entry.hdr_size ? entry.hdr_size : static_cast(sizeof(entry_v1))) + entry.len; } #endif }; #endif #ifndef __ANDROID_USE_LIBLOG_READER_INTERFACE #ifndef __ANDROID_API__ #define __ANDROID_USE_LIBLOG_READER_INTERFACE 3 #elif __ANDROID_API__ > 23 /* > Marshmallow */ #define __ANDROID_USE_LIBLOG_READER_INTERFACE 3 #elif __ANDROID_API__ > 22 /* > Lollipop */ #define __ANDROID_USE_LIBLOG_READER_INTERFACE 2 #elif __ANDROID_API__ > 19 /* > KitKat */ #define __ANDROID_USE_LIBLOG_READER_INTERFACE 1 #else #define __ANDROID_USE_LIBLOG_READER_INTERFACE 0 #endif #endif #if __ANDROID_USE_LIBLOG_READER_INTERFACE struct logger; log_id_t android_logger_get_id(struct logger* logger); int android_logger_clear(struct logger* logger); long android_logger_get_log_size(struct logger* logger); int android_logger_set_log_size(struct logger* logger, unsigned long size); long android_logger_get_log_readable_size(struct logger* logger); int android_logger_get_log_version(struct logger* logger); struct logger_list; #if __ANDROID_USE_LIBLOG_READER_INTERFACE > 1 ssize_t android_logger_get_statistics(struct logger_list* logger_list, char* buf, size_t len); ssize_t android_logger_get_prune_list(struct logger_list* logger_list, char* buf, size_t len); int android_logger_set_prune_list(struct logger_list* logger_list, char* buf, size_t len); #endif #define ANDROID_LOG_RDONLY O_RDONLY #define ANDROID_LOG_WRONLY O_WRONLY #define ANDROID_LOG_RDWR O_RDWR #define ANDROID_LOG_ACCMODE O_ACCMODE #define ANDROID_LOG_NONBLOCK O_NONBLOCK #if __ANDROID_USE_LIBLOG_READER_INTERFACE > 2 #define ANDROID_LOG_WRAP 0x40000000 /* Block until buffer about to wrap */ #define ANDROID_LOG_WRAP_DEFAULT_TIMEOUT 7200 /* 2 hour default */ #endif #if __ANDROID_USE_LIBLOG_READER_INTERFACE > 1 #define ANDROID_LOG_PSTORE 0x80000000 #endif struct logger_list* android_logger_list_alloc(int mode, unsigned int tail, pid_t pid); struct logger_list* android_logger_list_alloc_time(int mode, log_time start, pid_t pid); void android_logger_list_free(struct logger_list* logger_list); /* In the purest sense, the following two are orthogonal interfaces */ int android_logger_list_read(struct logger_list* logger_list, struct log_msg* log_msg); /* Multiple log_id_t opens */ struct logger* android_logger_open(struct logger_list* logger_list, log_id_t id); #define android_logger_close android_logger_free /* Single log_id_t open */ struct logger_list* android_logger_list_open(log_id_t id, int mode, unsigned int tail, pid_t pid); #define android_logger_list_close android_logger_list_free #endif /* __ANDROID_USE_LIBLOG_READER_INTERFACE */ #ifdef __linux__ #ifndef __ANDROID_USE_LIBLOG_CLOCK_INTERFACE #ifndef __ANDROID_API__ #define __ANDROID_USE_LIBLOG_CLOCK_INTERFACE 1 #elif __ANDROID_API__ > 22 /* > Lollipop */ #define __ANDROID_USE_LIBLOG_CLOCK_INTERFACE 1 #else #define __ANDROID_USE_LIBLOG_CLOCK_INTERFACE 0 #endif #endif #if __ANDROID_USE_LIBLOG_CLOCK_INTERFACE clockid_t android_log_clockid(); #endif #endif /* __linux__ */ /* * log_id_t helpers */ log_id_t android_name_to_log_id(const char* logName); const char* android_log_id_to_name(log_id_t log_id); /* --------------------------------------------------------------------- */ #ifndef _ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE #ifndef __ANDROID_API__ #define __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE 1 #elif __ANDROID_API__ > 22 /* > Lollipop */ #define __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE 1 #else #define __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE 0 #endif #endif #if __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE #define android_errorWriteLog(tag, subTag) \ __android_log_error_write(tag, subTag, -1, NULL, 0) #define android_errorWriteWithInfoLog(tag, subTag, uid, data, dataLen) \ __android_log_error_write(tag, subTag, uid, data, dataLen) int __android_log_error_write(int tag, const char* subTag, int32_t uid, const char* data, uint32_t dataLen); #endif /* __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE */ /* --------------------------------------------------------------------- */ #ifndef __ANDROID_USE_LIBLOG_CLOSE_INTERFACE #ifndef __ANDROID_API__ #define __ANDROID_USE_LIBLOG_CLOSE_INTERFACE 1 #elif __ANDROID_API__ > 18 /* > JellyBean */ #define __ANDROID_USE_LIBLOG_CLOSE_INTERFACE 1 #else #define __ANDROID_USE_LIBLOG_CLOSE_INTERFACE 0 #endif #endif #if __ANDROID_USE_LIBLOG_CLOSE_INTERFACE /* * Release any logger resources (a new log write will immediately re-acquire) * * May be used to clean up File descriptors after a Fork, the resources are * all O_CLOEXEC so wil self clean on exec(). */ void __android_log_close(); #endif #ifndef __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE #ifndef __ANDROID_API__ #define __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE 1 #elif __ANDROID_API__ > 25 /* > OC */ #define __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE 1 #else #define __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE 0 #endif #endif #if __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE /* * if last is NULL, caller _must_ provide a consistent value for seconds. * * Return -1 if we can not acquire a lock, which below will permit the logging, * error on allowing a log message through. */ int __android_log_ratelimit(time_t seconds, time_t* last); /* * Usage: * * // Global default and state * IF_ALOG_RATELIMIT() { * ALOG*(...); * } * * // local state, 10 seconds ratelimit * static time_t local_state; * IF_ALOG_RATELIMIT_LOCAL(10, &local_state) { * ALOG*(...); * } */ #define IF_ALOG_RATELIMIT() \ if (__android_log_ratelimit(0, NULL) > 0) #define IF_ALOG_RATELIMIT_LOCAL(seconds, state) \ if (__android_log_ratelimit(seconds, state) > 0) #else /* No ratelimiting as API unsupported */ #define IF_ALOG_RATELIMIT() if (1) #define IF_ALOG_RATELIMIT_LOCAL(...) if (1) #endif #if defined(__clang__) #pragma clang diagnostic pop #endif #ifdef __cplusplus } #endif #endif /* _LIBS_LOG_LOG_H */