Merge changes I7c1c0f3d,I670cb0b7,Id426d5c5

am: ce7ee088ff

Change-Id: I952d27f5b06753ae424a7e92b9511c95ef0c355b
This commit is contained in:
Mark Salyzyn 2017-03-10 15:22:05 +00:00 committed by android-build-merger
commit 8294bbf2d0
57 changed files with 10182 additions and 10469 deletions

9
liblog/.clang-format Normal file
View file

@ -0,0 +1,9 @@
BasedOnStyle: Google
AllowShortFunctionsOnASingleLine: false
CommentPragmas: NOLINT:.*
DerivePointerAlignment: false
PointerAlignment: Left
PenaltyExcessCharacter: 32
Cpp11BracedListStyle: false

View file

@ -108,10 +108,10 @@ SYNOPSIS
int android_log_destroy(android_log_context *ctx) int android_log_destroy(android_log_context *ctx)
#include <log/log_frontend.h> #include <log/log_transport.h>
int android_set_log_frontend(int frontend_flag) int android_set_log_transport(int transport_flag)
int android_get_log_frontend() int android_get_log_transport()
Link with -llog Link with -llog
@ -167,12 +167,12 @@ DESCRIPTION
when opening the sub-log. It is recommended to open the log when opening the sub-log. It is recommended to open the log
ANDROID_LOG_RDONLY in these cases. ANDROID_LOG_RDONLY in these cases.
android_set_log_frontend() selects frontend filters. Argument is either android_set_log_transport() selects transport filters. Argument is
LOGGER_DEFAULT, LOGGER_LOGD, LOGGER_NULL or LOGGER_LOCAL. Log to logger either LOGGER_DEFAULT, LOGGER_LOGD, LOGGER_NULL or LOGGER_LOCAL. Log to
daemon for default or logd, drop contents on floor, or log into local logger daemon for default or logd, drop contents on floor, or log into
memory respectively. Both android_set_log_frontend() and local memory respectively. Both android_set_log_transport()
android_get_log_frontend() return the current frontend mask, or a and android_get_log_transport() return the current transport mask, or
negative errno for any problems. a negative errno for any problems.
ERRORS ERRORS
If messages fail, a negative error code will be returned to the caller. If messages fail, a negative error code will be returned to the caller.

View file

@ -14,75 +14,73 @@
* limitations under the License. * limitations under the License.
*/ */
#include <log/log_frontend.h> #include <log/log_transport.h>
#include "config_read.h" #include "config_read.h"
#include "logger.h" #include "logger.h"
LIBLOG_HIDDEN struct listnode __android_log_transport_read = LIBLOG_HIDDEN struct listnode __android_log_transport_read = {
{ &__android_log_transport_read, &__android_log_transport_read }; &__android_log_transport_read, &__android_log_transport_read
LIBLOG_HIDDEN struct listnode __android_log_persist_read = };
{ &__android_log_persist_read, &__android_log_persist_read }; LIBLOG_HIDDEN struct listnode __android_log_persist_read = {
&__android_log_persist_read, &__android_log_persist_read
};
static void __android_log_add_transport( static void __android_log_add_transport(
struct listnode *list, struct android_log_transport_read *transport) { struct listnode* list, struct android_log_transport_read* transport) {
size_t i; size_t i;
/* Try to keep one functioning transport for each log buffer id */ /* Try to keep one functioning transport for each log buffer id */
for (i = LOG_ID_MIN; i < LOG_ID_MAX; i++) { for (i = LOG_ID_MIN; i < LOG_ID_MAX; i++) {
struct android_log_transport_read *transp; struct android_log_transport_read* transp;
if (list_empty(list)) { if (list_empty(list)) {
if (!transport->available || ((*transport->available)(i) >= 0)) { if (!transport->available || ((*transport->available)(i) >= 0)) {
list_add_tail(list, &transport->node); list_add_tail(list, &transport->node);
return; return;
} }
} else { } else {
read_transport_for_each(transp, list) { read_transport_for_each(transp, list) {
if (!transp->available) { if (!transp->available) {
return; return;
}
if (((*transp->available)(i) < 0) &&
(!transport->available ||
((*transport->available)(i) >= 0))) {
list_add_tail(list, &transport->node);
return;
}
}
} }
if (((*transp->available)(i) < 0) &&
(!transport->available || ((*transport->available)(i) >= 0))) {
list_add_tail(list, &transport->node);
return;
}
}
} }
}
} }
LIBLOG_HIDDEN void __android_log_config_read() { LIBLOG_HIDDEN void __android_log_config_read() {
if (__android_log_frontend & LOGGER_LOCAL) { if (__android_log_transport & LOGGER_LOCAL) {
extern struct android_log_transport_read localLoggerRead; extern struct android_log_transport_read localLoggerRead;
__android_log_add_transport(&__android_log_transport_read, __android_log_add_transport(&__android_log_transport_read, &localLoggerRead);
&localLoggerRead); }
}
#if (FAKE_LOG_DEVICE == 0) #if (FAKE_LOG_DEVICE == 0)
if ((__android_log_frontend == LOGGER_DEFAULT) || if ((__android_log_transport == LOGGER_DEFAULT) ||
(__android_log_frontend & LOGGER_LOGD)) { (__android_log_transport & LOGGER_LOGD)) {
extern struct android_log_transport_read logdLoggerRead; extern struct android_log_transport_read logdLoggerRead;
extern struct android_log_transport_read pmsgLoggerRead; extern struct android_log_transport_read pmsgLoggerRead;
__android_log_add_transport(&__android_log_transport_read, __android_log_add_transport(&__android_log_transport_read, &logdLoggerRead);
&logdLoggerRead); __android_log_add_transport(&__android_log_persist_read, &pmsgLoggerRead);
__android_log_add_transport(&__android_log_persist_read, }
&pmsgLoggerRead);
}
#endif #endif
} }
LIBLOG_HIDDEN void __android_log_config_read_close() { LIBLOG_HIDDEN void __android_log_config_read_close() {
struct android_log_transport_read *transport; struct android_log_transport_read* transport;
struct listnode *n; struct listnode* n;
read_transport_for_each_safe(transport, n, &__android_log_transport_read) { read_transport_for_each_safe(transport, n, &__android_log_transport_read) {
list_remove(&transport->node); list_remove(&transport->node);
} }
read_transport_for_each_safe(transport, n, &__android_log_persist_read) { read_transport_for_each_safe(transport, n, &__android_log_persist_read) {
list_remove(&transport->node); list_remove(&transport->node);
} }
} }

View file

@ -26,30 +26,26 @@ __BEGIN_DECLS
extern LIBLOG_HIDDEN struct listnode __android_log_transport_read; extern LIBLOG_HIDDEN struct listnode __android_log_transport_read;
extern LIBLOG_HIDDEN struct listnode __android_log_persist_read; extern LIBLOG_HIDDEN struct listnode __android_log_persist_read;
#define read_transport_for_each(transp, transports) \ #define read_transport_for_each(transp, transports) \
for ((transp) = node_to_item((transports)->next, \ for ((transp) = node_to_item((transports)->next, \
struct android_log_transport_read, node); \ struct android_log_transport_read, node); \
((transp) != node_to_item((transports), \ ((transp) != node_to_item((transports), \
struct android_log_transport_read, \ struct android_log_transport_read, node)) && \
node)) && \ ((transp) != node_to_item((transp)->node.next, \
((transp) != node_to_item((transp)->node.next, \ struct android_log_transport_read, node)); \
struct android_log_transport_read, \ (transp) = node_to_item((transp)->node.next, \
node)); \ struct android_log_transport_read, node))
(transp) = node_to_item((transp)->node.next, \
struct android_log_transport_read, node))
#define read_transport_for_each_safe(transp, n, transports) \ #define read_transport_for_each_safe(transp, n, transports) \
for ((transp) = node_to_item((transports)->next, \ for ((transp) = node_to_item((transports)->next, \
struct android_log_transport_read, node), \ struct android_log_transport_read, node), \
(n) = (transp)->node.next; \ (n) = (transp)->node.next; \
((transp) != node_to_item((transports), \ ((transp) != node_to_item((transports), \
struct android_log_transport_read, \ struct android_log_transport_read, node)) && \
node)) && \ ((transp) != \
((transp) != node_to_item((n), struct android_log_transport_read, \ node_to_item((n), struct android_log_transport_read, node)); \
node)); \ (transp) = node_to_item((n), struct android_log_transport_read, node), \
(transp) = node_to_item((n), struct android_log_transport_read, \ (n) = (transp)->node.next)
node), \
(n) = (transp)->node.next)
LIBLOG_HIDDEN void __android_log_config_read(); LIBLOG_HIDDEN void __android_log_config_read();
LIBLOG_HIDDEN void __android_log_config_read_close(); LIBLOG_HIDDEN void __android_log_config_read_close();

View file

@ -14,105 +14,105 @@
* limitations under the License. * limitations under the License.
*/ */
#include <log/log_frontend.h> #include <log/log_transport.h>
#include "config_write.h" #include "config_write.h"
#include "logger.h" #include "logger.h"
LIBLOG_HIDDEN struct listnode __android_log_transport_write = LIBLOG_HIDDEN struct listnode __android_log_transport_write = {
{ &__android_log_transport_write, &__android_log_transport_write }; &__android_log_transport_write, &__android_log_transport_write
LIBLOG_HIDDEN struct listnode __android_log_persist_write = };
{ &__android_log_persist_write, &__android_log_persist_write}; LIBLOG_HIDDEN struct listnode __android_log_persist_write = {
&__android_log_persist_write, &__android_log_persist_write
};
static void __android_log_add_transport( static void __android_log_add_transport(
struct listnode *list, struct android_log_transport_write *transport) { struct listnode* list, struct android_log_transport_write* transport) {
size_t i; size_t i;
/* Try to keep one functioning transport for each log buffer id */ /* Try to keep one functioning transport for each log buffer id */
for (i = LOG_ID_MIN; i < LOG_ID_MAX; i++) { for (i = LOG_ID_MIN; i < LOG_ID_MAX; i++) {
struct android_log_transport_write *transp; struct android_log_transport_write* transp;
if (list_empty(list)) { if (list_empty(list)) {
if (!transport->available || ((*transport->available)(i) >= 0)) { if (!transport->available || ((*transport->available)(i) >= 0)) {
list_add_tail(list, &transport->node); list_add_tail(list, &transport->node);
return; return;
} }
} else { } else {
write_transport_for_each(transp, list) { write_transport_for_each(transp, list) {
if (!transp->available) { if (!transp->available) {
return; return;
}
if (((*transp->available)(i) < 0) &&
(!transport->available ||
((*transport->available)(i) >= 0))) {
list_add_tail(list, &transport->node);
return;
}
}
} }
if (((*transp->available)(i) < 0) &&
(!transport->available || ((*transport->available)(i) >= 0))) {
list_add_tail(list, &transport->node);
return;
}
}
} }
}
} }
LIBLOG_HIDDEN void __android_log_config_write() { LIBLOG_HIDDEN void __android_log_config_write() {
if (__android_log_frontend & LOGGER_LOCAL) { if (__android_log_transport & LOGGER_LOCAL) {
extern struct android_log_transport_write localLoggerWrite; extern struct android_log_transport_write localLoggerWrite;
__android_log_add_transport(&__android_log_transport_write, __android_log_add_transport(&__android_log_transport_write,
&localLoggerWrite); &localLoggerWrite);
} }
if ((__android_log_frontend == LOGGER_DEFAULT) || if ((__android_log_transport == LOGGER_DEFAULT) ||
(__android_log_frontend & LOGGER_LOGD)) { (__android_log_transport & LOGGER_LOGD)) {
#if (FAKE_LOG_DEVICE == 0) #if (FAKE_LOG_DEVICE == 0)
extern struct android_log_transport_write logdLoggerWrite; extern struct android_log_transport_write logdLoggerWrite;
extern struct android_log_transport_write pmsgLoggerWrite; extern struct android_log_transport_write pmsgLoggerWrite;
__android_log_add_transport(&__android_log_transport_write, __android_log_add_transport(&__android_log_transport_write,
&logdLoggerWrite); &logdLoggerWrite);
__android_log_add_transport(&__android_log_persist_write, __android_log_add_transport(&__android_log_persist_write, &pmsgLoggerWrite);
&pmsgLoggerWrite);
#else #else
extern struct android_log_transport_write fakeLoggerWrite; extern struct android_log_transport_write fakeLoggerWrite;
__android_log_add_transport(&__android_log_transport_write, __android_log_add_transport(&__android_log_transport_write,
&fakeLoggerWrite); &fakeLoggerWrite);
#endif #endif
} }
if (__android_log_frontend & LOGGER_STDERR) { if (__android_log_transport & LOGGER_STDERR) {
extern struct android_log_transport_write stderrLoggerWrite; extern struct android_log_transport_write stderrLoggerWrite;
/* /*
* stderr logger should be primary if we can be the only one, or if * stderr logger should be primary if we can be the only one, or if
* already in the primary list. Otherwise land in the persist list. * already in the primary list. Otherwise land in the persist list.
* Remember we can be called here if we are already initialized. * Remember we can be called here if we are already initialized.
*/ */
if (list_empty(&__android_log_transport_write)) { if (list_empty(&__android_log_transport_write)) {
__android_log_add_transport(&__android_log_transport_write, __android_log_add_transport(&__android_log_transport_write,
&stderrLoggerWrite); &stderrLoggerWrite);
} else { } else {
struct android_log_transport_write *transp; struct android_log_transport_write* transp;
write_transport_for_each(transp, &__android_log_transport_write) { write_transport_for_each(transp, &__android_log_transport_write) {
if (transp == &stderrLoggerWrite) { if (transp == &stderrLoggerWrite) {
return; return;
}
}
__android_log_add_transport(&__android_log_persist_write,
&stderrLoggerWrite);
} }
}
__android_log_add_transport(&__android_log_persist_write,
&stderrLoggerWrite);
} }
}
} }
LIBLOG_HIDDEN void __android_log_config_write_close() { LIBLOG_HIDDEN void __android_log_config_write_close() {
struct android_log_transport_write *transport; struct android_log_transport_write* transport;
struct listnode *n; struct listnode* n;
write_transport_for_each_safe(transport, n, &__android_log_transport_write) { write_transport_for_each_safe(transport, n, &__android_log_transport_write) {
transport->logMask = 0; transport->logMask = 0;
list_remove(&transport->node); list_remove(&transport->node);
} }
write_transport_for_each_safe(transport, n, &__android_log_persist_write) { write_transport_for_each_safe(transport, n, &__android_log_persist_write) {
transport->logMask = 0; transport->logMask = 0;
list_remove(&transport->node); list_remove(&transport->node);
} }
} }

View file

@ -26,30 +26,26 @@ __BEGIN_DECLS
extern LIBLOG_HIDDEN struct listnode __android_log_transport_write; extern LIBLOG_HIDDEN struct listnode __android_log_transport_write;
extern LIBLOG_HIDDEN struct listnode __android_log_persist_write; extern LIBLOG_HIDDEN struct listnode __android_log_persist_write;
#define write_transport_for_each(transp, transports) \ #define write_transport_for_each(transp, transports) \
for ((transp) = node_to_item((transports)->next, \ for ((transp) = node_to_item((transports)->next, \
struct android_log_transport_write, node); \ struct android_log_transport_write, node); \
((transp) != node_to_item((transports), \ ((transp) != node_to_item((transports), \
struct android_log_transport_write, \ struct android_log_transport_write, node)) && \
node)) && \ ((transp) != node_to_item((transp)->node.next, \
((transp) != node_to_item((transp)->node.next, \ struct android_log_transport_write, node)); \
struct android_log_transport_write, \ (transp) = node_to_item((transp)->node.next, \
node)); \ struct android_log_transport_write, node))
(transp) = node_to_item((transp)->node.next, \
struct android_log_transport_write, node))
#define write_transport_for_each_safe(transp, n, transports) \ #define write_transport_for_each_safe(transp, n, transports) \
for ((transp) = node_to_item((transports)->next, \ for ((transp) = node_to_item((transports)->next, \
struct android_log_transport_write, node), \ struct android_log_transport_write, node), \
(n) = (transp)->node.next; \ (n) = (transp)->node.next; \
((transp) != node_to_item((transports), \ ((transp) != node_to_item((transports), \
struct android_log_transport_write, \ struct android_log_transport_write, node)) && \
node)) && \ ((transp) != \
((transp) != node_to_item((n), struct android_log_transport_write, \ node_to_item((n), struct android_log_transport_write, node)); \
node)); \ (transp) = node_to_item((n), struct android_log_transport_write, node), \
(transp) = node_to_item((n), struct android_log_transport_write, \ (n) = (transp)->node.next)
node), \
(n) = (transp)->node.next)
LIBLOG_HIDDEN void __android_log_config_write(); LIBLOG_HIDDEN void __android_log_config_write();
LIBLOG_HIDDEN void __android_log_config_write_close(); LIBLOG_HIDDEN void __android_log_config_write_close();

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -23,9 +23,9 @@
struct iovec; struct iovec;
LIBLOG_HIDDEN int fakeLogOpen(const char *pathName, int flags); LIBLOG_HIDDEN int fakeLogOpen(const char* pathName, int flags);
LIBLOG_HIDDEN int fakeLogClose(int fd); LIBLOG_HIDDEN int fakeLogClose(int fd);
LIBLOG_HIDDEN ssize_t fakeLogWritev(int fd, LIBLOG_HIDDEN ssize_t fakeLogWritev(int fd, const struct iovec* vector,
const struct iovec* vector, int count); int count);
#endif // _LIBLOG_FAKE_LOG_DEVICE_H #endif // _LIBLOG_FAKE_LOG_DEVICE_H

View file

@ -27,78 +27,77 @@
static int fakeOpen(); static int fakeOpen();
static void fakeClose(); static void fakeClose();
static int fakeWrite(log_id_t log_id, struct timespec *ts, static int fakeWrite(log_id_t log_id, struct timespec* ts, struct iovec* vec,
struct iovec *vec, size_t nr); size_t nr);
static int logFds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1, -1 }; static int logFds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1, -1 };
LIBLOG_HIDDEN struct android_log_transport_write fakeLoggerWrite = { LIBLOG_HIDDEN struct android_log_transport_write fakeLoggerWrite = {
.node = { &fakeLoggerWrite.node, &fakeLoggerWrite.node }, .node = { &fakeLoggerWrite.node, &fakeLoggerWrite.node },
.context.private = &logFds, .context.priv = &logFds,
.name = "fake", .name = "fake",
.available = NULL, .available = NULL,
.open = fakeOpen, .open = fakeOpen,
.close = fakeClose, .close = fakeClose,
.write = fakeWrite, .write = fakeWrite,
}; };
static int fakeOpen() { static int fakeOpen() {
int i; int i;
for (i = 0; i < LOG_ID_MAX; i++) { for (i = 0; i < LOG_ID_MAX; i++) {
/* /*
* Known maximum size string, plus an 8 character margin to deal with * Known maximum size string, plus an 8 character margin to deal with
* possible independent changes to android_log_id_to_name(). * possible independent changes to android_log_id_to_name().
*/ */
char buf[sizeof("/dev/log_security") + 8]; char buf[sizeof("/dev/log_security") + 8];
if (logFds[i] >= 0) { if (logFds[i] >= 0) {
continue; continue;
}
snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i));
logFds[i] = fakeLogOpen(buf, O_WRONLY);
if (logFds[i] < 0) {
fprintf(stderr, "fakeLogOpen(%s, O_WRONLY) failed\n", buf);
}
} }
return 0; snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i));
logFds[i] = fakeLogOpen(buf, O_WRONLY);
if (logFds[i] < 0) {
fprintf(stderr, "fakeLogOpen(%s, O_WRONLY) failed\n", buf);
}
}
return 0;
} }
static void fakeClose() { static void fakeClose() {
int i; int i;
for (i = 0; i < LOG_ID_MAX; i++) { for (i = 0; i < LOG_ID_MAX; i++) {
fakeLogClose(logFds[i]); fakeLogClose(logFds[i]);
logFds[i] = -1; logFds[i] = -1;
} }
} }
static int fakeWrite(log_id_t log_id, struct timespec *ts __unused, static int fakeWrite(log_id_t log_id, struct timespec* ts __unused,
struct iovec *vec, size_t nr) struct iovec* vec, size_t nr) {
{ ssize_t ret;
ssize_t ret; size_t i;
size_t i; int logFd, len;
int logFd, len;
if (/*(int)log_id >= 0 &&*/ (int)log_id >= (int)LOG_ID_MAX) { if (/*(int)log_id >= 0 &&*/ (int)log_id >= (int)LOG_ID_MAX) {
return -EINVAL; return -EINVAL;
} }
len = 0; len = 0;
for (i = 0; i < nr; ++i) { for (i = 0; i < nr; ++i) {
len += vec[i].iov_len; len += vec[i].iov_len;
} }
if (len > LOGGER_ENTRY_MAX_PAYLOAD) { if (len > LOGGER_ENTRY_MAX_PAYLOAD) {
len = LOGGER_ENTRY_MAX_PAYLOAD; len = LOGGER_ENTRY_MAX_PAYLOAD;
} }
logFd = logFds[(int)log_id]; logFd = logFds[(int)log_id];
ret = TEMP_FAILURE_RETRY(fakeLogWritev(logFd, vec, nr)); ret = TEMP_FAILURE_RETRY(fakeLogWritev(logFd, vec, nr));
if (ret < 0) { if (ret < 0) {
ret = -errno; ret = -errno;
} else if (ret > len) { } else if (ret > len) {
ret = len; ret = len;
} }
return ret; return ret;
} }

View file

@ -50,8 +50,8 @@
* limit (e.g. 1023 characters max). * limit (e.g. 1023 characters max).
* *
* Note that a newline character ("\n") will be appended automatically to your * Note that a newline character ("\n") will be appended automatically to your
* log message, if not already there. It is not possible to send several messages * log message, if not already there. It is not possible to send several
* and have them appear on a single line in logcat. * messages and have them appear on a single line in logcat.
* *
* PLEASE USE LOGS WITH MODERATION: * PLEASE USE LOGS WITH MODERATION:
* *
@ -77,15 +77,15 @@ extern "C" {
* Android log priority values, in ascending priority order. * Android log priority values, in ascending priority order.
*/ */
typedef enum android_LogPriority { typedef enum android_LogPriority {
ANDROID_LOG_UNKNOWN = 0, ANDROID_LOG_UNKNOWN = 0,
ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */ ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */
ANDROID_LOG_VERBOSE, ANDROID_LOG_VERBOSE,
ANDROID_LOG_DEBUG, ANDROID_LOG_DEBUG,
ANDROID_LOG_INFO, ANDROID_LOG_INFO,
ANDROID_LOG_WARN, ANDROID_LOG_WARN,
ANDROID_LOG_ERROR, ANDROID_LOG_ERROR,
ANDROID_LOG_FATAL, ANDROID_LOG_FATAL,
ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */ ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */
} android_LogPriority; } android_LogPriority;
/* /*
@ -96,16 +96,16 @@ int __android_log_write(int prio, const char* tag, const char* text);
/* /*
* Send a formatted string to the log, used like printf(fmt,...) * Send a formatted string to the log, used like printf(fmt,...)
*/ */
int __android_log_print(int prio, const char* tag, const char* fmt, ...) int __android_log_print(int prio, const char* tag, const char* fmt, ...)
#if defined(__GNUC__) #if defined(__GNUC__)
#ifdef __USE_MINGW_ANSI_STDIO #ifdef __USE_MINGW_ANSI_STDIO
#if __USE_MINGW_ANSI_STDIO #if __USE_MINGW_ANSI_STDIO
__attribute__ ((__format__(gnu_printf, 3, 4))) __attribute__((__format__(gnu_printf, 3, 4)))
#else #else
__attribute__ ((__format__(printf, 3, 4))) __attribute__((__format__(printf, 3, 4)))
#endif #endif
#else #else
__attribute__ ((__format__(printf, 3, 4))) __attribute__((__format__(printf, 3, 4)))
#endif #endif
#endif #endif
; ;
@ -114,17 +114,16 @@ int __android_log_print(int prio, const char* tag, const char* fmt, ...)
* A variant of __android_log_print() that takes a va_list to list * A variant of __android_log_print() that takes a va_list to list
* additional parameters. * additional parameters.
*/ */
int __android_log_vprint(int prio, const char* tag, int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap)
const char* fmt, va_list ap)
#if defined(__GNUC__) #if defined(__GNUC__)
#ifdef __USE_MINGW_ANSI_STDIO #ifdef __USE_MINGW_ANSI_STDIO
#if __USE_MINGW_ANSI_STDIO #if __USE_MINGW_ANSI_STDIO
__attribute__ ((__format__(gnu_printf, 3, 0))) __attribute__((__format__(gnu_printf, 3, 0)))
#else #else
__attribute__ ((__format__(printf, 3, 0))) __attribute__((__format__(printf, 3, 0)))
#endif #endif
#else #else
__attribute__ ((__format__(printf, 3, 0))) __attribute__((__format__(printf, 3, 0)))
#endif #endif
#endif #endif
; ;
@ -133,18 +132,18 @@ int __android_log_vprint(int prio, const char* tag,
* Log an assertion failure and abort the process to have a chance * Log an assertion failure and abort the process to have a chance
* to inspect it if a debugger is attached. This uses the FATAL priority. * to inspect it if a debugger is attached. This uses the FATAL priority.
*/ */
void __android_log_assert(const char* cond, const char* tag, void __android_log_assert(const char* cond, const char* tag, const char* fmt,
const char* fmt, ...) ...)
#if defined(__GNUC__) #if defined(__GNUC__)
__attribute__ ((__noreturn__)) __attribute__((__noreturn__))
#ifdef __USE_MINGW_ANSI_STDIO #ifdef __USE_MINGW_ANSI_STDIO
#if __USE_MINGW_ANSI_STDIO #if __USE_MINGW_ANSI_STDIO
__attribute__ ((__format__(gnu_printf, 3, 4))) __attribute__((__format__(gnu_printf, 3, 4)))
#else #else
__attribute__ ((__format__(printf, 3, 4))) __attribute__((__format__(printf, 3, 4)))
#endif #endif
#else #else
__attribute__ ((__format__(printf, 3, 4))) __attribute__((__format__(printf, 3, 4)))
#endif #endif
#endif #endif
; ;

View file

@ -21,7 +21,7 @@
extern "C" { extern "C" {
#endif #endif
#define EVENT_TAG_MAP_FILE "/system/etc/event-log-tags" #define EVENT_TAG_MAP_FILE "/system/etc/event-log-tags"
struct EventTagMap; struct EventTagMap;
typedef struct EventTagMap EventTagMap; typedef struct EventTagMap EventTagMap;
@ -42,21 +42,23 @@ void android_closeEventTagMap(EventTagMap* map);
* Look up a tag by index. Returns the tag string, or NULL if not found. * Look up a tag by index. Returns the tag string, or NULL if not found.
*/ */
const char* android_lookupEventTag(const EventTagMap* map, unsigned int tag) const char* android_lookupEventTag(const EventTagMap* map, unsigned int tag)
__attribute__((deprecated("use android_lookupEventTag_len() instead to minimize MAP_PRIVATE copy-on-write memory impact"))); __attribute__((
deprecated("use android_lookupEventTag_len() instead to minimize "
"MAP_PRIVATE copy-on-write memory impact")));
/* /*
* Look up a tag by index. Returns the tag string & string length, or NULL if * Look up a tag by index. Returns the tag string & string length, or NULL if
* not found. Returned string is not guaranteed to be nul terminated. * not found. Returned string is not guaranteed to be nul terminated.
*/ */
const char* android_lookupEventTag_len(const EventTagMap* map, const char* android_lookupEventTag_len(const EventTagMap* map, size_t* len,
size_t* len, unsigned int tag); unsigned int tag);
/* /*
* Look up a format by index. Returns the format string & string length, * Look up a format by index. Returns the format string & string length,
* or NULL if not found. Returned string is not guaranteed to be nul terminated. * or NULL if not found. Returned string is not guaranteed to be nul terminated.
*/ */
const char* android_lookupEventFormat_len(const EventTagMap* map, const char* android_lookupEventFormat_len(const EventTagMap* map, size_t* len,
size_t* len, unsigned int tag); unsigned int tag);
/* /*
* Look up tagname, generate one if necessary, and return a tag * Look up tagname, generate one if necessary, and return a tag

View file

@ -21,7 +21,7 @@
#if !defined(_WIN32) #if !defined(_WIN32)
#include <pthread.h> #include <pthread.h>
#endif #endif
#include <stdint.h> /* uint16_t, int32_t */ #include <stdint.h> /* uint16_t, int32_t */
#include <stdio.h> #include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
#include <time.h> #include <time.h>
@ -95,9 +95,9 @@ int __android_log_btwrite(int32_t tag, char type, const void* payload,
int __android_log_bswrite(int32_t tag, const char* payload); int __android_log_bswrite(int32_t tag, const char* payload);
#define android_bWriteLog(tag, payload, len) \ #define android_bWriteLog(tag, payload, len) \
__android_log_bwrite(tag, payload, len) __android_log_bwrite(tag, payload, len)
#define android_btWriteLog(tag, type, payload, len) \ #define android_btWriteLog(tag, type, payload, len) \
__android_log_btwrite(tag, type, payload, len) __android_log_btwrite(tag, type, payload, len)
/* /*
* Event log entry types. * Event log entry types.
@ -105,45 +105,46 @@ int __android_log_bswrite(int32_t tag, const char* payload);
#ifndef __AndroidEventLogType_defined #ifndef __AndroidEventLogType_defined
#define __AndroidEventLogType_defined #define __AndroidEventLogType_defined
typedef enum { typedef enum {
/* Special markers for android_log_list_element type */ /* Special markers for android_log_list_element type */
EVENT_TYPE_LIST_STOP = '\n', /* declare end of list */ EVENT_TYPE_LIST_STOP = '\n', /* declare end of list */
EVENT_TYPE_UNKNOWN = '?', /* protocol error */ EVENT_TYPE_UNKNOWN = '?', /* protocol error */
/* must match with declaration in java/android/android/util/EventLog.java */ /* must match with declaration in java/android/android/util/EventLog.java */
EVENT_TYPE_INT = 0, /* int32_t */ EVENT_TYPE_INT = 0, /* int32_t */
EVENT_TYPE_LONG = 1, /* int64_t */ EVENT_TYPE_LONG = 1, /* int64_t */
EVENT_TYPE_STRING = 2, EVENT_TYPE_STRING = 2,
EVENT_TYPE_LIST = 3, EVENT_TYPE_LIST = 3,
EVENT_TYPE_FLOAT = 4, EVENT_TYPE_FLOAT = 4,
} AndroidEventLogType; } AndroidEventLogType;
#endif #endif
#define sizeof_AndroidEventLogType sizeof(typeof_AndroidEventLogType) #define sizeof_AndroidEventLogType sizeof(typeof_AndroidEventLogType)
#define typeof_AndroidEventLogType unsigned char #define typeof_AndroidEventLogType unsigned char
#ifndef LOG_EVENT_INT #ifndef LOG_EVENT_INT
#define LOG_EVENT_INT(_tag, _value) { \ #define LOG_EVENT_INT(_tag, _value) \
int intBuf = _value; \ { \
(void) android_btWriteLog(_tag, EVENT_TYPE_INT, &intBuf, \ int intBuf = _value; \
sizeof(intBuf)); \ (void)android_btWriteLog(_tag, EVENT_TYPE_INT, &intBuf, sizeof(intBuf)); \
} }
#endif #endif
#ifndef LOG_EVENT_LONG #ifndef LOG_EVENT_LONG
#define LOG_EVENT_LONG(_tag, _value) { \ #define LOG_EVENT_LONG(_tag, _value) \
long long longBuf = _value; \ { \
(void) android_btWriteLog(_tag, EVENT_TYPE_LONG, &longBuf, \ long long longBuf = _value; \
sizeof(longBuf)); \ (void)android_btWriteLog(_tag, EVENT_TYPE_LONG, &longBuf, sizeof(longBuf)); \
} }
#endif #endif
#ifndef LOG_EVENT_FLOAT #ifndef LOG_EVENT_FLOAT
#define LOG_EVENT_FLOAT(_tag, _value) { \ #define LOG_EVENT_FLOAT(_tag, _value) \
float floatBuf = _value; \ { \
(void) android_btWriteLog(_tag, EVENT_TYPE_FLOAT, &floatBuf, \ float floatBuf = _value; \
sizeof(floatBuf)); \ (void)android_btWriteLog(_tag, EVENT_TYPE_FLOAT, &floatBuf, \
} sizeof(floatBuf)); \
}
#endif #endif
#ifndef LOG_EVENT_STRING #ifndef LOG_EVENT_STRING
#define LOG_EVENT_STRING(_tag, _value) \ #define LOG_EVENT_STRING(_tag, _value) \
(void) __android_log_bswrite(_tag, _value); (void)__android_log_bswrite(_tag, _value);
#endif #endif
#ifdef __linux__ #ifdef __linux__
@ -179,10 +180,10 @@ clockid_t android_log_clockid();
#if __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE #if __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE
#define android_errorWriteLog(tag, subTag) \ #define android_errorWriteLog(tag, subTag) \
__android_log_error_write(tag, subTag, -1, NULL, 0) __android_log_error_write(tag, subTag, -1, NULL, 0)
#define android_errorWriteWithInfoLog(tag, subTag, uid, data, dataLen) \ #define android_errorWriteWithInfoLog(tag, subTag, uid, data, dataLen) \
__android_log_error_write(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, int __android_log_error_write(int tag, const char* subTag, int32_t uid,
const char* data, uint32_t dataLen); const char* data, uint32_t dataLen);
@ -246,10 +247,9 @@ int __android_log_ratelimit(time_t seconds, time_t* last);
* } * }
*/ */
#define IF_ALOG_RATELIMIT() \ #define IF_ALOG_RATELIMIT() if (__android_log_ratelimit(0, NULL) > 0)
if (__android_log_ratelimit(0, NULL) > 0)
#define IF_ALOG_RATELIMIT_LOCAL(seconds, state) \ #define IF_ALOG_RATELIMIT_LOCAL(seconds, state) \
if (__android_log_ratelimit(seconds, state) > 0) if (__android_log_ratelimit(seconds, state) > 0)
#else #else

View file

@ -61,15 +61,15 @@ typedef struct android_log_context_internal* android_log_context;
#ifndef __android_log_list_element_defined #ifndef __android_log_list_element_defined
#define __android_log_list_element_defined #define __android_log_list_element_defined
typedef struct { typedef struct {
AndroidEventLogType type; AndroidEventLogType type;
uint16_t complete; uint16_t complete;
uint16_t len; uint16_t len;
union { union {
int32_t int32; int32_t int32;
int64_t int64; int64_t int64;
char* string; char* string;
float float32; float float32;
} data; } data;
} android_log_list_element; } android_log_list_element;
#endif #endif
@ -91,8 +91,8 @@ int android_log_write_list_end(android_log_context ctx);
int android_log_write_int32(android_log_context ctx, int32_t value); int android_log_write_int32(android_log_context ctx, int32_t value);
int android_log_write_int64(android_log_context ctx, int64_t value); int android_log_write_int64(android_log_context ctx, int64_t value);
int android_log_write_string8(android_log_context ctx, const char* value); int android_log_write_string8(android_log_context ctx, const char* value);
int android_log_write_string8_len(android_log_context ctx, int android_log_write_string8_len(android_log_context ctx, const char* value,
const char* value, size_t maxlen); size_t maxlen);
int android_log_write_float32(android_log_context ctx, float value); int android_log_write_float32(android_log_context ctx, float value);
/* Submit the composed list context to the specified logger id */ /* Submit the composed list context to the specified logger id */
@ -116,173 +116,182 @@ int android_log_destroy(android_log_context* ctx);
/* android_log_list C++ helpers */ /* android_log_list C++ helpers */
extern "C++" { extern "C++" {
class android_log_event_list { class android_log_event_list {
friend class __android_log_event_list; friend class __android_log_event_list;
private: private:
android_log_context ctx; android_log_context ctx;
int ret; int ret;
android_log_event_list(const android_log_event_list&) = delete; android_log_event_list(const android_log_event_list&) = delete;
void operator =(const android_log_event_list&) = delete; void operator=(const android_log_event_list&) = delete;
public: public:
explicit android_log_event_list(int tag) : ret(0) { explicit android_log_event_list(int tag) : ret(0) {
ctx = create_android_logger(static_cast<uint32_t>(tag)); ctx = create_android_logger(static_cast<uint32_t>(tag));
} }
explicit android_log_event_list(log_msg& log_msg) : ret(0) { explicit android_log_event_list(log_msg& log_msg) : ret(0) {
ctx = create_android_log_parser(log_msg.msg() + sizeof(uint32_t), ctx = create_android_log_parser(log_msg.msg() + sizeof(uint32_t),
log_msg.entry.len - sizeof(uint32_t)); log_msg.entry.len - sizeof(uint32_t));
} }
~android_log_event_list() { android_log_destroy(&ctx); } ~android_log_event_list() {
android_log_destroy(&ctx);
}
int close() { int close() {
int retval = android_log_destroy(&ctx); int retval = android_log_destroy(&ctx);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return retval; return retval;
} }
/* To allow above C calls to use this class as parameter */ /* To allow above C calls to use this class as parameter */
operator android_log_context() const { return ctx; } operator android_log_context() const {
return ctx;
}
int status() const { return ret; } int status() const {
return ret;
}
int begin() { int begin() {
int retval = android_log_write_list_begin(ctx); int retval = android_log_write_list_begin(ctx);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return ret; return ret;
} }
int end() { int end() {
int retval = android_log_write_list_end(ctx); int retval = android_log_write_list_end(ctx);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return ret; return ret;
} }
android_log_event_list& operator <<(int32_t value) { android_log_event_list& operator<<(int32_t value) {
int retval = android_log_write_int32(ctx, value); int retval = android_log_write_int32(ctx, value);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return *this; return *this;
} }
android_log_event_list& operator <<(uint32_t value) { android_log_event_list& operator<<(uint32_t value) {
int retval = android_log_write_int32(ctx, static_cast<int32_t>(value)); int retval = android_log_write_int32(ctx, static_cast<int32_t>(value));
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return *this; return *this;
} }
android_log_event_list& operator <<(int64_t value) { android_log_event_list& operator<<(int64_t value) {
int retval = android_log_write_int64(ctx, value); int retval = android_log_write_int64(ctx, value);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return *this; return *this;
} }
android_log_event_list& operator <<(uint64_t value) { android_log_event_list& operator<<(uint64_t value) {
int retval = android_log_write_int64(ctx, static_cast<int64_t>(value)); int retval = android_log_write_int64(ctx, static_cast<int64_t>(value));
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return *this; return *this;
} }
android_log_event_list& operator <<(const char* value) { android_log_event_list& operator<<(const char* value) {
int retval = android_log_write_string8(ctx, value); int retval = android_log_write_string8(ctx, value);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return *this; return *this;
} }
#if defined(_USING_LIBCXX) #if defined(_USING_LIBCXX)
android_log_event_list& operator <<(const std::string& value) { android_log_event_list& operator<<(const std::string& value) {
int retval = android_log_write_string8_len(ctx, int retval =
value.data(), android_log_write_string8_len(ctx, value.data(), value.length());
value.length()); if (retval < 0) ret = retval;
if (retval < 0) ret = retval; return *this;
return *this; }
}
#endif #endif
android_log_event_list& operator <<(float value) { android_log_event_list& operator<<(float value) {
int retval = android_log_write_float32(ctx, value); int retval = android_log_write_float32(ctx, value);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return *this; return *this;
} }
int write(log_id_t id = LOG_ID_EVENTS) { int write(log_id_t id = LOG_ID_EVENTS) {
int retval = android_log_write_list(ctx, id); int retval = android_log_write_list(ctx, id);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return ret; return ret;
} }
int operator <<(log_id_t id) { int operator<<(log_id_t id) {
int retval = android_log_write_list(ctx, id); int retval = android_log_write_list(ctx, id);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
android_log_destroy(&ctx); android_log_destroy(&ctx);
return ret; return ret;
} }
/* /*
* Append<Type> methods removes any integer promotion * Append<Type> methods removes any integer promotion
* confusion, and adds access to string with length. * confusion, and adds access to string with length.
* Append methods are also added for all types for * Append methods are also added for all types for
* convenience. * convenience.
*/ */
bool AppendInt(int32_t value) { bool AppendInt(int32_t value) {
int retval = android_log_write_int32(ctx, value); int retval = android_log_write_int32(ctx, value);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return ret >= 0; return ret >= 0;
} }
bool AppendLong(int64_t value) { bool AppendLong(int64_t value) {
int retval = android_log_write_int64(ctx, value); int retval = android_log_write_int64(ctx, value);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return ret >= 0; return ret >= 0;
} }
bool AppendString(const char* value) { bool AppendString(const char* value) {
int retval = android_log_write_string8(ctx, value); int retval = android_log_write_string8(ctx, value);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return ret >= 0; return ret >= 0;
} }
bool AppendString(const char* value, size_t len) { bool AppendString(const char* value, size_t len) {
int retval = android_log_write_string8_len(ctx, value, len); int retval = android_log_write_string8_len(ctx, value, len);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return ret >= 0; return ret >= 0;
} }
#if defined(_USING_LIBCXX) #if defined(_USING_LIBCXX)
bool AppendString(const std::string& value) { bool AppendString(const std::string& value) {
int retval = android_log_write_string8_len(ctx, int retval =
value.data(), android_log_write_string8_len(ctx, value.data(), value.length());
value.length()); if (retval < 0) ret = retval;
if (retval < 0) ret = retval; return ret;
return ret; }
}
bool Append(const std::string& value) { bool Append(const std::string& value) {
int retval = android_log_write_string8_len(ctx, int retval =
value.data(), android_log_write_string8_len(ctx, value.data(), value.length());
value.length()); if (retval < 0) ret = retval;
if (retval < 0) ret = retval; return ret;
return ret; }
}
#endif #endif
bool AppendFloat(float value) { bool AppendFloat(float value) {
int retval = android_log_write_float32(ctx, value); int retval = android_log_write_float32(ctx, value);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return ret >= 0; return ret >= 0;
} }
template <typename Tvalue> template <typename Tvalue>
bool Append(Tvalue value) { *this << value; return ret >= 0; } bool Append(Tvalue value) {
*this << value;
return ret >= 0;
}
bool Append(const char* value, size_t len) { bool Append(const char* value, size_t len) {
int retval = android_log_write_string8_len(ctx, value, len); int retval = android_log_write_string8_len(ctx, value, len);
if (retval < 0) ret = retval; if (retval < 0) ret = retval;
return ret >= 0; return ret >= 0;
} }
android_log_list_element read() { return android_log_read_next(ctx); }
android_log_list_element peek() { return android_log_peek_next(ctx); }
android_log_list_element read() {
return android_log_read_next(ctx);
}
android_log_list_element peek() {
return android_log_peek_next(ctx);
}
}; };
} }
#endif #endif

View file

@ -24,17 +24,17 @@ extern "C" {
#ifndef log_id_t_defined #ifndef log_id_t_defined
#define log_id_t_defined #define log_id_t_defined
typedef enum log_id { typedef enum log_id {
LOG_ID_MIN = 0, LOG_ID_MIN = 0,
LOG_ID_MAIN = 0, LOG_ID_MAIN = 0,
LOG_ID_RADIO = 1, LOG_ID_RADIO = 1,
LOG_ID_EVENTS = 2, LOG_ID_EVENTS = 2,
LOG_ID_SYSTEM = 3, LOG_ID_SYSTEM = 3,
LOG_ID_CRASH = 4, LOG_ID_CRASH = 4,
LOG_ID_SECURITY = 5, LOG_ID_SECURITY = 5,
LOG_ID_KERNEL = 6, /* place last, third-parties can not use it */ LOG_ID_KERNEL = 6, /* place last, third-parties can not use it */
LOG_ID_MAX LOG_ID_MAX
} log_id_t; } log_id_t;
#endif #endif
#define sizeof_log_id_t sizeof(typeof_log_id_t) #define sizeof_log_id_t sizeof(typeof_log_id_t)
@ -43,8 +43,10 @@ typedef enum log_id {
/* /*
* Send a simple string to the log. * 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_write(int bufID, int prio, const char* tag,
int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...) const char* text);
int __android_log_buf_print(int bufID, int prio, const char* tag,
const char* fmt, ...)
#if defined(__GNUC__) #if defined(__GNUC__)
__attribute__((__format__(printf, 4, 5))) __attribute__((__format__(printf, 4, 5)))
#endif #endif

View file

@ -56,21 +56,19 @@ extern "C" {
#define __predict_false(exp) __builtin_expect((exp) != 0, 0) #define __predict_false(exp) __builtin_expect((exp) != 0, 0)
#endif #endif
#define android_writeLog(prio, tag, text) \ #define android_writeLog(prio, tag, text) __android_log_write(prio, tag, text)
__android_log_write(prio, tag, text)
#define android_printLog(prio, tag, ...) \ #define android_printLog(prio, tag, ...) \
__android_log_print(prio, tag, __VA_ARGS__) __android_log_print(prio, tag, __VA_ARGS__)
#define android_vprintLog(prio, cond, tag, ...) \ #define android_vprintLog(prio, cond, tag, ...) \
__android_log_vprint(prio, tag, __VA_ARGS__) __android_log_vprint(prio, tag, __VA_ARGS__)
/* /*
* Log macro that allows you to specify a number for the priority. * Log macro that allows you to specify a number for the priority.
*/ */
#ifndef LOG_PRI #ifndef LOG_PRI
#define LOG_PRI(priority, tag, ...) \ #define LOG_PRI(priority, tag, ...) android_printLog(priority, tag, __VA_ARGS__)
android_printLog(priority, tag, __VA_ARGS__)
#endif #endif
/* /*
@ -78,7 +76,7 @@ extern "C" {
*/ */
#ifndef LOG_PRI_VA #ifndef LOG_PRI_VA
#define LOG_PRI_VA(priority, tag, fmt, args) \ #define LOG_PRI_VA(priority, tag, fmt, args) \
android_vprintLog(priority, NULL, tag, fmt, args) android_vprintLog(priority, NULL, tag, fmt, args)
#endif #endif
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
@ -91,16 +89,17 @@ extern "C" {
/* Returns 2nd arg. Used to substitute default value if caller's vararg list /* Returns 2nd arg. Used to substitute default value if caller's vararg list
* is empty. * is empty.
*/ */
#define __android_second(dummy, second, ...) second #define __android_second(dummy, second, ...) second
/* If passed multiple args, returns ',' followed by all but 1st arg, otherwise /* If passed multiple args, returns ',' followed by all but 1st arg, otherwise
* returns nothing. * returns nothing.
*/ */
#define __android_rest(first, ...) , ## __VA_ARGS__ #define __android_rest(first, ...) , ##__VA_ARGS__
#define android_printAssert(cond, tag, ...) \ #define android_printAssert(cond, tag, ...) \
__android_log_assert(cond, tag, \ __android_log_assert(cond, tag, \
__android_second(0, ## __VA_ARGS__, NULL) __android_rest(__VA_ARGS__)) __android_second(0, ##__VA_ARGS__, NULL) \
__android_rest(__VA_ARGS__))
/* /*
* Log a fatal error. If the given condition fails, this stops program * Log a fatal error. If the given condition fails, this stops program
@ -109,15 +108,15 @@ extern "C" {
* is -inverted- from the normal assert() semantics. * is -inverted- from the normal assert() semantics.
*/ */
#ifndef LOG_ALWAYS_FATAL_IF #ifndef LOG_ALWAYS_FATAL_IF
#define LOG_ALWAYS_FATAL_IF(cond, ...) \ #define LOG_ALWAYS_FATAL_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) \
? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \ ? ((void)android_printAssert(#cond, LOG_TAG, ##__VA_ARGS__)) \
: (void)0 ) : (void)0)
#endif #endif
#ifndef LOG_ALWAYS_FATAL #ifndef LOG_ALWAYS_FATAL
#define LOG_ALWAYS_FATAL(...) \ #define LOG_ALWAYS_FATAL(...) \
( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) ) (((void)android_printAssert(NULL, LOG_TAG, ##__VA_ARGS__)))
#endif #endif
/* /*
@ -137,7 +136,7 @@ extern "C" {
#else #else
#ifndef LOG_FATAL_IF #ifndef LOG_FATAL_IF
#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__) #define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ##__VA_ARGS__)
#endif #endif
#ifndef LOG_FATAL #ifndef LOG_FATAL
#define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__) #define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__)
@ -150,7 +149,7 @@ extern "C" {
* Stripped out of release builds. Uses the current LOG_TAG. * Stripped out of release builds. Uses the current LOG_TAG.
*/ */
#ifndef ALOG_ASSERT #ifndef ALOG_ASSERT
#define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__) #define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ##__VA_ARGS__)
#endif #endif
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
@ -175,7 +174,12 @@ extern "C" {
#ifndef ALOGV #ifndef ALOGV
#define __ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) #define __ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
#if LOG_NDEBUG #if LOG_NDEBUG
#define ALOGV(...) do { if (0) { __ALOGV(__VA_ARGS__); } } while (0) #define ALOGV(...) \
do { \
if (0) { \
__ALOGV(__VA_ARGS__); \
} \
} while (0)
#else #else
#define ALOGV(...) __ALOGV(__VA_ARGS__) #define ALOGV(...) __ALOGV(__VA_ARGS__)
#endif #endif
@ -183,12 +187,11 @@ extern "C" {
#ifndef ALOGV_IF #ifndef ALOGV_IF
#if LOG_NDEBUG #if LOG_NDEBUG
#define ALOGV_IF(cond, ...) ((void)0) #define ALOGV_IF(cond, ...) ((void)0)
#else #else
#define ALOGV_IF(cond, ...) \ #define ALOGV_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) ? ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
? ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ : (void)0)
: (void)0 )
#endif #endif
#endif #endif
@ -200,10 +203,9 @@ extern "C" {
#endif #endif
#ifndef ALOGD_IF #ifndef ALOGD_IF
#define ALOGD_IF(cond, ...) \ #define ALOGD_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) ? ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
? ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ : (void)0)
: (void)0 )
#endif #endif
/* /*
@ -214,10 +216,9 @@ extern "C" {
#endif #endif
#ifndef ALOGI_IF #ifndef ALOGI_IF
#define ALOGI_IF(cond, ...) \ #define ALOGI_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) ? ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \
? ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \ : (void)0)
: (void)0 )
#endif #endif
/* /*
@ -228,10 +229,9 @@ extern "C" {
#endif #endif
#ifndef ALOGW_IF #ifndef ALOGW_IF
#define ALOGW_IF(cond, ...) \ #define ALOGW_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) ? ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \
? ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \ : (void)0)
: (void)0 )
#endif #endif
/* /*
@ -242,10 +242,9 @@ extern "C" {
#endif #endif
#ifndef ALOGE_IF #ifndef ALOGE_IF
#define ALOGE_IF(cond, ...) \ #define ALOGE_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) ? ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
? ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ : (void)0)
: (void)0 )
#endif #endif
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
@ -305,16 +304,14 @@ extern "C" {
* The second argument may be NULL or "" to indicate the "global" tag. * The second argument may be NULL or "" to indicate the "global" tag.
*/ */
#ifndef ALOG #ifndef ALOG
#define ALOG(priority, tag, ...) \ #define ALOG(priority, tag, ...) LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
#endif #endif
/* /*
* Conditional given a desired logging priority and tag. * Conditional given a desired logging priority and tag.
*/ */
#ifndef IF_ALOG #ifndef IF_ALOG
#define IF_ALOG(priority, tag) \ #define IF_ALOG(priority, tag) if (android_testLog(ANDROID_##priority, tag))
if (android_testLog(ANDROID_##priority, tag))
#endif #endif
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
@ -357,23 +354,23 @@ int __android_log_is_loggable_len(int prio, const char* tag, size_t len,
int default_prio); int default_prio);
#if LOG_NDEBUG /* Production */ #if LOG_NDEBUG /* Production */
#define android_testLog(prio, tag) \ #define android_testLog(prio, tag) \
(__android_log_is_loggable_len(prio, tag, (tag && *tag) ? strlen(tag) : 0, \ (__android_log_is_loggable_len(prio, tag, (tag && *tag) ? strlen(tag) : 0, \
ANDROID_LOG_DEBUG) != 0) ANDROID_LOG_DEBUG) != 0)
#else #else
#define android_testLog(prio, tag) \ #define android_testLog(prio, tag) \
(__android_log_is_loggable_len(prio, tag, (tag && *tag) ? strlen(tag) : 0, \ (__android_log_is_loggable_len(prio, tag, (tag && *tag) ? strlen(tag) : 0, \
ANDROID_LOG_VERBOSE) != 0) ANDROID_LOG_VERBOSE) != 0)
#endif #endif
#else #else
#if LOG_NDEBUG /* Production */ #if LOG_NDEBUG /* Production */
#define android_testLog(prio, tag) \ #define android_testLog(prio, tag) \
(__android_log_is_loggable(prio, tag, ANDROID_LOG_DEBUG) != 0) (__android_log_is_loggable(prio, tag, ANDROID_LOG_DEBUG) != 0)
#else #else
#define android_testLog(prio, tag) \ #define android_testLog(prio, tag) \
(__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE) != 0) (__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE) != 0)
#endif #endif
#endif #endif

View file

@ -46,10 +46,16 @@
* Simplified macro to send a verbose radio log message using current LOG_TAG. * Simplified macro to send a verbose radio log message using current LOG_TAG.
*/ */
#ifndef RLOGV #ifndef RLOGV
#define __RLOGV(...) \ #define __RLOGV(...) \
((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, \
__VA_ARGS__))
#if LOG_NDEBUG #if LOG_NDEBUG
#define RLOGV(...) do { if (0) { __RLOGV(__VA_ARGS__); } } while (0) #define RLOGV(...) \
do { \
if (0) { \
__RLOGV(__VA_ARGS__); \
} \
} while (0)
#else #else
#define RLOGV(...) __RLOGV(__VA_ARGS__) #define RLOGV(...) __RLOGV(__VA_ARGS__)
#endif #endif
@ -57,12 +63,13 @@
#ifndef RLOGV_IF #ifndef RLOGV_IF
#if LOG_NDEBUG #if LOG_NDEBUG
#define RLOGV_IF(cond, ...) ((void)0) #define RLOGV_IF(cond, ...) ((void)0)
#else #else
#define RLOGV_IF(cond, ...) \ #define RLOGV_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) \
? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, \
: (void)0 ) LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif #endif
#endif #endif
@ -70,60 +77,68 @@
* Simplified macro to send a debug radio log message using current LOG_TAG. * Simplified macro to send a debug radio log message using current LOG_TAG.
*/ */
#ifndef RLOGD #ifndef RLOGD
#define RLOGD(...) \ #define RLOGD(...) \
((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, \
__VA_ARGS__))
#endif #endif
#ifndef RLOGD_IF #ifndef RLOGD_IF
#define RLOGD_IF(cond, ...) \ #define RLOGD_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) \
? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, \
: (void)0 ) LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif #endif
/* /*
* Simplified macro to send an info radio log message using current LOG_TAG. * Simplified macro to send an info radio log message using current LOG_TAG.
*/ */
#ifndef RLOGI #ifndef RLOGI
#define RLOGI(...) \ #define RLOGI(...) \
((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, \
__VA_ARGS__))
#endif #endif
#ifndef RLOGI_IF #ifndef RLOGI_IF
#define RLOGI_IF(cond, ...) \ #define RLOGI_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) \
? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, \
: (void)0 ) LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif #endif
/* /*
* Simplified macro to send a warning radio log message using current LOG_TAG. * Simplified macro to send a warning radio log message using current LOG_TAG.
*/ */
#ifndef RLOGW #ifndef RLOGW
#define RLOGW(...) \ #define RLOGW(...) \
((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, \
__VA_ARGS__))
#endif #endif
#ifndef RLOGW_IF #ifndef RLOGW_IF
#define RLOGW_IF(cond, ...) \ #define RLOGW_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) \
? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, \
: (void)0 ) LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif #endif
/* /*
* Simplified macro to send an error radio log message using current LOG_TAG. * Simplified macro to send an error radio log message using current LOG_TAG.
*/ */
#ifndef RLOGE #ifndef RLOGE
#define RLOGE(...) \ #define RLOGE(...) \
((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, \
__VA_ARGS__))
#endif #endif
#ifndef RLOGE_IF #ifndef RLOGE_IF
#define RLOGE_IF(cond, ...) \ #define RLOGE_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) \
? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, \
: (void)0 ) LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif #endif
#endif /* _LIBS_LOG_LOG_RADIO_H */ #endif /* _LIBS_LOG_LOG_RADIO_H */

View file

@ -53,14 +53,14 @@ extern "C" {
#ifndef __struct_logger_entry_defined #ifndef __struct_logger_entry_defined
#define __struct_logger_entry_defined #define __struct_logger_entry_defined
struct logger_entry { struct logger_entry {
uint16_t len; /* length of the payload */ uint16_t len; /* length of the payload */
uint16_t __pad; /* no matter what, we get 2 bytes of padding */ uint16_t __pad; /* no matter what, we get 2 bytes of padding */
int32_t pid; /* generating process's pid */ int32_t pid; /* generating process's pid */
int32_t tid; /* generating process's tid */ int32_t tid; /* generating process's tid */
int32_t sec; /* seconds since Epoch */ int32_t sec; /* seconds since Epoch */
int32_t nsec; /* nanoseconds */ int32_t nsec; /* nanoseconds */
#ifndef __cplusplus #ifndef __cplusplus
char msg[0]; /* the entry's payload */ char msg[0]; /* the entry's payload */
#endif #endif
}; };
#endif #endif
@ -71,15 +71,15 @@ struct logger_entry {
#ifndef __struct_logger_entry_v2_defined #ifndef __struct_logger_entry_v2_defined
#define __struct_logger_entry_v2_defined #define __struct_logger_entry_v2_defined
struct logger_entry_v2 { struct logger_entry_v2 {
uint16_t len; /* length of the payload */ uint16_t len; /* length of the payload */
uint16_t hdr_size; /* sizeof(struct logger_entry_v2) */ uint16_t hdr_size; /* sizeof(struct logger_entry_v2) */
int32_t pid; /* generating process's pid */ int32_t pid; /* generating process's pid */
int32_t tid; /* generating process's tid */ int32_t tid; /* generating process's tid */
int32_t sec; /* seconds since Epoch */ int32_t sec; /* seconds since Epoch */
int32_t nsec; /* nanoseconds */ int32_t nsec; /* nanoseconds */
uint32_t euid; /* effective UID of logger */ uint32_t euid; /* effective UID of logger */
#ifndef __cplusplus #ifndef __cplusplus
char msg[0]; /* the entry's payload */ char msg[0]; /* the entry's payload */
#endif #endif
} __attribute__((__packed__)); } __attribute__((__packed__));
#endif #endif
@ -90,15 +90,15 @@ struct logger_entry_v2 {
#ifndef __struct_logger_entry_v3_defined #ifndef __struct_logger_entry_v3_defined
#define __struct_logger_entry_v3_defined #define __struct_logger_entry_v3_defined
struct logger_entry_v3 { struct logger_entry_v3 {
uint16_t len; /* length of the payload */ uint16_t len; /* length of the payload */
uint16_t hdr_size; /* sizeof(struct logger_entry_v3) */ uint16_t hdr_size; /* sizeof(struct logger_entry_v3) */
int32_t pid; /* generating process's pid */ int32_t pid; /* generating process's pid */
int32_t tid; /* generating process's tid */ int32_t tid; /* generating process's tid */
int32_t sec; /* seconds since Epoch */ int32_t sec; /* seconds since Epoch */
int32_t nsec; /* nanoseconds */ int32_t nsec; /* nanoseconds */
uint32_t lid; /* log id of the payload */ uint32_t lid; /* log id of the payload */
#ifndef __cplusplus #ifndef __cplusplus
char msg[0]; /* the entry's payload */ char msg[0]; /* the entry's payload */
#endif #endif
} __attribute__((__packed__)); } __attribute__((__packed__));
#endif #endif
@ -109,16 +109,16 @@ struct logger_entry_v3 {
#ifndef __struct_logger_entry_v4_defined #ifndef __struct_logger_entry_v4_defined
#define __struct_logger_entry_v4_defined #define __struct_logger_entry_v4_defined
struct logger_entry_v4 { struct logger_entry_v4 {
uint16_t len; /* length of the payload */ uint16_t len; /* length of the payload */
uint16_t hdr_size; /* sizeof(struct logger_entry_v4) */ uint16_t hdr_size; /* sizeof(struct logger_entry_v4) */
int32_t pid; /* generating process's pid */ int32_t pid; /* generating process's pid */
uint32_t tid; /* generating process's tid */ uint32_t tid; /* generating process's tid */
uint32_t sec; /* seconds since Epoch */ uint32_t sec; /* seconds since Epoch */
uint32_t nsec; /* nanoseconds */ uint32_t nsec; /* nanoseconds */
uint32_t lid; /* log id of the payload, bottom 4 bits currently */ uint32_t lid; /* log id of the payload, bottom 4 bits currently */
uint32_t uid; /* generating process's uid */ uint32_t uid; /* generating process's uid */
#ifndef __cplusplus #ifndef __cplusplus
char msg[0]; /* the entry's payload */ char msg[0]; /* the entry's payload */
#endif #endif
}; };
#endif #endif
@ -135,77 +135,64 @@ struct logger_entry_v4 {
* An attempt to read less than this amount may result * An attempt to read less than this amount may result
* in read() returning EINVAL. * in read() returning EINVAL.
*/ */
#define LOGGER_ENTRY_MAX_LEN (5*1024) #define LOGGER_ENTRY_MAX_LEN (5 * 1024)
#ifndef __struct_log_msg_defined #ifndef __struct_log_msg_defined
#define __struct_log_msg_defined #define __struct_log_msg_defined
struct log_msg { struct log_msg {
union { union {
unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1]; unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
struct logger_entry_v4 entry; struct logger_entry_v4 entry;
struct logger_entry_v4 entry_v4; struct logger_entry_v4 entry_v4;
struct logger_entry_v3 entry_v3; struct logger_entry_v3 entry_v3;
struct logger_entry_v2 entry_v2; struct logger_entry_v2 entry_v2;
struct logger_entry entry_v1; struct logger_entry entry_v1;
} __attribute__((aligned(4))); } __attribute__((aligned(4)));
#ifdef __cplusplus #ifdef __cplusplus
/* Matching log_time operators */ /* Matching log_time operators */
bool operator== (const log_msg& T) const bool operator==(const log_msg& T) const {
{ return (entry.sec == T.entry.sec) && (entry.nsec == T.entry.nsec);
return (entry.sec == T.entry.sec) && (entry.nsec == T.entry.nsec); }
} bool operator!=(const log_msg& T) const {
bool operator!= (const log_msg& T) const return !(*this == T);
{ }
return !(*this == T); bool operator<(const log_msg& T) const {
} return (entry.sec < T.entry.sec) ||
bool operator< (const log_msg& T) const ((entry.sec == T.entry.sec) && (entry.nsec < T.entry.nsec));
{ }
return (entry.sec < T.entry.sec) bool operator>=(const log_msg& T) const {
|| ((entry.sec == T.entry.sec) return !(*this < T);
&& (entry.nsec < T.entry.nsec)); }
} bool operator>(const log_msg& T) const {
bool operator>= (const log_msg& T) const return (entry.sec > T.entry.sec) ||
{ ((entry.sec == T.entry.sec) && (entry.nsec > T.entry.nsec));
return !(*this < T); }
} bool operator<=(const log_msg& T) const {
bool operator> (const log_msg& T) const return !(*this > T);
{ }
return (entry.sec > T.entry.sec) uint64_t nsec() const {
|| ((entry.sec == T.entry.sec) return static_cast<uint64_t>(entry.sec) * NS_PER_SEC + entry.nsec;
&& (entry.nsec > T.entry.nsec)); }
}
bool operator<= (const log_msg& T) const
{
return !(*this > T);
}
uint64_t nsec() const
{
return static_cast<uint64_t>(entry.sec) * NS_PER_SEC + entry.nsec;
}
/* packet methods */ /* packet methods */
log_id_t id() log_id_t id() {
{ return static_cast<log_id_t>(entry.lid);
return static_cast<log_id_t>(entry.lid); }
char* msg() {
unsigned short hdr_size = entry.hdr_size;
if (!hdr_size) {
hdr_size = sizeof(entry_v1);
} }
char* msg() if ((hdr_size < sizeof(entry_v1)) || (hdr_size > sizeof(entry))) {
{ return NULL;
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<char*>(buf) + hdr_size;
}
unsigned int len()
{
return (entry.hdr_size ?
entry.hdr_size :
static_cast<uint16_t>(sizeof(entry_v1))) +
entry.len;
} }
return reinterpret_cast<char*>(buf) + hdr_size;
}
unsigned int len() {
return (entry.hdr_size ? entry.hdr_size
: static_cast<uint16_t>(sizeof(entry_v1))) +
entry.len;
}
#endif #endif
}; };
#endif #endif
@ -243,32 +230,30 @@ ssize_t android_logger_get_statistics(struct logger_list* logger_list,
char* buf, size_t len); char* buf, size_t len);
ssize_t android_logger_get_prune_list(struct logger_list* logger_list, ssize_t android_logger_get_prune_list(struct logger_list* logger_list,
char* buf, size_t len); char* buf, size_t len);
int android_logger_set_prune_list(struct logger_list* logger_list, int android_logger_set_prune_list(struct logger_list* logger_list, char* buf,
char* buf, size_t len); size_t len);
#endif #endif
#define ANDROID_LOG_RDONLY O_RDONLY #define ANDROID_LOG_RDONLY O_RDONLY
#define ANDROID_LOG_WRONLY O_WRONLY #define ANDROID_LOG_WRONLY O_WRONLY
#define ANDROID_LOG_RDWR O_RDWR #define ANDROID_LOG_RDWR O_RDWR
#define ANDROID_LOG_ACCMODE O_ACCMODE #define ANDROID_LOG_ACCMODE O_ACCMODE
#ifndef O_NONBLOCK #ifndef O_NONBLOCK
#define ANDROID_LOG_NONBLOCK 0x00000800 #define ANDROID_LOG_NONBLOCK 0x00000800
#else #else
#define ANDROID_LOG_NONBLOCK O_NONBLOCK #define ANDROID_LOG_NONBLOCK O_NONBLOCK
#endif #endif
#if __ANDROID_USE_LIBLOG_READER_INTERFACE > 2 #if __ANDROID_USE_LIBLOG_READER_INTERFACE > 2
#define ANDROID_LOG_WRAP 0x40000000 /* Block until buffer about to wrap */ #define ANDROID_LOG_WRAP 0x40000000 /* Block until buffer about to wrap */
#define ANDROID_LOG_WRAP_DEFAULT_TIMEOUT 7200 /* 2 hour default */ #define ANDROID_LOG_WRAP_DEFAULT_TIMEOUT 7200 /* 2 hour default */
#endif #endif
#if __ANDROID_USE_LIBLOG_READER_INTERFACE > 1 #if __ANDROID_USE_LIBLOG_READER_INTERFACE > 1
#define ANDROID_LOG_PSTORE 0x80000000 #define ANDROID_LOG_PSTORE 0x80000000
#endif #endif
struct logger_list* android_logger_list_alloc(int mode, struct logger_list* android_logger_list_alloc(int mode, unsigned int tail,
unsigned int tail,
pid_t pid); pid_t pid);
struct logger_list* android_logger_list_alloc_time(int mode, struct logger_list* android_logger_list_alloc_time(int mode, log_time start,
log_time start,
pid_t pid); pid_t pid);
void android_logger_list_free(struct logger_list* logger_list); void android_logger_list_free(struct logger_list* logger_list);
/* In the purest sense, the following two are orthogonal interfaces */ /* In the purest sense, the following two are orthogonal interfaces */
@ -276,14 +261,11 @@ int android_logger_list_read(struct logger_list* logger_list,
struct log_msg* log_msg); struct log_msg* log_msg);
/* Multiple log_id_t opens */ /* Multiple log_id_t opens */
struct logger* android_logger_open(struct logger_list* logger_list, struct logger* android_logger_open(struct logger_list* logger_list, log_id_t id);
log_id_t id);
#define android_logger_close android_logger_free #define android_logger_close android_logger_free
/* Single log_id_t open */ /* Single log_id_t open */
struct logger_list* android_logger_list_open(log_id_t id, struct logger_list* android_logger_list_open(log_id_t id, int mode,
int mode, unsigned int tail, pid_t pid);
unsigned int tail,
pid_t pid);
#define android_logger_list_close android_logger_list_free #define android_logger_list_close android_logger_list_free
#endif /* __ANDROID_USE_LIBLOG_READER_INTERFACE */ #endif /* __ANDROID_USE_LIBLOG_READER_INTERFACE */

View file

@ -44,10 +44,16 @@
* Simplified macro to send a verbose system log message using current LOG_TAG. * Simplified macro to send a verbose system log message using current LOG_TAG.
*/ */
#ifndef SLOGV #ifndef SLOGV
#define __SLOGV(...) \ #define __SLOGV(...) \
((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, \
__VA_ARGS__))
#if LOG_NDEBUG #if LOG_NDEBUG
#define SLOGV(...) do { if (0) { __SLOGV(__VA_ARGS__); } } while (0) #define SLOGV(...) \
do { \
if (0) { \
__SLOGV(__VA_ARGS__); \
} \
} while (0)
#else #else
#define SLOGV(...) __SLOGV(__VA_ARGS__) #define SLOGV(...) __SLOGV(__VA_ARGS__)
#endif #endif
@ -55,12 +61,13 @@
#ifndef SLOGV_IF #ifndef SLOGV_IF
#if LOG_NDEBUG #if LOG_NDEBUG
#define SLOGV_IF(cond, ...) ((void)0) #define SLOGV_IF(cond, ...) ((void)0)
#else #else
#define SLOGV_IF(cond, ...) \ #define SLOGV_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) \
? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, \
: (void)0 ) LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif #endif
#endif #endif
@ -68,60 +75,68 @@
* Simplified macro to send a debug system log message using current LOG_TAG. * Simplified macro to send a debug system log message using current LOG_TAG.
*/ */
#ifndef SLOGD #ifndef SLOGD
#define SLOGD(...) \ #define SLOGD(...) \
((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, \
__VA_ARGS__))
#endif #endif
#ifndef SLOGD_IF #ifndef SLOGD_IF
#define SLOGD_IF(cond, ...) \ #define SLOGD_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) \
? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, \
: (void)0 ) LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif #endif
/* /*
* Simplified macro to send an info system log message using current LOG_TAG. * Simplified macro to send an info system log message using current LOG_TAG.
*/ */
#ifndef SLOGI #ifndef SLOGI
#define SLOGI(...) \ #define SLOGI(...) \
((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, \
__VA_ARGS__))
#endif #endif
#ifndef SLOGI_IF #ifndef SLOGI_IF
#define SLOGI_IF(cond, ...) \ #define SLOGI_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) \
? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, \
: (void)0 ) LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif #endif
/* /*
* Simplified macro to send a warning system log message using current LOG_TAG. * Simplified macro to send a warning system log message using current LOG_TAG.
*/ */
#ifndef SLOGW #ifndef SLOGW
#define SLOGW(...) \ #define SLOGW(...) \
((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, \
__VA_ARGS__))
#endif #endif
#ifndef SLOGW_IF #ifndef SLOGW_IF
#define SLOGW_IF(cond, ...) \ #define SLOGW_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) \
? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, \
: (void)0 ) LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif #endif
/* /*
* Simplified macro to send an error system log message using current LOG_TAG. * Simplified macro to send an error system log message using current LOG_TAG.
*/ */
#ifndef SLOGE #ifndef SLOGE
#define SLOGE(...) \ #define SLOGE(...) \
((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, \
__VA_ARGS__))
#endif #endif
#ifndef SLOGE_IF #ifndef SLOGE_IF
#define SLOGE_IF(cond, ...) \ #define SLOGE_IF(cond, ...) \
( (__predict_false(cond)) \ ((__predict_false(cond)) \
? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, \
: (void)0 ) LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif #endif
#endif /* _LIBS_LOG_LOG_SYSTEM_H */ #endif /* _LIBS_LOG_LOG_SYSTEM_H */

View file

@ -34,159 +34,135 @@
* efficient behavior. Also, pass-by-reference breaks C/C++ ABI. * efficient behavior. Also, pass-by-reference breaks C/C++ ABI.
*/ */
struct log_time { struct log_time {
public: public:
uint32_t tv_sec; /* good to Feb 5 2106 */ uint32_t tv_sec; /* good to Feb 5 2106 */
uint32_t tv_nsec; uint32_t tv_nsec;
static const uint32_t tv_sec_max = 0xFFFFFFFFUL; static const uint32_t tv_sec_max = 0xFFFFFFFFUL;
static const uint32_t tv_nsec_max = 999999999UL; static const uint32_t tv_nsec_max = 999999999UL;
log_time(const timespec& T) log_time(const timespec& T) {
{ tv_sec = static_cast<uint32_t>(T.tv_sec);
tv_sec = static_cast<uint32_t>(T.tv_sec); tv_nsec = static_cast<uint32_t>(T.tv_nsec);
tv_nsec = static_cast<uint32_t>(T.tv_nsec); }
} log_time(uint32_t sec, uint32_t nsec) {
log_time(uint32_t sec, uint32_t nsec) tv_sec = sec;
{ tv_nsec = nsec;
tv_sec = sec; }
tv_nsec = nsec;
}
#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_ #ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
#define __struct_log_time_private_defined #define __struct_log_time_private_defined
static const timespec EPOCH; static const timespec EPOCH;
#endif #endif
log_time() log_time() {
{ }
}
#ifdef __linux__ #ifdef __linux__
log_time(clockid_t id) log_time(clockid_t id) {
{ timespec T;
timespec T; clock_gettime(id, &T);
clock_gettime(id, &T); tv_sec = static_cast<uint32_t>(T.tv_sec);
tv_sec = static_cast<uint32_t>(T.tv_sec); tv_nsec = static_cast<uint32_t>(T.tv_nsec);
tv_nsec = static_cast<uint32_t>(T.tv_nsec); }
}
#endif #endif
log_time(const char* T) log_time(const char* T) {
{ const uint8_t* c = reinterpret_cast<const uint8_t*>(T);
const uint8_t* c = reinterpret_cast<const uint8_t*>(T); tv_sec = c[0] | (static_cast<uint32_t>(c[1]) << 8) |
tv_sec = c[0] | (static_cast<uint32_t>(c[2]) << 16) |
(static_cast<uint32_t>(c[1]) << 8) | (static_cast<uint32_t>(c[3]) << 24);
(static_cast<uint32_t>(c[2]) << 16) | tv_nsec = c[4] | (static_cast<uint32_t>(c[5]) << 8) |
(static_cast<uint32_t>(c[3]) << 24); (static_cast<uint32_t>(c[6]) << 16) |
tv_nsec = c[4] | (static_cast<uint32_t>(c[7]) << 24);
(static_cast<uint32_t>(c[5]) << 8) | }
(static_cast<uint32_t>(c[6]) << 16) |
(static_cast<uint32_t>(c[7]) << 24);
}
/* timespec */ /* timespec */
bool operator== (const timespec& T) const bool operator==(const timespec& T) const {
{ return (tv_sec == static_cast<uint32_t>(T.tv_sec)) &&
return (tv_sec == static_cast<uint32_t>(T.tv_sec)) (tv_nsec == static_cast<uint32_t>(T.tv_nsec));
&& (tv_nsec == static_cast<uint32_t>(T.tv_nsec)); }
} bool operator!=(const timespec& T) const {
bool operator!= (const timespec& T) const return !(*this == T);
{ }
return !(*this == T); bool operator<(const timespec& T) const {
} return (tv_sec < static_cast<uint32_t>(T.tv_sec)) ||
bool operator< (const timespec& T) const ((tv_sec == static_cast<uint32_t>(T.tv_sec)) &&
{ (tv_nsec < static_cast<uint32_t>(T.tv_nsec)));
return (tv_sec < static_cast<uint32_t>(T.tv_sec)) }
|| ((tv_sec == static_cast<uint32_t>(T.tv_sec)) bool operator>=(const timespec& T) const {
&& (tv_nsec < static_cast<uint32_t>(T.tv_nsec))); return !(*this < T);
} }
bool operator>= (const timespec& T) const bool operator>(const timespec& T) const {
{ return (tv_sec > static_cast<uint32_t>(T.tv_sec)) ||
return !(*this < T); ((tv_sec == static_cast<uint32_t>(T.tv_sec)) &&
} (tv_nsec > static_cast<uint32_t>(T.tv_nsec)));
bool operator> (const timespec& T) const }
{ bool operator<=(const timespec& T) const {
return (tv_sec > static_cast<uint32_t>(T.tv_sec)) return !(*this > T);
|| ((tv_sec == static_cast<uint32_t>(T.tv_sec)) }
&& (tv_nsec > static_cast<uint32_t>(T.tv_nsec)));
}
bool operator<= (const timespec& T) const
{
return !(*this > T);
}
#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_ #ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
log_time operator-= (const timespec& T); log_time operator-=(const timespec& T);
log_time operator- (const timespec& T) const log_time operator-(const timespec& T) const {
{ log_time local(*this);
log_time local(*this); return local -= T;
return local -= T; }
} log_time operator+=(const timespec& T);
log_time operator+= (const timespec& T); log_time operator+(const timespec& T) const {
log_time operator+ (const timespec& T) const log_time local(*this);
{ return local += T;
log_time local(*this); }
return local += T;
}
#endif #endif
/* log_time */ /* log_time */
bool operator== (const log_time& T) const bool operator==(const log_time& T) const {
{ return (tv_sec == T.tv_sec) && (tv_nsec == T.tv_nsec);
return (tv_sec == T.tv_sec) && (tv_nsec == T.tv_nsec); }
} bool operator!=(const log_time& T) const {
bool operator!= (const log_time& T) const return !(*this == T);
{ }
return !(*this == T); bool operator<(const log_time& T) const {
} return (tv_sec < T.tv_sec) ||
bool operator< (const log_time& T) const ((tv_sec == T.tv_sec) && (tv_nsec < T.tv_nsec));
{ }
return (tv_sec < T.tv_sec) bool operator>=(const log_time& T) const {
|| ((tv_sec == T.tv_sec) && (tv_nsec < T.tv_nsec)); return !(*this < T);
} }
bool operator>= (const log_time& T) const bool operator>(const log_time& T) const {
{ return (tv_sec > T.tv_sec) ||
return !(*this < T); ((tv_sec == T.tv_sec) && (tv_nsec > T.tv_nsec));
} }
bool operator> (const log_time& T) const bool operator<=(const log_time& T) const {
{ return !(*this > T);
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_ #ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
log_time operator-= (const log_time& T); log_time operator-=(const log_time& T);
log_time operator- (const log_time& T) const log_time operator-(const log_time& T) const {
{ log_time local(*this);
log_time local(*this); return local -= T;
return local -= T; }
} log_time operator+=(const log_time& T);
log_time operator+= (const log_time& T); log_time operator+(const log_time& T) const {
log_time operator+ (const log_time& T) const log_time local(*this);
{ return local += T;
log_time local(*this); }
return local += T;
}
#endif #endif
uint64_t nsec() const uint64_t nsec() const {
{ return static_cast<uint64_t>(tv_sec) * NS_PER_SEC + tv_nsec;
return static_cast<uint64_t>(tv_sec) * NS_PER_SEC + tv_nsec; }
}
#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_ #ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
static const char default_format[]; static const char default_format[];
/* Add %#q for the fraction of a second to the standard library functions */ /* Add %#q for the fraction of a second to the standard library functions */
char* strptime(const char* s, const char* format = default_format); char* strptime(const char* s, const char* format = default_format);
#endif #endif
} __attribute__((__packed__)); } __attribute__((__packed__));
#else #else
typedef struct log_time { typedef struct log_time {
uint32_t tv_sec; uint32_t tv_sec;
uint32_t tv_nsec; uint32_t tv_nsec;
} __attribute__((__packed__)) log_time; } __attribute__((__packed__)) log_time;
#endif #endif

View file

@ -7,29 +7,31 @@
** General Public License. ** General Public License.
*/ */
#ifndef _LIBS_LOG_FRONTEND_H #ifndef _LIBS_LOG_TRANSPORT_H
#define _LIBS_LOG_FRONTEND_H #define _LIBS_LOG_TRANSPORT_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* /*
* Logging frontends, bit mask to select features. Function returns selection. * Logging transports, bit mask to select features. Function returns selection.
*/ */
/* clang-format off */
#define LOGGER_DEFAULT 0x00 #define LOGGER_DEFAULT 0x00
#define LOGGER_LOGD 0x01 #define LOGGER_LOGD 0x01
#define LOGGER_KERNEL 0x02 /* Reserved/Deprecated */ #define LOGGER_KERNEL 0x02 /* Reserved/Deprecated */
#define LOGGER_NULL 0x04 /* Does not release resources of other selections */ #define LOGGER_NULL 0x04 /* Does not release resources of other selections */
#define LOGGER_LOCAL 0x08 /* logs sent to local memory */ #define LOGGER_LOCAL 0x08 /* logs sent to local memory */
#define LOGGER_STDERR 0x10 /* logs sent to stderr */ #define LOGGER_STDERR 0x10 /* logs sent to stderr */
/* clang-format on */
/* Both return the selected frontend flag mask, or negative errno */ /* Both return the selected transport flag mask, or negative errno */
int android_set_log_frontend(int frontend_flag); int android_set_log_transport(int transport_flag);
int android_get_log_frontend(); int android_get_log_transport();
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _LIBS_LOG_FRONTEND_H */ #endif /* _LIBS_LOG_TRANSPORT_H */

View file

@ -27,43 +27,43 @@ extern "C" {
#endif #endif
typedef enum { typedef enum {
/* Verbs */ /* Verbs */
FORMAT_OFF = 0, FORMAT_OFF = 0,
FORMAT_BRIEF, FORMAT_BRIEF,
FORMAT_PROCESS, FORMAT_PROCESS,
FORMAT_TAG, FORMAT_TAG,
FORMAT_THREAD, FORMAT_THREAD,
FORMAT_RAW, FORMAT_RAW,
FORMAT_TIME, FORMAT_TIME,
FORMAT_THREADTIME, FORMAT_THREADTIME,
FORMAT_LONG, FORMAT_LONG,
/* Adverbs. The following are modifiers to above format verbs */ /* Adverbs. The following are modifiers to above format verbs */
FORMAT_MODIFIER_COLOR, /* converts priority to color */ FORMAT_MODIFIER_COLOR, /* converts priority to color */
FORMAT_MODIFIER_TIME_USEC, /* switches from msec to usec time precision */ FORMAT_MODIFIER_TIME_USEC, /* switches from msec to usec time precision */
FORMAT_MODIFIER_PRINTABLE, /* converts non-printable to printable escapes */ FORMAT_MODIFIER_PRINTABLE, /* converts non-printable to printable escapes */
FORMAT_MODIFIER_YEAR, /* Adds year to date */ FORMAT_MODIFIER_YEAR, /* Adds year to date */
FORMAT_MODIFIER_ZONE, /* Adds zone to date, + UTC */ FORMAT_MODIFIER_ZONE, /* Adds zone to date, + UTC */
FORMAT_MODIFIER_EPOCH, /* Print time as seconds since Jan 1 1970 */ FORMAT_MODIFIER_EPOCH, /* Print time as seconds since Jan 1 1970 */
FORMAT_MODIFIER_MONOTONIC, /* Print cpu time as seconds since start */ FORMAT_MODIFIER_MONOTONIC, /* Print cpu time as seconds since start */
FORMAT_MODIFIER_UID, /* Adds uid */ FORMAT_MODIFIER_UID, /* Adds uid */
FORMAT_MODIFIER_DESCRIPT, /* Adds descriptive */ FORMAT_MODIFIER_DESCRIPT, /* Adds descriptive */
/* private, undocumented */ /* private, undocumented */
FORMAT_MODIFIER_TIME_NSEC, /* switches from msec to nsec time precision */ FORMAT_MODIFIER_TIME_NSEC, /* switches from msec to nsec time precision */
} AndroidLogPrintFormat; } AndroidLogPrintFormat;
typedef struct AndroidLogFormat_t AndroidLogFormat; typedef struct AndroidLogFormat_t AndroidLogFormat;
typedef struct AndroidLogEntry_t { typedef struct AndroidLogEntry_t {
time_t tv_sec; time_t tv_sec;
long tv_nsec; long tv_nsec;
android_LogPriority priority; android_LogPriority priority;
int32_t uid; int32_t uid;
int32_t pid; int32_t pid;
int32_t tid; int32_t tid;
const char* tag; const char* tag;
size_t tagLen; size_t tagLen;
size_t messageLen; size_t messageLen;
const char* message; const char* message;
} AndroidLogEntry; } AndroidLogEntry;
AndroidLogFormat* android_log_format_new(); AndroidLogFormat* android_log_format_new();
@ -72,7 +72,7 @@ void android_log_format_free(AndroidLogFormat* p_format);
/* currently returns 0 if format is a modifier, 1 if not */ /* currently returns 0 if format is a modifier, 1 if not */
int android_log_setPrintFormat(AndroidLogFormat* p_format, int android_log_setPrintFormat(AndroidLogFormat* p_format,
AndroidLogPrintFormat format); AndroidLogPrintFormat format);
/** /**
* Returns FORMAT_OFF on invalid string * Returns FORMAT_OFF on invalid string
@ -90,7 +90,7 @@ AndroidLogPrintFormat android_log_formatFromString(const char* s);
*/ */
int android_log_addFilterRule(AndroidLogFormat* p_format, int android_log_addFilterRule(AndroidLogFormat* p_format,
const char* filterExpression); const char* filterExpression);
/** /**
* filterString: a whitespace-separated set of filter expressions * filterString: a whitespace-separated set of filter expressions
@ -103,14 +103,14 @@ int android_log_addFilterRule(AndroidLogFormat* p_format,
*/ */
int android_log_addFilterString(AndroidLogFormat* p_format, int android_log_addFilterString(AndroidLogFormat* p_format,
const char* filterString); const char* filterString);
/** /**
* returns 1 if this log line should be printed based on its priority * returns 1 if this log line should be printed based on its priority
* and tag, and 0 if it should not * and tag, and 0 if it should not
*/ */
int android_log_shouldPrintLine ( int android_log_shouldPrintLine(AndroidLogFormat* p_format, const char* tag,
AndroidLogFormat* p_format, const char* tag, android_LogPriority pri); android_LogPriority pri);
/** /**
* Splits a wire-format buffer into an AndroidLogEntry * Splits a wire-format buffer into an AndroidLogEntry
@ -129,8 +129,9 @@ int android_log_processLogBuffer(struct logger_entry* buf,
* into a string. * into a string.
*/ */
int android_log_processBinaryLogBuffer(struct logger_entry* buf, int android_log_processBinaryLogBuffer(struct logger_entry* buf,
AndroidLogEntry* entry, const EventTagMap* map, char* messageBuf, AndroidLogEntry* entry,
int messageBufLen); const EventTagMap* map, char* messageBuf,
int messageBufLen);
/** /**
* Formats a log message into a buffer * Formats a log message into a buffer
@ -140,12 +141,10 @@ int android_log_processBinaryLogBuffer(struct logger_entry* buf,
* Returns NULL on malloc error * Returns NULL on malloc error
*/ */
char* android_log_formatLogLine ( char* android_log_formatLogLine(AndroidLogFormat* p_format, char* defaultBuffer,
AndroidLogFormat* p_format, size_t defaultBufferSize,
char* defaultBuffer, const AndroidLogEntry* p_line,
size_t defaultBufferSize, size_t* p_outLength);
const AndroidLogEntry* p_line,
size_t* p_outLength);
/** /**
* Either print or do not print log line, based on filter * Either print or do not print log line, based on filter
@ -153,10 +152,8 @@ char* android_log_formatLogLine (
* Assumes single threaded execution * Assumes single threaded execution
* *
*/ */
int android_log_printLogLine( int android_log_printLogLine(AndroidLogFormat* p_format, int fd,
AndroidLogFormat* p_format, const AndroidLogEntry* entry);
int fd,
const AndroidLogEntry* entry);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -34,12 +34,12 @@ extern "C" {
#include <stddef.h> #include <stddef.h>
struct iovec { struct iovec {
void* iov_base; void* iov_base;
size_t iov_len; size_t iov_len;
}; };
extern int readv( int fd, struct iovec* vecs, int count ); extern int readv(int fd, struct iovec* vecs, int count);
extern int writev( int fd, const struct iovec* vecs, int count ); extern int writev(int fd, const struct iovec* vecs, int count);
#ifdef __cplusplus #ifdef __cplusplus
} }
@ -48,4 +48,3 @@ extern int writev( int fd, const struct iovec* vecs, int count );
#endif #endif
#endif /* _LIBS_UTILS_UIO_H */ #endif /* _LIBS_UTILS_UIO_H */

View file

@ -31,8 +31,8 @@ extern "C++" {
} }
#endif #endif
#include <log/log_event_list.h>
#include <log/log.h> #include <log/log.h>
#include <log/log_event_list.h>
#define LOGGER_MAGIC 'l' #define LOGGER_MAGIC 'l'
@ -42,46 +42,46 @@ extern "C" {
/* Header Structure to pstore */ /* Header Structure to pstore */
typedef struct __attribute__((__packed__)) { typedef struct __attribute__((__packed__)) {
uint8_t magic; uint8_t magic;
uint16_t len; uint16_t len;
uint16_t uid; uint16_t uid;
uint16_t pid; uint16_t pid;
} android_pmsg_log_header_t; } android_pmsg_log_header_t;
/* Header Structure to logd, and second header for pstore */ /* Header Structure to logd, and second header for pstore */
typedef struct __attribute__((__packed__)) { typedef struct __attribute__((__packed__)) {
typeof_log_id_t id; typeof_log_id_t id;
uint16_t tid; uint16_t tid;
log_time realtime; log_time realtime;
} android_log_header_t; } android_log_header_t;
/* Event Header Structure to logd */ /* Event Header Structure to logd */
typedef struct __attribute__((__packed__)) { typedef struct __attribute__((__packed__)) {
int32_t tag; // Little Endian Order int32_t tag; // Little Endian Order
} android_event_header_t; } android_event_header_t;
/* Event payload EVENT_TYPE_INT */ /* Event payload EVENT_TYPE_INT */
typedef struct __attribute__((__packed__)) { typedef struct __attribute__((__packed__)) {
int8_t type; // EVENT_TYPE_INT int8_t type; // EVENT_TYPE_INT
int32_t data; // Little Endian Order int32_t data; // Little Endian Order
} android_event_int_t; } android_event_int_t;
/* Event with single EVENT_TYPE_INT */ /* Event with single EVENT_TYPE_INT */
typedef struct __attribute__((__packed__)) { typedef struct __attribute__((__packed__)) {
android_event_header_t header; android_event_header_t header;
android_event_int_t payload; android_event_int_t payload;
} android_log_event_int_t; } android_log_event_int_t;
/* Event payload EVENT_TYPE_LONG */ /* Event payload EVENT_TYPE_LONG */
typedef struct __attribute__((__packed__)) { typedef struct __attribute__((__packed__)) {
int8_t type; // EVENT_TYPE_LONG int8_t type; // EVENT_TYPE_LONG
int64_t data; // Little Endian Order int64_t data; // Little Endian Order
} android_event_long_t; } android_event_long_t;
/* Event with single EVENT_TYPE_LONG */ /* Event with single EVENT_TYPE_LONG */
typedef struct __attribute__((__packed__)) { typedef struct __attribute__((__packed__)) {
android_event_header_t header; android_event_header_t header;
android_event_long_t payload; android_event_long_t payload;
} android_log_event_long_t; } android_log_event_long_t;
/* /*
@ -97,41 +97,39 @@ typedef struct __attribute__((__packed__)) {
*/ */
typedef struct __attribute__((__packed__)) { typedef struct __attribute__((__packed__)) {
int8_t type; // EVENT_TYPE_STRING; int8_t type; // EVENT_TYPE_STRING;
int32_t length; // Little Endian Order int32_t length; // Little Endian Order
char data[]; char data[];
} android_event_string_t; } android_event_string_t;
/* Event with single EVENT_TYPE_STRING */ /* Event with single EVENT_TYPE_STRING */
typedef struct __attribute__((__packed__)) { typedef struct __attribute__((__packed__)) {
android_event_header_t header; android_event_header_t header;
int8_t type; // EVENT_TYPE_STRING; int8_t type; // EVENT_TYPE_STRING;
int32_t length; // Little Endian Order int32_t length; // Little Endian Order
char data[]; char data[];
} android_log_event_string_t; } android_log_event_string_t;
#define ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE 256 /* 1MB file */ #define ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE 256 /* 1MB file */
#define ANDROID_LOG_PMSG_FILE_SEQUENCE 1000 #define ANDROID_LOG_PMSG_FILE_SEQUENCE 1000
ssize_t __android_log_pmsg_file_write( ssize_t __android_log_pmsg_file_write(log_id_t logId, char prio,
log_id_t logId, const char* filename, const char* buf,
char prio, size_t len);
const char* filename,
const char* buf, size_t len);
#define LOG_ID_ANY ((log_id_t)-1) #define LOG_ID_ANY ((log_id_t)-1)
#define ANDROID_LOG_ANY ANDROID_LOG_UNKNOWN #define ANDROID_LOG_ANY ANDROID_LOG_UNKNOWN
/* first 5 arguments match __android_log_msg_file_write, a cast is safe */ /* first 5 arguments match __android_log_msg_file_write, a cast is safe */
typedef ssize_t (*__android_log_pmsg_file_read_fn)( typedef ssize_t (*__android_log_pmsg_file_read_fn)(log_id_t logId, char prio,
log_id_t logId, const char* filename,
char prio, const char* buf, size_t len,
const char* filename, void* arg);
const char* buf, size_t len, void* arg);
ssize_t __android_log_pmsg_file_read( ssize_t __android_log_pmsg_file_read(log_id_t logId, char prio,
log_id_t logId, char prio, const char* prefix, const char* prefix,
__android_log_pmsg_file_read_fn fn, void* arg); __android_log_pmsg_file_read_fn fn,
void* arg);
int __android_log_security_bwrite(int32_t tag, const void* payload, size_t len); int __android_log_security_bwrite(int32_t tag, const void* payload, size_t len);
int __android_log_security_bswrite(int32_t tag, const char* payload); int __android_log_security_bswrite(int32_t tag, const char* payload);
@ -140,14 +138,15 @@ int __android_log_security(); /* Device Owner is present */
int __android_log_is_debuggable(); int __android_log_is_debuggable();
#define BOOL_DEFAULT_FLAG_TRUE_FALSE 0x1 #define BOOL_DEFAULT_FLAG_TRUE_FALSE 0x1
#define BOOL_DEFAULT_FALSE 0x0 /* false if property not present */ #define BOOL_DEFAULT_FALSE 0x0 /* false if property not present */
#define BOOL_DEFAULT_TRUE 0x1 /* true if property not present */ #define BOOL_DEFAULT_TRUE 0x1 /* true if property not present */
#define BOOL_DEFAULT_FLAG_PERSIST 0x2 /* <key>, persist.<key>, ro.<key> */ #define BOOL_DEFAULT_FLAG_PERSIST 0x2 /* <key>, persist.<key>, ro.<key> */
#define BOOL_DEFAULT_FLAG_ENG 0x4 /* off for user */ #define BOOL_DEFAULT_FLAG_ENG 0x4 /* off for user */
#define BOOL_DEFAULT_FLAG_SVELTE 0x8 /* off for low_ram */ #define BOOL_DEFAULT_FLAG_SVELTE 0x8 /* off for low_ram */
bool __android_logger_property_get_bool(const char* key, int flag); bool __android_logger_property_get_bool(const char* key, int flag);
#define LOG_BUFFER_SIZE (256 * 1024) /* Tuned with ro.logd.size per-platform */ #define LOG_BUFFER_SIZE (256 * 1024) /* Tuned with ro.logd.size per-platform \
*/
#define LOG_BUFFER_MIN_SIZE (64 * 1024UL) #define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL) #define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
unsigned long __android_logger_get_buffer_size(log_id_t logId); unsigned long __android_logger_get_buffer_size(log_id_t logId);
@ -163,24 +162,26 @@ int android_log_write_list_buffer(android_log_context ctx, const char** msg);
/* android_log_context C++ helpers */ /* android_log_context C++ helpers */
extern "C++" { extern "C++" {
class __android_log_event_list : public android_log_event_list { class __android_log_event_list : public android_log_event_list {
__android_log_event_list(const android_log_event_list&) = delete; __android_log_event_list(const android_log_event_list&) = delete;
void operator =(const __android_log_event_list&) = delete; void operator=(const __android_log_event_list&) = delete;
public: public:
explicit __android_log_event_list(int tag) : android_log_event_list(tag) { } explicit __android_log_event_list(int tag) : android_log_event_list(tag) {
explicit __android_log_event_list(log_msg& log_msg) : android_log_event_list(log_msg) { } }
explicit __android_log_event_list(log_msg& log_msg)
: android_log_event_list(log_msg) {
}
#if defined(_USING_LIBCXX) #if defined(_USING_LIBCXX)
operator std::string() { operator std::string() {
if (ret) return std::string(""); if (ret) return std::string("");
const char* cp = NULL; const char* cp = NULL;
ssize_t len = android_log_write_list_buffer(ctx, &cp); ssize_t len = android_log_write_list_buffer(ctx, &cp);
if (len < 0) ret = len; if (len < 0) ret = len;
if (!cp || (len <= 0)) return std::string(""); if (!cp || (len <= 0)) return std::string("");
return std::string(cp, len); return std::string(cp, len);
} }
#endif #endif
}; };
} }
#endif #endif

View file

@ -20,14 +20,14 @@
#if !defined(__MINGW32__) #if !defined(__MINGW32__)
#include <pwd.h> #include <pwd.h>
#endif #endif
#include <log/uio.h>
#include <sched.h> #include <sched.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <log/uio.h>
#include <cutils/list.h> /* template, no library dependency */ #include <cutils/list.h> /* template, no library dependency */
#include <log/log_frontend.h> #include <log/log_transport.h>
#include <private/android_filesystem_config.h> #include <private/android_filesystem_config.h>
#include <private/android_logger.h> #include <private/android_logger.h>
#include <system/thread_defs.h> #include <system/thread_defs.h>
@ -42,56 +42,54 @@ static const char baseServiceName[] = "android.logd";
static int writeToLocalInit(); static int writeToLocalInit();
static int writeToLocalAvailable(log_id_t logId); static int writeToLocalAvailable(log_id_t logId);
static void writeToLocalReset(); static void writeToLocalReset();
static int writeToLocalWrite(log_id_t logId, struct timespec *ts, static int writeToLocalWrite(log_id_t logId, struct timespec* ts,
struct iovec *vec, size_t nr); struct iovec* vec, size_t nr);
LIBLOG_HIDDEN struct android_log_transport_write localLoggerWrite = { LIBLOG_HIDDEN struct android_log_transport_write localLoggerWrite = {
.node = { &localLoggerWrite.node, &localLoggerWrite.node }, .node = { &localLoggerWrite.node, &localLoggerWrite.node },
.context.private = NULL, .context.priv = NULL,
.name = "local", .name = "local",
.available = writeToLocalAvailable, .available = writeToLocalAvailable,
.open = writeToLocalInit, .open = writeToLocalInit,
.close = writeToLocalReset, .close = writeToLocalReset,
.write = writeToLocalWrite, .write = writeToLocalWrite,
}; };
static int writeToLocalVersion(struct android_log_logger *logger, static int writeToLocalVersion(struct android_log_logger* logger,
struct android_log_transport_context *transp); struct android_log_transport_context* transp);
static int writeToLocalRead(struct android_log_logger_list *logger_list, static int writeToLocalRead(struct android_log_logger_list* logger_list,
struct android_log_transport_context *transp, struct android_log_transport_context* transp,
struct log_msg *log_msg); struct log_msg* log_msg);
static int writeToLocalPoll(struct android_log_logger_list *logger_list, static int writeToLocalPoll(struct android_log_logger_list* logger_list,
struct android_log_transport_context *transp); struct android_log_transport_context* transp);
static void writeToLocalClose(struct android_log_logger_list *logger_list, static void writeToLocalClose(struct android_log_logger_list* logger_list,
struct android_log_transport_context *transp); struct android_log_transport_context* transp);
static int writeToLocalClear(struct android_log_logger *logger, static int writeToLocalClear(struct android_log_logger* logger,
struct android_log_transport_context *transp); struct android_log_transport_context* transp);
static ssize_t writeToLocalGetSize( static ssize_t writeToLocalGetSize(struct android_log_logger* logger,
struct android_log_logger *logger, struct android_log_transport_context* transp);
struct android_log_transport_context *transp);
static ssize_t writeToLocalSetSize( static ssize_t writeToLocalSetSize(
struct android_log_logger *logger, struct android_log_logger* logger,
struct android_log_transport_context *transp __unused, struct android_log_transport_context* transp __unused, size_t size);
size_t size);
static ssize_t writeToLocalGetReadbleSize( static ssize_t writeToLocalGetReadbleSize(
struct android_log_logger *logger, struct android_log_logger* logger,
struct android_log_transport_context *transp); struct android_log_transport_context* transp);
struct android_log_transport_read localLoggerRead = { struct android_log_transport_read localLoggerRead = {
.node = { &localLoggerRead.node, &localLoggerRead.node }, .node = { &localLoggerRead.node, &localLoggerRead.node },
.name = "local", .name = "local",
.available = writeToLocalAvailable, .available = writeToLocalAvailable,
.version = writeToLocalVersion, .version = writeToLocalVersion,
.read = writeToLocalRead, .read = writeToLocalRead,
.poll = writeToLocalPoll, .poll = writeToLocalPoll,
.close = writeToLocalClose, .close = writeToLocalClose,
.clear = writeToLocalClear, .clear = writeToLocalClear,
.getSize = writeToLocalGetSize, .getSize = writeToLocalGetSize,
.setSize = writeToLocalSetSize, .setSize = writeToLocalSetSize,
.getReadableSize = writeToLocalGetReadbleSize, .getReadableSize = writeToLocalGetReadbleSize,
.getPrune = NULL, .getPrune = NULL,
.setPrune = NULL, .setPrune = NULL,
.getStats = NULL, .getStats = NULL,
}; };
struct LogBufferElement { struct LogBufferElement {
@ -115,53 +113,51 @@ static const size_t MAX_SIZE_DEFAULT = 32768;
* *
* Confirm the following should <log/log_id.h> be adjusted in the future. * Confirm the following should <log/log_id.h> be adjusted in the future.
*/ */
#define NUMBER_OF_LOG_BUFFERS ((LOG_ID_SECURITY == (LOG_ID_MAX - 2)) ? \ #define NUMBER_OF_LOG_BUFFERS \
LOG_ID_SECURITY : \ ((LOG_ID_SECURITY == (LOG_ID_MAX - 2)) ? LOG_ID_SECURITY : LOG_ID_KERNEL)
LOG_ID_KERNEL) #define BLOCK_LOG_BUFFERS(id) \
#define BLOCK_LOG_BUFFERS(id) (((id) == LOG_ID_SECURITY) || \ (((id) == LOG_ID_SECURITY) || ((id) == LOG_ID_KERNEL))
((id) == LOG_ID_KERNEL))
static struct LogBuffer { static struct LogBuffer {
struct listnode head; struct listnode head;
pthread_rwlock_t listLock; pthread_rwlock_t listLock;
char *serviceName; /* Also indicates ready by having a value */ char* serviceName; /* Also indicates ready by having a value */
/* Order and proximity important for memset */ /* Order and proximity important for memset */
size_t number[NUMBER_OF_LOG_BUFFERS]; /* clear memset */ size_t number[NUMBER_OF_LOG_BUFFERS]; /* clear memset */
size_t size[NUMBER_OF_LOG_BUFFERS]; /* clear memset */ size_t size[NUMBER_OF_LOG_BUFFERS]; /* clear memset */
size_t totalSize[NUMBER_OF_LOG_BUFFERS]; /* init memset */ size_t totalSize[NUMBER_OF_LOG_BUFFERS]; /* init memset */
size_t maxSize[NUMBER_OF_LOG_BUFFERS]; /* init MAX_SIZE_DEFAULT */ size_t maxSize[NUMBER_OF_LOG_BUFFERS]; /* init MAX_SIZE_DEFAULT */
struct listnode *last[NUMBER_OF_LOG_BUFFERS]; /* init &head */ struct listnode* last[NUMBER_OF_LOG_BUFFERS]; /* init &head */
} logbuf = { } logbuf = {
.head = { &logbuf.head, &logbuf.head }, .head = { &logbuf.head, &logbuf.head }, .listLock = PTHREAD_RWLOCK_INITIALIZER,
.listLock = PTHREAD_RWLOCK_INITIALIZER,
}; };
static void LogBufferInit(struct LogBuffer *log) { static void LogBufferInit(struct LogBuffer* log) {
size_t i; size_t i;
pthread_rwlock_wrlock(&log->listLock); pthread_rwlock_wrlock(&log->listLock);
list_init(&log->head); list_init(&log->head);
memset(log->number, 0, memset(log->number, 0,
sizeof(log->number) + sizeof(log->size) + sizeof(log->totalSize)); sizeof(log->number) + sizeof(log->size) + sizeof(log->totalSize));
for (i = 0; i < NUMBER_OF_LOG_BUFFERS; ++i) { for (i = 0; i < NUMBER_OF_LOG_BUFFERS; ++i) {
log->maxSize[i] = MAX_SIZE_DEFAULT; log->maxSize[i] = MAX_SIZE_DEFAULT;
log->last[i] = &log->head; log->last[i] = &log->head;
} }
#ifdef __BIONIC__ #ifdef __BIONIC__
asprintf(&log->serviceName, "%s@%d:%d", baseServiceName, asprintf(&log->serviceName, "%s@%d:%d", baseServiceName, __android_log_uid(),
__android_log_uid(), getpid()); getpid());
#else #else
char buffer[sizeof(baseServiceName) + 1 + 5 + 1 + 5 + 8]; char buffer[sizeof(baseServiceName) + 1 + 5 + 1 + 5 + 8];
snprintf(buffer, sizeof(buffer), "%s@%d:%d", baseServiceName, snprintf(buffer, sizeof(buffer), "%s@%d:%d", baseServiceName,
__android_log_uid(), getpid()); __android_log_uid(), getpid());
log->serviceName = strdup(buffer); log->serviceName = strdup(buffer);
#endif #endif
pthread_rwlock_unlock(&log->listLock); pthread_rwlock_unlock(&log->listLock);
} }
static void LogBufferClear(struct LogBuffer *log) { static void LogBufferClear(struct LogBuffer* log) {
size_t i; size_t i;
struct listnode *node; struct listnode* node;
pthread_rwlock_wrlock(&log->listLock); pthread_rwlock_wrlock(&log->listLock);
memset(log->number, 0, sizeof(log->number) + sizeof(log->size)); memset(log->number, 0, sizeof(log->number) + sizeof(log->size));
@ -169,7 +165,7 @@ static void LogBufferClear(struct LogBuffer *log) {
log->last[i] = &log->head; log->last[i] = &log->head;
} }
while ((node = list_head(&log->head)) != &log->head) { while ((node = list_head(&log->head)) != &log->head) {
struct LogBufferElement *element; struct LogBufferElement* element;
element = node_to_item(node, struct LogBufferElement, node); element = node_to_item(node, struct LogBufferElement, node);
list_remove(node); list_remove(node);
@ -178,7 +174,7 @@ static void LogBufferClear(struct LogBuffer *log) {
pthread_rwlock_unlock(&log->listLock); pthread_rwlock_unlock(&log->listLock);
} }
static inline void LogBufferFree(struct LogBuffer *log) { static inline void LogBufferFree(struct LogBuffer* log) {
pthread_rwlock_wrlock(&log->listLock); pthread_rwlock_wrlock(&log->listLock);
free(log->serviceName); free(log->serviceName);
log->serviceName = NULL; log->serviceName = NULL;
@ -186,8 +182,8 @@ static inline void LogBufferFree(struct LogBuffer *log) {
LogBufferClear(log); LogBufferClear(log);
} }
static int LogBufferLog(struct LogBuffer *log, static int LogBufferLog(struct LogBuffer* log,
struct LogBufferElement *element) { struct LogBufferElement* element) {
log_id_t logId = element->logId; log_id_t logId = element->logId;
pthread_rwlock_wrlock(&log->listLock); pthread_rwlock_wrlock(&log->listLock);
@ -199,16 +195,16 @@ static int LogBufferLog(struct LogBuffer *log,
log->last[logId] = list_tail(&log->head); log->last[logId] = list_tail(&log->head);
} }
while (log->size[logId] > log->maxSize[logId]) { while (log->size[logId] > log->maxSize[logId]) {
struct listnode *node = log->last[logId]; struct listnode* node = log->last[logId];
struct LogBufferElement *e; struct LogBufferElement* e;
struct android_log_logger_list *logger_list; struct android_log_logger_list* logger_list;
e = node_to_item(node, struct LogBufferElement, node); e = node_to_item(node, struct LogBufferElement, node);
log->number[logId]--; log->number[logId]--;
log->size[logId] -= e->len; log->size[logId] -= e->len;
logger_list_rdlock(); logger_list_rdlock();
logger_list_for_each(logger_list) { logger_list_for_each(logger_list) {
struct android_log_transport_context *transp; struct android_log_transport_context* transp;
transport_context_for_each(transp, logger_list) { transport_context_for_each(transp, logger_list) {
if ((transp->transport == &localLoggerRead) && if ((transp->transport == &localLoggerRead) &&
@ -243,7 +239,7 @@ static int LogBufferLog(struct LogBuffer *log,
*/ */
static int writeToLocalInit() { static int writeToLocalInit() {
pthread_attr_t attr; pthread_attr_t attr;
struct LogBuffer *log; struct LogBuffer* log;
if (writeToLocalAvailable(LOG_ID_MAIN) < 0) { if (writeToLocalAvailable(LOG_ID_MAIN) < 0) {
return -EPERM; return -EPERM;
@ -251,7 +247,7 @@ static int writeToLocalInit() {
log = &logbuf; log = &logbuf;
if (!log->serviceName) { if (!log->serviceName) {
LogBufferInit(log); LogBufferInit(log);
} }
if (!log->serviceName) { if (!log->serviceName) {
@ -275,9 +271,9 @@ static int writeToLocalAvailable(log_id_t logId) {
return -EINVAL; return -EINVAL;
} }
/* Android hard coded permitted, system goes to logd */ /* Android hard coded permitted, system goes to logd */
#if !defined(__MINGW32__) #if !defined(__MINGW32__)
if (__android_log_frontend == LOGGER_DEFAULT) { if (__android_log_transport == LOGGER_DEFAULT) {
uid = __android_log_uid(); uid = __android_log_uid();
if ((uid < AID_APP) && (getpwuid(uid) != NULL)) { if ((uid < AID_APP) && (getpwuid(uid) != NULL)) {
return -EPERM; return -EPERM;
@ -290,10 +286,10 @@ static int writeToLocalAvailable(log_id_t logId) {
return 0; return 0;
} }
static int writeToLocalWrite(log_id_t logId, struct timespec *ts, static int writeToLocalWrite(log_id_t logId, struct timespec* ts,
struct iovec *vec, size_t nr) { struct iovec* vec, size_t nr) {
size_t len, i; size_t len, i;
struct LogBufferElement *element; struct LogBufferElement* element;
if ((logId >= NUMBER_OF_LOG_BUFFERS) || BLOCK_LOG_BUFFERS(logId)) { if ((logId >= NUMBER_OF_LOG_BUFFERS) || BLOCK_LOG_BUFFERS(logId)) {
return -EINVAL; return -EINVAL;
@ -307,8 +303,8 @@ static int writeToLocalWrite(log_id_t logId, struct timespec *ts,
if (len > LOGGER_ENTRY_MAX_PAYLOAD) { if (len > LOGGER_ENTRY_MAX_PAYLOAD) {
len = LOGGER_ENTRY_MAX_PAYLOAD; len = LOGGER_ENTRY_MAX_PAYLOAD;
} }
element = (struct LogBufferElement *)calloc(1, element = (struct LogBufferElement*)calloc(
sizeof(struct LogBufferElement) + len + 1); 1, sizeof(struct LogBufferElement) + len + 1);
if (!element) { if (!element) {
return errno ? -errno : -ENOMEM; return errno ? -errno : -ENOMEM;
} }
@ -322,7 +318,7 @@ static int writeToLocalWrite(log_id_t logId, struct timespec *ts,
element->logId = logId; element->logId = logId;
element->len = len; element->len = len;
char *cp = element->msg; char* cp = element->msg;
for (i = 0; i < nr; ++i) { for (i = 0; i < nr; ++i) {
size_t iov_len = vec[i].iov_len; size_t iov_len = vec[i].iov_len;
if (iov_len > len) { if (iov_len > len) {
@ -339,17 +335,17 @@ static int writeToLocalWrite(log_id_t logId, struct timespec *ts,
return LogBufferLog(&logbuf, element); return LogBufferLog(&logbuf, element);
} }
static int writeToLocalVersion( static int writeToLocalVersion(struct android_log_logger* logger __unused,
struct android_log_logger *logger __unused, struct android_log_transport_context* transp
struct android_log_transport_context *transp __unused) { __unused) {
return 3; return 3;
} }
/* within reader lock, serviceName already validated */ /* within reader lock, serviceName already validated */
static struct listnode *writeToLocalNode( static struct listnode* writeToLocalNode(
struct android_log_logger_list *logger_list, struct android_log_logger_list* logger_list,
struct android_log_transport_context *transp) { struct android_log_transport_context* transp) {
struct listnode *node; struct listnode* node;
unsigned logMask; unsigned logMask;
unsigned int tail; unsigned int tail;
@ -366,7 +362,7 @@ static struct listnode *writeToLocalNode(
tail = logger_list->tail; tail = logger_list->tail;
for (node = list_head(&logbuf.head); node != &logbuf.head; node = node->next) { for (node = list_head(&logbuf.head); node != &logbuf.head; node = node->next) {
struct LogBufferElement *element; struct LogBufferElement* element;
log_id_t logId; log_id_t logId;
element = node_to_item(node, struct LogBufferElement, node); element = node_to_item(node, struct LogBufferElement, node);
@ -380,12 +376,11 @@ static struct listnode *writeToLocalNode(
return transp->context.node = node; return transp->context.node = node;
} }
static int writeToLocalRead( static int writeToLocalRead(struct android_log_logger_list* logger_list,
struct android_log_logger_list *logger_list, struct android_log_transport_context* transp,
struct android_log_transport_context *transp, struct log_msg* log_msg) {
struct log_msg *log_msg) {
int ret; int ret;
struct listnode *node; struct listnode* node;
unsigned logMask; unsigned logMask;
pthread_rwlock_rdlock(&logbuf.listLock); pthread_rwlock_rdlock(&logbuf.listLock);
@ -401,7 +396,7 @@ static int writeToLocalRead(
ret = 0; ret = 0;
while (node != list_head(&logbuf.head)) { while (node != list_head(&logbuf.head)) {
struct LogBufferElement *element; struct LogBufferElement* element;
log_id_t logId; log_id_t logId;
node = node->prev; node = node->prev;
@ -429,23 +424,22 @@ static int writeToLocalRead(
return ret; return ret;
} }
static int writeToLocalPoll( static int writeToLocalPoll(struct android_log_logger_list* logger_list,
struct android_log_logger_list *logger_list, struct android_log_transport_context* transp) {
struct android_log_transport_context *transp) {
int ret = (logger_list->mode & ANDROID_LOG_NONBLOCK) ? -ENODEV : 0; int ret = (logger_list->mode & ANDROID_LOG_NONBLOCK) ? -ENODEV : 0;
pthread_rwlock_rdlock(&logbuf.listLock); pthread_rwlock_rdlock(&logbuf.listLock);
if (logbuf.serviceName) { if (logbuf.serviceName) {
unsigned logMask = transp->logMask; unsigned logMask = transp->logMask;
struct listnode *node = writeToLocalNode(logger_list, transp); struct listnode* node = writeToLocalNode(logger_list, transp);
ret = (node != list_head(&logbuf.head)); ret = (node != list_head(&logbuf.head));
if (ret) { if (ret) {
do { do {
ret = !!(logMask & (1 << (node_to_item(node->prev, ret = !!(logMask &
struct LogBufferElement, (1 << (node_to_item(node->prev, struct LogBufferElement, node))
node))->logId)); ->logId));
} while (!ret && ((node = node->prev) != list_head(&logbuf.head))); } while (!ret && ((node = node->prev) != list_head(&logbuf.head)));
} }
@ -457,17 +451,17 @@ static int writeToLocalPoll(
return ret; return ret;
} }
static void writeToLocalClose( static void writeToLocalClose(struct android_log_logger_list* logger_list
struct android_log_logger_list *logger_list __unused, __unused,
struct android_log_transport_context *transp) { struct android_log_transport_context* transp) {
pthread_rwlock_wrlock(&logbuf.listLock); pthread_rwlock_wrlock(&logbuf.listLock);
transp->context.node = list_head(&logbuf.head); transp->context.node = list_head(&logbuf.head);
pthread_rwlock_unlock(&logbuf.listLock); pthread_rwlock_unlock(&logbuf.listLock);
} }
static int writeToLocalClear( static int writeToLocalClear(struct android_log_logger* logger,
struct android_log_logger *logger, struct android_log_transport_context* unused
struct android_log_transport_context *unused __unused) { __unused) {
log_id_t logId = logger->logId; log_id_t logId = logger->logId;
struct listnode *node, *n; struct listnode *node, *n;
@ -479,15 +473,15 @@ static int writeToLocalClear(
logbuf.number[logId] = 0; logbuf.number[logId] = 0;
logbuf.last[logId] = &logbuf.head; logbuf.last[logId] = &logbuf.head;
list_for_each_safe(node, n, &logbuf.head) { list_for_each_safe(node, n, &logbuf.head) {
struct LogBufferElement *element; struct LogBufferElement* element;
element = node_to_item(node, struct LogBufferElement, node); element = node_to_item(node, struct LogBufferElement, node);
if (logId == element->logId) { if (logId == element->logId) {
struct android_log_logger_list *logger_list; struct android_log_logger_list* logger_list;
logger_list_rdlock(); logger_list_rdlock();
logger_list_for_each(logger_list) { logger_list_for_each(logger_list) {
struct android_log_transport_context *transp; struct android_log_transport_context* transp;
transport_context_for_each(transp, logger_list) { transport_context_for_each(transp, logger_list) {
if ((transp->transport == &localLoggerRead) && if ((transp->transport == &localLoggerRead) &&
@ -507,9 +501,9 @@ static int writeToLocalClear(
return 0; return 0;
} }
static ssize_t writeToLocalGetSize( static ssize_t writeToLocalGetSize(struct android_log_logger* logger,
struct android_log_logger *logger, struct android_log_transport_context* transp
struct android_log_transport_context *transp __unused) { __unused) {
ssize_t ret = -EINVAL; ssize_t ret = -EINVAL;
log_id_t logId = logger->logId; log_id_t logId = logger->logId;
@ -523,9 +517,8 @@ static ssize_t writeToLocalGetSize(
} }
static ssize_t writeToLocalSetSize( static ssize_t writeToLocalSetSize(
struct android_log_logger *logger, struct android_log_logger* logger,
struct android_log_transport_context *transp __unused, struct android_log_transport_context* transp __unused, size_t size) {
size_t size) {
ssize_t ret = -EINVAL; ssize_t ret = -EINVAL;
if ((size > LOGGER_ENTRY_MAX_LEN) || (size < (4 * 1024 * 1024))) { if ((size > LOGGER_ENTRY_MAX_LEN) || (size < (4 * 1024 * 1024))) {
@ -541,8 +534,8 @@ static ssize_t writeToLocalSetSize(
} }
static ssize_t writeToLocalGetReadbleSize( static ssize_t writeToLocalGetReadbleSize(
struct android_log_logger *logger, struct android_log_logger* logger,
struct android_log_transport_context *transp __unused) { struct android_log_transport_context* transp __unused) {
ssize_t ret = -EINVAL; ssize_t ret = -EINVAL;
log_id_t logId = logger->logId; log_id_t logId = logger->logId;

View file

@ -30,270 +30,266 @@
#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t)) #define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
typedef struct { typedef struct {
uint32_t tag; uint32_t tag;
unsigned pos; /* Read/write position into buffer */ unsigned pos; /* Read/write position into buffer */
unsigned count[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* Number of elements */ unsigned count[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* Number of elements */
unsigned list[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* pos for list counter */ unsigned list[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* pos for list counter */
unsigned list_nest_depth; unsigned list_nest_depth;
unsigned len; /* Length or raw buffer. */ unsigned len; /* Length or raw buffer. */
bool overflow; bool overflow;
bool list_stop; /* next call decrement list_nest_depth and issue a stop */ bool list_stop; /* next call decrement list_nest_depth and issue a stop */
enum { enum {
kAndroidLoggerRead = 1, kAndroidLoggerRead = 1,
kAndroidLoggerWrite = 2, kAndroidLoggerWrite = 2,
} read_write_flag; } read_write_flag;
uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD]; uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD];
} android_log_context_internal; } android_log_context_internal;
LIBLOG_ABI_PUBLIC android_log_context create_android_logger(uint32_t tag) { LIBLOG_ABI_PUBLIC android_log_context create_android_logger(uint32_t tag) {
size_t needed, i; size_t needed, i;
android_log_context_internal *context; android_log_context_internal* context;
context = calloc(1, sizeof(android_log_context_internal)); context = calloc(1, sizeof(android_log_context_internal));
if (!context) { if (!context) {
return NULL; return NULL;
} }
context->tag = tag; context->tag = tag;
context->read_write_flag = kAndroidLoggerWrite; context->read_write_flag = kAndroidLoggerWrite;
needed = sizeof(uint8_t) + sizeof(uint8_t); needed = sizeof(uint8_t) + sizeof(uint8_t);
if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
context->overflow = true; context->overflow = true;
} }
/* Everything is a list */ /* Everything is a list */
context->storage[context->pos + 0] = EVENT_TYPE_LIST; context->storage[context->pos + 0] = EVENT_TYPE_LIST;
context->list[0] = context->pos + 1; context->list[0] = context->pos + 1;
context->pos += needed; context->pos += needed;
return (android_log_context)context; return (android_log_context)context;
} }
LIBLOG_ABI_PUBLIC android_log_context create_android_log_parser( LIBLOG_ABI_PUBLIC android_log_context create_android_log_parser(const char* msg,
const char *msg, size_t len) {
size_t len) { android_log_context_internal* context;
android_log_context_internal *context; size_t i;
size_t i;
context = calloc(1, sizeof(android_log_context_internal)); context = calloc(1, sizeof(android_log_context_internal));
if (!context) { if (!context) {
return NULL; return NULL;
} }
len = (len <= MAX_EVENT_PAYLOAD) ? len : MAX_EVENT_PAYLOAD; len = (len <= MAX_EVENT_PAYLOAD) ? len : MAX_EVENT_PAYLOAD;
context->len = len; context->len = len;
memcpy(context->storage, msg, len); memcpy(context->storage, msg, len);
context->read_write_flag = kAndroidLoggerRead; context->read_write_flag = kAndroidLoggerRead;
return (android_log_context)context; return (android_log_context)context;
} }
LIBLOG_ABI_PUBLIC int android_log_destroy(android_log_context *ctx) { LIBLOG_ABI_PUBLIC int android_log_destroy(android_log_context* ctx) {
android_log_context_internal *context; android_log_context_internal* context;
context = (android_log_context_internal *)*ctx; context = (android_log_context_internal*)*ctx;
if (!context) { if (!context) {
return -EBADF; return -EBADF;
} }
memset(context, 0, sizeof(*context)); memset(context, 0, sizeof(*context));
free(context); free(context);
*ctx = NULL; *ctx = NULL;
return 0; return 0;
} }
LIBLOG_ABI_PUBLIC int android_log_write_list_begin(android_log_context ctx) { LIBLOG_ABI_PUBLIC int android_log_write_list_begin(android_log_context ctx) {
size_t needed; size_t needed;
android_log_context_internal *context; android_log_context_internal* context;
context = (android_log_context_internal *)ctx; context = (android_log_context_internal*)ctx;
if (!context || if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
(kAndroidLoggerWrite != context->read_write_flag)) { return -EBADF;
return -EBADF; }
} if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) { context->overflow = true;
context->overflow = true; return -EOVERFLOW;
return -EOVERFLOW; }
} needed = sizeof(uint8_t) + sizeof(uint8_t);
needed = sizeof(uint8_t) + sizeof(uint8_t); if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { context->overflow = true;
context->overflow = true; return -EIO;
return -EIO; }
} context->count[context->list_nest_depth]++;
context->count[context->list_nest_depth]++; context->list_nest_depth++;
context->list_nest_depth++; if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) { context->overflow = true;
context->overflow = true; return -EOVERFLOW;
return -EOVERFLOW; }
} if (context->overflow) {
if (context->overflow) { return -EIO;
return -EIO; }
} context->storage[context->pos + 0] = EVENT_TYPE_LIST;
context->storage[context->pos + 0] = EVENT_TYPE_LIST; context->storage[context->pos + 1] = 0;
context->storage[context->pos + 1] = 0; context->list[context->list_nest_depth] = context->pos + 1;
context->list[context->list_nest_depth] = context->pos + 1; context->count[context->list_nest_depth] = 0;
context->count[context->list_nest_depth] = 0; context->pos += needed;
context->pos += needed; return 0;
return 0;
} }
static inline void copy4LE(uint8_t *buf, uint32_t val) static inline void copy4LE(uint8_t* buf, uint32_t val) {
{ buf[0] = val & 0xFF;
buf[0] = val & 0xFF; buf[1] = (val >> 8) & 0xFF;
buf[1] = (val >> 8) & 0xFF; buf[2] = (val >> 16) & 0xFF;
buf[2] = (val >> 16) & 0xFF; buf[3] = (val >> 24) & 0xFF;
buf[3] = (val >> 24) & 0xFF;
} }
LIBLOG_ABI_PUBLIC int android_log_write_int32(android_log_context ctx, LIBLOG_ABI_PUBLIC int android_log_write_int32(android_log_context ctx,
int32_t value) { int32_t value) {
size_t needed; size_t needed;
android_log_context_internal *context; android_log_context_internal* context;
context = (android_log_context_internal *)ctx; context = (android_log_context_internal*)ctx;
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF; return -EBADF;
} }
if (context->overflow) { if (context->overflow) {
return -EIO; return -EIO;
} }
needed = sizeof(uint8_t) + sizeof(value); needed = sizeof(uint8_t) + sizeof(value);
if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
context->overflow = true; context->overflow = true;
return -EIO; return -EIO;
} }
context->count[context->list_nest_depth]++; context->count[context->list_nest_depth]++;
context->storage[context->pos + 0] = EVENT_TYPE_INT; context->storage[context->pos + 0] = EVENT_TYPE_INT;
copy4LE(&context->storage[context->pos + 1], value); copy4LE(&context->storage[context->pos + 1], value);
context->pos += needed; context->pos += needed;
return 0; return 0;
} }
static inline void copy8LE(uint8_t *buf, uint64_t val) static inline void copy8LE(uint8_t* buf, uint64_t val) {
{ buf[0] = val & 0xFF;
buf[0] = val & 0xFF; buf[1] = (val >> 8) & 0xFF;
buf[1] = (val >> 8) & 0xFF; buf[2] = (val >> 16) & 0xFF;
buf[2] = (val >> 16) & 0xFF; buf[3] = (val >> 24) & 0xFF;
buf[3] = (val >> 24) & 0xFF; buf[4] = (val >> 32) & 0xFF;
buf[4] = (val >> 32) & 0xFF; buf[5] = (val >> 40) & 0xFF;
buf[5] = (val >> 40) & 0xFF; buf[6] = (val >> 48) & 0xFF;
buf[6] = (val >> 48) & 0xFF; buf[7] = (val >> 56) & 0xFF;
buf[7] = (val >> 56) & 0xFF;
} }
LIBLOG_ABI_PUBLIC int android_log_write_int64(android_log_context ctx, LIBLOG_ABI_PUBLIC int android_log_write_int64(android_log_context ctx,
int64_t value) { int64_t value) {
size_t needed; size_t needed;
android_log_context_internal *context; android_log_context_internal* context;
context = (android_log_context_internal *)ctx; context = (android_log_context_internal*)ctx;
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF; return -EBADF;
} }
if (context->overflow) { if (context->overflow) {
return -EIO; return -EIO;
} }
needed = sizeof(uint8_t) + sizeof(value); needed = sizeof(uint8_t) + sizeof(value);
if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
context->overflow = true; context->overflow = true;
return -EIO; return -EIO;
} }
context->count[context->list_nest_depth]++; context->count[context->list_nest_depth]++;
context->storage[context->pos + 0] = EVENT_TYPE_LONG; context->storage[context->pos + 0] = EVENT_TYPE_LONG;
copy8LE(&context->storage[context->pos + 1], value); copy8LE(&context->storage[context->pos + 1], value);
context->pos += needed; context->pos += needed;
return 0; return 0;
} }
LIBLOG_ABI_PUBLIC int android_log_write_string8_len(android_log_context ctx, LIBLOG_ABI_PUBLIC int android_log_write_string8_len(android_log_context ctx,
const char *value, const char* value,
size_t maxlen) { size_t maxlen) {
size_t needed; size_t needed;
ssize_t len; ssize_t len;
android_log_context_internal *context; android_log_context_internal* context;
context = (android_log_context_internal *)ctx; context = (android_log_context_internal*)ctx;
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF; return -EBADF;
}
if (context->overflow) {
return -EIO;
}
if (!value) {
value = "";
}
len = strnlen(value, maxlen);
needed = sizeof(uint8_t) + sizeof(int32_t) + len;
if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
/* Truncate string for delivery */
len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(int32_t);
if (len <= 0) {
context->overflow = true;
return -EIO;
} }
if (context->overflow) { }
return -EIO; context->count[context->list_nest_depth]++;
} context->storage[context->pos + 0] = EVENT_TYPE_STRING;
if (!value) { copy4LE(&context->storage[context->pos + 1], len);
value = ""; if (len) {
} memcpy(&context->storage[context->pos + 5], value, len);
len = strnlen(value, maxlen); }
needed = sizeof(uint8_t) + sizeof(int32_t) + len; context->pos += needed;
if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { return len;
/* Truncate string for delivery */
len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(int32_t);
if (len <= 0) {
context->overflow = true;
return -EIO;
}
}
context->count[context->list_nest_depth]++;
context->storage[context->pos + 0] = EVENT_TYPE_STRING;
copy4LE(&context->storage[context->pos + 1], len);
if (len) {
memcpy(&context->storage[context->pos + 5], value, len);
}
context->pos += needed;
return len;
} }
LIBLOG_ABI_PUBLIC int android_log_write_string8(android_log_context ctx, LIBLOG_ABI_PUBLIC int android_log_write_string8(android_log_context ctx,
const char *value) { const char* value) {
return android_log_write_string8_len(ctx, value, MAX_EVENT_PAYLOAD); return android_log_write_string8_len(ctx, value, MAX_EVENT_PAYLOAD);
} }
LIBLOG_ABI_PUBLIC int android_log_write_float32(android_log_context ctx, LIBLOG_ABI_PUBLIC int android_log_write_float32(android_log_context ctx,
float value) { float value) {
size_t needed; size_t needed;
uint32_t ivalue; uint32_t ivalue;
android_log_context_internal *context; android_log_context_internal* context;
context = (android_log_context_internal *)ctx; context = (android_log_context_internal*)ctx;
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF; return -EBADF;
} }
if (context->overflow) { if (context->overflow) {
return -EIO; return -EIO;
} }
needed = sizeof(uint8_t) + sizeof(ivalue); needed = sizeof(uint8_t) + sizeof(ivalue);
if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
context->overflow = true; context->overflow = true;
return -EIO; return -EIO;
} }
ivalue = *(uint32_t *)&value; ivalue = *(uint32_t*)&value;
context->count[context->list_nest_depth]++; context->count[context->list_nest_depth]++;
context->storage[context->pos + 0] = EVENT_TYPE_FLOAT; context->storage[context->pos + 0] = EVENT_TYPE_FLOAT;
copy4LE(&context->storage[context->pos + 1], ivalue); copy4LE(&context->storage[context->pos + 1], ivalue);
context->pos += needed; context->pos += needed;
return 0; return 0;
} }
LIBLOG_ABI_PUBLIC int android_log_write_list_end(android_log_context ctx) { LIBLOG_ABI_PUBLIC int android_log_write_list_end(android_log_context ctx) {
android_log_context_internal *context; android_log_context_internal* context;
context = (android_log_context_internal *)ctx; context = (android_log_context_internal*)ctx;
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF; return -EBADF;
} }
if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) { if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
context->overflow = true; context->overflow = true;
context->list_nest_depth--;
return -EOVERFLOW;
}
if (!context->list_nest_depth) {
context->overflow = true;
return -EOVERFLOW;
}
if (context->list[context->list_nest_depth] <= 0) {
context->list_nest_depth--;
context->overflow = true;
return -EOVERFLOW;
}
context->storage[context->list[context->list_nest_depth]] =
context->count[context->list_nest_depth];
context->list_nest_depth--; context->list_nest_depth--;
return 0; return -EOVERFLOW;
}
if (!context->list_nest_depth) {
context->overflow = true;
return -EOVERFLOW;
}
if (context->list[context->list_nest_depth] <= 0) {
context->list_nest_depth--;
context->overflow = true;
return -EOVERFLOW;
}
context->storage[context->list[context->list_nest_depth]] =
context->count[context->list_nest_depth];
context->list_nest_depth--;
return 0;
} }
/* /*
@ -301,86 +297,84 @@ LIBLOG_ABI_PUBLIC int android_log_write_list_end(android_log_context ctx) {
*/ */
LIBLOG_ABI_PUBLIC int android_log_write_list(android_log_context ctx, LIBLOG_ABI_PUBLIC int android_log_write_list(android_log_context ctx,
log_id_t id) { log_id_t id) {
android_log_context_internal *context; android_log_context_internal* context;
const char *msg; const char* msg;
ssize_t len; ssize_t len;
if ((id != LOG_ID_EVENTS) && (id != LOG_ID_SECURITY)) { if ((id != LOG_ID_EVENTS) && (id != LOG_ID_SECURITY)) {
return -EINVAL; return -EINVAL;
} }
context = (android_log_context_internal *)ctx; context = (android_log_context_internal*)ctx;
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF; return -EBADF;
}
if (context->list_nest_depth) {
return -EIO;
}
/* NB: if there was overflow, then log is truncated. Nothing reported */
context->storage[1] = context->count[0];
len = context->len = context->pos;
msg = (const char*)context->storage;
/* it's not a list */
if (context->count[0] <= 1) {
len -= sizeof(uint8_t) + sizeof(uint8_t);
if (len < 0) {
len = 0;
} }
if (context->list_nest_depth) { msg += sizeof(uint8_t) + sizeof(uint8_t);
return -EIO; }
} return (id == LOG_ID_EVENTS)
/* NB: if there was overflow, then log is truncated. Nothing reported */ ? __android_log_bwrite(context->tag, msg, len)
context->storage[1] = context->count[0]; : __android_log_security_bwrite(context->tag, msg, len);
len = context->len = context->pos;
msg = (const char *)context->storage;
/* it's not a list */
if (context->count[0] <= 1) {
len -= sizeof(uint8_t) + sizeof(uint8_t);
if (len < 0) {
len = 0;
}
msg += sizeof(uint8_t) + sizeof(uint8_t);
}
return (id == LOG_ID_EVENTS) ?
__android_log_bwrite(context->tag, msg, len) :
__android_log_security_bwrite(context->tag, msg, len);
} }
LIBLOG_ABI_PRIVATE int android_log_write_list_buffer(android_log_context ctx, LIBLOG_ABI_PRIVATE int android_log_write_list_buffer(android_log_context ctx,
const char **buffer) { const char** buffer) {
android_log_context_internal *context; android_log_context_internal* context;
const char *msg; const char* msg;
ssize_t len; ssize_t len;
context = (android_log_context_internal *)ctx; context = (android_log_context_internal*)ctx;
if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
return -EBADF; return -EBADF;
}
if (context->list_nest_depth) {
return -EIO;
}
if (buffer == NULL) {
return -EFAULT;
}
/* NB: if there was overflow, then log is truncated. Nothing reported */
context->storage[1] = context->count[0];
len = context->len = context->pos;
msg = (const char*)context->storage;
/* it's not a list */
if (context->count[0] <= 1) {
len -= sizeof(uint8_t) + sizeof(uint8_t);
if (len < 0) {
len = 0;
} }
if (context->list_nest_depth) { msg += sizeof(uint8_t) + sizeof(uint8_t);
return -EIO; }
} *buffer = msg;
if (buffer == NULL) { return len;
return -EFAULT;
}
/* NB: if there was overflow, then log is truncated. Nothing reported */
context->storage[1] = context->count[0];
len = context->len = context->pos;
msg = (const char *)context->storage;
/* it's not a list */
if (context->count[0] <= 1) {
len -= sizeof(uint8_t) + sizeof(uint8_t);
if (len < 0) {
len = 0;
}
msg += sizeof(uint8_t) + sizeof(uint8_t);
}
*buffer = msg;
return len;
} }
/* /*
* Extract a 4-byte value from a byte stream. * Extract a 4-byte value from a byte stream.
*/ */
static inline uint32_t get4LE(const uint8_t* src) static inline uint32_t get4LE(const uint8_t* src) {
{ return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
} }
/* /*
* Extract an 8-byte value from a byte stream. * Extract an 8-byte value from a byte stream.
*/ */
static inline uint64_t get8LE(const uint8_t* src) static inline uint64_t get8LE(const uint8_t* src) {
{ uint32_t low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
uint32_t low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); uint32_t high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
uint32_t high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24); return ((uint64_t)high << 32) | (uint64_t)low;
return ((uint64_t) high << 32) | (uint64_t) low;
} }
/* /*
@ -391,181 +385,181 @@ static inline uint64_t get8LE(const uint8_t* src)
* (although it won't crash). * (although it won't crash).
*/ */
static android_log_list_element android_log_read_next_internal( static android_log_list_element android_log_read_next_internal(
android_log_context ctx, int peek) { android_log_context ctx, int peek) {
android_log_list_element elem; android_log_list_element elem;
unsigned pos; unsigned pos;
android_log_context_internal *context; android_log_context_internal* context;
context = (android_log_context_internal *)ctx; context = (android_log_context_internal*)ctx;
memset(&elem, 0, sizeof(elem)); memset(&elem, 0, sizeof(elem));
/* Nothing to parse from this context, so return complete. */ /* Nothing to parse from this context, so return complete. */
if (!context || (kAndroidLoggerRead != context->read_write_flag) || if (!context || (kAndroidLoggerRead != context->read_write_flag) ||
(context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) || (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) ||
(context->count[context->list_nest_depth] >= (context->count[context->list_nest_depth] >=
(MAX_EVENT_PAYLOAD / (sizeof(uint8_t) + sizeof(uint8_t))))) { (MAX_EVENT_PAYLOAD / (sizeof(uint8_t) + sizeof(uint8_t))))) {
elem.type = EVENT_TYPE_UNKNOWN; elem.type = EVENT_TYPE_UNKNOWN;
if (context && if (context && (context->list_stop ||
(context->list_stop || ((context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) &&
((context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) && !context->count[context->list_nest_depth]))) {
!context->count[context->list_nest_depth]))) { elem.type = EVENT_TYPE_LIST_STOP;
elem.type = EVENT_TYPE_LIST_STOP; }
elem.complete = true;
return elem;
}
/*
* Use a different variable to update the position in case this
* operation is a "peek".
*/
pos = context->pos;
if (context->list_stop) {
elem.type = EVENT_TYPE_LIST_STOP;
elem.complete = !context->count[0] &&
(!context->list_nest_depth ||
((context->list_nest_depth == 1) && !context->count[1]));
if (!peek) {
/* Suck in superfluous stop */
if (context->storage[pos] == EVENT_TYPE_LIST_STOP) {
context->pos = pos + 1;
}
if (context->list_nest_depth) {
--context->list_nest_depth;
if (context->count[context->list_nest_depth]) {
context->list_stop = false;
} }
elem.complete = true; } else {
return elem; context->list_stop = false;
}
} }
return elem;
}
if ((pos + 1) > context->len) {
elem.type = EVENT_TYPE_UNKNOWN;
elem.complete = true;
return elem;
}
/* elem.type = context->storage[pos++];
* Use a different variable to update the position in case this switch ((int)elem.type) {
* operation is a "peek".
*/
pos = context->pos;
if (context->list_stop) {
elem.type = EVENT_TYPE_LIST_STOP;
elem.complete = !context->count[0] && (!context->list_nest_depth ||
((context->list_nest_depth == 1) && !context->count[1]));
if (!peek) {
/* Suck in superfluous stop */
if (context->storage[pos] == EVENT_TYPE_LIST_STOP) {
context->pos = pos + 1;
}
if (context->list_nest_depth) {
--context->list_nest_depth;
if (context->count[context->list_nest_depth]) {
context->list_stop = false;
}
} else {
context->list_stop = false;
}
}
return elem;
}
if ((pos + 1) > context->len) {
elem.type = EVENT_TYPE_UNKNOWN;
elem.complete = true;
return elem;
}
elem.type = context->storage[pos++];
switch ((int)elem.type) {
case EVENT_TYPE_FLOAT: case EVENT_TYPE_FLOAT:
/* Rely on union to translate elem.data.int32 into elem.data.float32 */ /* Rely on union to translate elem.data.int32 into elem.data.float32 */
/* FALLTHRU */ /* FALLTHRU */
case EVENT_TYPE_INT: case EVENT_TYPE_INT:
elem.len = sizeof(int32_t); elem.len = sizeof(int32_t);
if ((pos + elem.len) > context->len) { if ((pos + elem.len) > context->len) {
elem.type = EVENT_TYPE_UNKNOWN; elem.type = EVENT_TYPE_UNKNOWN;
return elem;
}
elem.data.int32 = get4LE(&context->storage[pos]);
/* common tangeable object suffix */
pos += elem.len;
elem.complete = !context->list_nest_depth && !context->count[0];
if (!peek) {
if (!context->count[context->list_nest_depth] ||
!--(context->count[context->list_nest_depth])) {
context->list_stop = true;
}
context->pos = pos;
}
return elem; return elem;
}
elem.data.int32 = get4LE(&context->storage[pos]);
/* common tangeable object suffix */
pos += elem.len;
elem.complete = !context->list_nest_depth && !context->count[0];
if (!peek) {
if (!context->count[context->list_nest_depth] ||
!--(context->count[context->list_nest_depth])) {
context->list_stop = true;
}
context->pos = pos;
}
return elem;
case EVENT_TYPE_LONG: case EVENT_TYPE_LONG:
elem.len = sizeof(int64_t); elem.len = sizeof(int64_t);
if ((pos + elem.len) > context->len) { if ((pos + elem.len) > context->len) {
elem.type = EVENT_TYPE_UNKNOWN; elem.type = EVENT_TYPE_UNKNOWN;
return elem;
}
elem.data.int64 = get8LE(&context->storage[pos]);
/* common tangeable object suffix */
pos += elem.len;
elem.complete = !context->list_nest_depth && !context->count[0];
if (!peek) {
if (!context->count[context->list_nest_depth] ||
!--(context->count[context->list_nest_depth])) {
context->list_stop = true;
}
context->pos = pos;
}
return elem; return elem;
}
elem.data.int64 = get8LE(&context->storage[pos]);
/* common tangeable object suffix */
pos += elem.len;
elem.complete = !context->list_nest_depth && !context->count[0];
if (!peek) {
if (!context->count[context->list_nest_depth] ||
!--(context->count[context->list_nest_depth])) {
context->list_stop = true;
}
context->pos = pos;
}
return elem;
case EVENT_TYPE_STRING: case EVENT_TYPE_STRING:
if ((pos + sizeof(int32_t)) > context->len) { if ((pos + sizeof(int32_t)) > context->len) {
elem.type = EVENT_TYPE_UNKNOWN; elem.type = EVENT_TYPE_UNKNOWN;
elem.complete = true; elem.complete = true;
return elem;
}
elem.len = get4LE(&context->storage[pos]);
pos += sizeof(int32_t);
if ((pos + elem.len) > context->len) {
elem.len = context->len - pos; /* truncate string */
elem.complete = true;
if (!elem.len) {
elem.type = EVENT_TYPE_UNKNOWN;
return elem;
}
}
elem.data.string = (char *)&context->storage[pos];
/* common tangeable object suffix */
pos += elem.len;
elem.complete = !context->list_nest_depth && !context->count[0];
if (!peek) {
if (!context->count[context->list_nest_depth] ||
!--(context->count[context->list_nest_depth])) {
context->list_stop = true;
}
context->pos = pos;
}
return elem; return elem;
}
elem.len = get4LE(&context->storage[pos]);
pos += sizeof(int32_t);
if ((pos + elem.len) > context->len) {
elem.len = context->len - pos; /* truncate string */
elem.complete = true;
if (!elem.len) {
elem.type = EVENT_TYPE_UNKNOWN;
return elem;
}
}
elem.data.string = (char*)&context->storage[pos];
/* common tangeable object suffix */
pos += elem.len;
elem.complete = !context->list_nest_depth && !context->count[0];
if (!peek) {
if (!context->count[context->list_nest_depth] ||
!--(context->count[context->list_nest_depth])) {
context->list_stop = true;
}
context->pos = pos;
}
return elem;
case EVENT_TYPE_LIST: case EVENT_TYPE_LIST:
if ((pos + sizeof(uint8_t)) > context->len) { if ((pos + sizeof(uint8_t)) > context->len) {
elem.type = EVENT_TYPE_UNKNOWN; elem.type = EVENT_TYPE_UNKNOWN;
elem.complete = true; elem.complete = true;
return elem;
}
elem.complete = context->list_nest_depth >= ANDROID_MAX_LIST_NEST_DEPTH;
if (peek) {
return elem;
}
if (context->count[context->list_nest_depth]) {
context->count[context->list_nest_depth]--;
}
context->list_stop = !context->storage[pos];
context->list_nest_depth++;
if (context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) {
context->count[context->list_nest_depth] = context->storage[pos];
}
context->pos = pos + sizeof(uint8_t);
return elem; return elem;
}
elem.complete = context->list_nest_depth >= ANDROID_MAX_LIST_NEST_DEPTH;
if (peek) {
return elem;
}
if (context->count[context->list_nest_depth]) {
context->count[context->list_nest_depth]--;
}
context->list_stop = !context->storage[pos];
context->list_nest_depth++;
if (context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) {
context->count[context->list_nest_depth] = context->storage[pos];
}
context->pos = pos + sizeof(uint8_t);
return elem;
case EVENT_TYPE_LIST_STOP: /* Suprise Newline terminates lists. */ case EVENT_TYPE_LIST_STOP: /* Suprise Newline terminates lists. */
if (!peek) {
context->pos = pos;
}
elem.type = EVENT_TYPE_UNKNOWN;
elem.complete = !context->list_nest_depth;
if (context->list_nest_depth > 0) {
elem.type = EVENT_TYPE_LIST_STOP;
if (!peek) { if (!peek) {
context->pos = pos; context->list_nest_depth--;
} }
elem.type = EVENT_TYPE_UNKNOWN; }
elem.complete = !context->list_nest_depth; return elem;
if (context->list_nest_depth > 0) {
elem.type = EVENT_TYPE_LIST_STOP;
if (!peek) {
context->list_nest_depth--;
}
}
return elem;
default: default:
elem.type = EVENT_TYPE_UNKNOWN; elem.type = EVENT_TYPE_UNKNOWN;
return elem; return elem;
} }
} }
LIBLOG_ABI_PUBLIC android_log_list_element android_log_read_next( LIBLOG_ABI_PUBLIC android_log_list_element
android_log_context ctx) { android_log_read_next(android_log_context ctx) {
return android_log_read_next_internal(ctx, 0); return android_log_read_next_internal(ctx, 0);
} }
LIBLOG_ABI_PUBLIC android_log_list_element android_log_peek_next( LIBLOG_ABI_PUBLIC android_log_list_element
android_log_context ctx) { android_log_peek_next(android_log_context ctx) {
return android_log_read_next_internal(ctx, 1); return android_log_read_next_internal(ctx, 1);
} }

View file

@ -24,31 +24,28 @@
#define MAX_SUBTAG_LEN 32 #define MAX_SUBTAG_LEN 32
LIBLOG_ABI_PUBLIC int __android_log_error_write( LIBLOG_ABI_PUBLIC int __android_log_error_write(int tag, const char* subTag,
int tag, int32_t uid, const char* data,
const char *subTag, uint32_t dataLen) {
int32_t uid, int ret = -EINVAL;
const char *data, uint32_t dataLen)
{
int ret = -EINVAL;
if (subTag && (data || !dataLen)) { if (subTag && (data || !dataLen)) {
android_log_context ctx = create_android_logger(tag); android_log_context ctx = create_android_logger(tag);
ret = -ENOMEM; ret = -ENOMEM;
if (ctx) { if (ctx) {
ret = android_log_write_string8_len(ctx, subTag, MAX_SUBTAG_LEN); ret = android_log_write_string8_len(ctx, subTag, MAX_SUBTAG_LEN);
if (ret >= 0) { if (ret >= 0) {
ret = android_log_write_int32(ctx, uid); ret = android_log_write_int32(ctx, uid);
if (ret >= 0) { if (ret >= 0) {
ret = android_log_write_string8_len(ctx, data, dataLen); ret = android_log_write_string8_len(ctx, data, dataLen);
if (ret >= 0) { if (ret >= 0) {
ret = android_log_write_list(ctx, LOG_ID_EVENTS); ret = android_log_write_list(ctx, LOG_ID_EVENTS);
} }
}
}
android_log_destroy(&ctx);
} }
}
android_log_destroy(&ctx);
} }
return ret; }
return ret;
} }

View file

@ -46,7 +46,7 @@
#if defined(_WIN32) #if defined(_WIN32)
#define LIBLOG_WEAK static /* Accept that it is totally private */ #define LIBLOG_WEAK static /* Accept that it is totally private */
#else #else
#define LIBLOG_WEAK __attribute__((weak,visibility("default"))) #define LIBLOG_WEAK __attribute__((weak, visibility("default")))
#endif #endif
/* possible missing definitions in sys/cdefs.h */ /* possible missing definitions in sys/cdefs.h */
@ -54,8 +54,8 @@
/* DECLS */ /* DECLS */
#ifndef __BEGIN_DECLS #ifndef __BEGIN_DECLS
#if defined(__cplusplus) #if defined(__cplusplus)
#define __BEGIN_DECLS extern "C" { #define __BEGIN_DECLS extern "C" {
#define __END_DECLS } #define __END_DECLS }
#else #else
#define __BEGIN_DECLS #define __BEGIN_DECLS
#define __END_DECLS #define __END_DECLS
@ -64,19 +64,21 @@
/* Unused argument. For C code only, remove symbol name for C++ */ /* Unused argument. For C code only, remove symbol name for C++ */
#ifndef __unused #ifndef __unused
#define __unused __attribute__((__unused__)) #define __unused __attribute__((__unused__))
#endif #endif
/* possible missing definitions in unistd.h */ /* possible missing definitions in unistd.h */
#ifndef TEMP_FAILURE_RETRY #ifndef TEMP_FAILURE_RETRY
/* Used to retry syscalls that can return EINTR. */ /* Used to retry syscalls that can return EINTR. */
#define TEMP_FAILURE_RETRY(exp) ({ \ #define TEMP_FAILURE_RETRY(exp) \
({ \
__typeof__(exp) _rc; \ __typeof__(exp) _rc; \
do { \ do { \
_rc = (exp); \ _rc = (exp); \
} while (_rc == -1 && errno == EINTR); \ } while (_rc == -1 && errno == EINTR); \
_rc; }) _rc; \
})
#endif #endif
#endif /* _LIBLOG_PORTABILITY_H__ */ #endif /* _LIBLOG_PORTABILITY_H__ */

View file

@ -31,8 +31,8 @@ static time_t g_last_clock;
// of varying the 'seconds' argument to their pleasure. // of varying the 'seconds' argument to their pleasure.
static time_t g_last_seconds; static time_t g_last_seconds;
static const time_t last_seconds_default = 10; static const time_t last_seconds_default = 10;
static const time_t last_seconds_max = 24 * 60 * 60; // maximum of a day static const time_t last_seconds_max = 24 * 60 * 60; // maximum of a day
static const time_t last_seconds_min = 2; // granularity static const time_t last_seconds_min = 2; // granularity
// Lock to protect last_clock and last_seconds, but also 'last' // Lock to protect last_clock and last_seconds, but also 'last'
// argument (not NULL) as supplied to __android_log_ratelimit. // argument (not NULL) as supplied to __android_log_ratelimit.
static pthread_mutex_t lock_ratelimit = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t lock_ratelimit = PTHREAD_MUTEX_INITIALIZER;
@ -43,44 +43,44 @@ static pthread_mutex_t lock_ratelimit = PTHREAD_MUTEX_INITIALIZER;
// can not acquire a lock, 0 if we are not to log a message, and 1 // can not acquire a lock, 0 if we are not to log a message, and 1
// if we are ok to log a message. Caller should check > 0 for true. // if we are ok to log a message. Caller should check > 0 for true.
LIBLOG_ABI_PUBLIC int __android_log_ratelimit(time_t seconds, time_t* last) { LIBLOG_ABI_PUBLIC int __android_log_ratelimit(time_t seconds, time_t* last) {
int save_errno = errno; int save_errno = errno;
// Two reasons for trylock failure: // Two reasons for trylock failure:
// 1. In a signal handler. Must prevent deadlock // 1. In a signal handler. Must prevent deadlock
// 2. Too many threads calling __android_log_ratelimit. // 2. Too many threads calling __android_log_ratelimit.
// Bonus to not print if they race here because that // Bonus to not print if they race here because that
// dovetails the goal of ratelimiting. One may print // dovetails the goal of ratelimiting. One may print
// and the others will wait their turn ... // and the others will wait their turn ...
if (pthread_mutex_trylock(&lock_ratelimit)) { if (pthread_mutex_trylock(&lock_ratelimit)) {
if (save_errno) errno = save_errno; if (save_errno) errno = save_errno;
return -1; return -1;
} }
if (seconds == 0) { if (seconds == 0) {
seconds = last_seconds_default; seconds = last_seconds_default;
} else if (seconds < last_seconds_min) { } else if (seconds < last_seconds_min) {
seconds = last_seconds_min; seconds = last_seconds_min;
} else if (seconds > last_seconds_max) { } else if (seconds > last_seconds_max) {
seconds = last_seconds_max; seconds = last_seconds_max;
} }
if (!last) { if (!last) {
if (g_last_seconds > seconds) { if (g_last_seconds > seconds) {
seconds = g_last_seconds; seconds = g_last_seconds;
} else if (g_last_seconds < seconds) { } else if (g_last_seconds < seconds) {
g_last_seconds = seconds; g_last_seconds = seconds;
}
last = &g_last_clock;
} }
last = &g_last_clock;
}
time_t now = time(NULL); time_t now = time(NULL);
if ((now == (time_t)-1) || ((*last + seconds) > now)) { if ((now == (time_t)-1) || ((*last + seconds) > now)) {
pthread_mutex_unlock(&lock_ratelimit);
if (save_errno) errno = save_errno;
return 0;
}
*last = now;
pthread_mutex_unlock(&lock_ratelimit); pthread_mutex_unlock(&lock_ratelimit);
if (save_errno) errno = save_errno; if (save_errno) errno = save_errno;
return 1; return 0;
}
*last = now;
pthread_mutex_unlock(&lock_ratelimit);
if (save_errno) errno = save_errno;
return 1;
} }

View file

@ -28,164 +28,164 @@ LIBLOG_ABI_PRIVATE const timespec log_time::EPOCH = { 0, 0 };
// Add %#q for fractional seconds to standard strptime function // Add %#q for fractional seconds to standard strptime function
LIBLOG_ABI_PRIVATE char *log_time::strptime(const char *s, const char *format) { LIBLOG_ABI_PRIVATE char* log_time::strptime(const char* s, const char* format) {
time_t now; time_t now;
#ifdef __linux__ #ifdef __linux__
*this = log_time(CLOCK_REALTIME); *this = log_time(CLOCK_REALTIME);
now = tv_sec; now = tv_sec;
#else #else
time(&now); time(&now);
tv_sec = now; tv_sec = now;
tv_nsec = 0; tv_nsec = 0;
#endif #endif
struct tm *ptm; struct tm* ptm;
#if !defined(_WIN32) #if !defined(_WIN32)
struct tm tmBuf; struct tm tmBuf;
ptm = localtime_r(&now, &tmBuf); ptm = localtime_r(&now, &tmBuf);
#else #else
ptm = localtime(&now); ptm = localtime(&now);
#endif #endif
char fmt[strlen(format) + 1]; char fmt[strlen(format) + 1];
strcpy(fmt, format); strcpy(fmt, format);
char *ret = const_cast<char *> (s); char* ret = const_cast<char*>(s);
char *cp; char* cp;
for (char *f = cp = fmt; ; ++cp) { for (char* f = cp = fmt;; ++cp) {
if (!*cp) { if (!*cp) {
if (f != cp) { if (f != cp) {
ret = ::strptime(ret, f, ptm); ret = ::strptime(ret, f, ptm);
} }
break; break;
} }
if (*cp != '%') { if (*cp != '%') {
continue; continue;
} }
char *e = cp; char* e = cp;
++e; ++e;
#if (defined(__BIONIC__)) #if (defined(__BIONIC__))
if (*e == 's') { if (*e == 's') {
*cp = '\0'; *cp = '\0';
if (*f) { if (*f) {
ret = ::strptime(ret, f, ptm); ret = ::strptime(ret, f, ptm);
if (!ret) { if (!ret) {
break; break;
}
}
tv_sec = 0;
while (isdigit(*ret)) {
tv_sec = tv_sec * 10 + *ret - '0';
++ret;
}
now = tv_sec;
#if !defined(_WIN32)
ptm = localtime_r(&now, &tmBuf);
#else
ptm = localtime(&now);
#endif
} else
#endif
{
unsigned num = 0;
while (isdigit(*e)) {
num = num * 10 + *e - '0';
++e;
}
if (*e != 'q') {
continue;
}
*cp = '\0';
if (*f) {
ret = ::strptime(ret, f, ptm);
if (!ret) {
break;
}
}
unsigned long mul = NS_PER_SEC;
if (num == 0) {
num = INT_MAX;
}
tv_nsec = 0;
while (isdigit(*ret) && num && (mul > 1)) {
--num;
mul /= 10;
tv_nsec = tv_nsec + (*ret - '0') * mul;
++ret;
}
} }
f = cp = e; }
++f; tv_sec = 0;
} while (isdigit(*ret)) {
tv_sec = tv_sec * 10 + *ret - '0';
if (ret) { ++ret;
tv_sec = mktime(ptm); }
return ret; now = tv_sec;
} #if !defined(_WIN32)
ptm = localtime_r(&now, &tmBuf);
// Upon error, place a known value into the class, the current time.
#ifdef __linux__
*this = log_time(CLOCK_REALTIME);
#else #else
time(&now); ptm = localtime(&now);
tv_sec = now;
tv_nsec = 0;
#endif #endif
} else
#endif
{
unsigned num = 0;
while (isdigit(*e)) {
num = num * 10 + *e - '0';
++e;
}
if (*e != 'q') {
continue;
}
*cp = '\0';
if (*f) {
ret = ::strptime(ret, f, ptm);
if (!ret) {
break;
}
}
unsigned long mul = NS_PER_SEC;
if (num == 0) {
num = INT_MAX;
}
tv_nsec = 0;
while (isdigit(*ret) && num && (mul > 1)) {
--num;
mul /= 10;
tv_nsec = tv_nsec + (*ret - '0') * mul;
++ret;
}
}
f = cp = e;
++f;
}
if (ret) {
tv_sec = mktime(ptm);
return ret; return ret;
}
// Upon error, place a known value into the class, the current time.
#ifdef __linux__
*this = log_time(CLOCK_REALTIME);
#else
time(&now);
tv_sec = now;
tv_nsec = 0;
#endif
return ret;
} }
LIBLOG_ABI_PRIVATE log_time log_time::operator-= (const timespec &T) { LIBLOG_ABI_PRIVATE log_time log_time::operator-=(const timespec& T) {
// No concept of negative time, clamp to EPOCH // No concept of negative time, clamp to EPOCH
if (*this <= T) { if (*this <= T) {
return *this = EPOCH; return *this = EPOCH;
} }
if (this->tv_nsec < (unsigned long int)T.tv_nsec) { if (this->tv_nsec < (unsigned long int)T.tv_nsec) {
--this->tv_sec; --this->tv_sec;
this->tv_nsec = NS_PER_SEC + this->tv_nsec - T.tv_nsec; this->tv_nsec = NS_PER_SEC + this->tv_nsec - T.tv_nsec;
} else { } else {
this->tv_nsec -= T.tv_nsec; this->tv_nsec -= T.tv_nsec;
} }
this->tv_sec -= T.tv_sec; this->tv_sec -= T.tv_sec;
return *this; return *this;
} }
LIBLOG_ABI_PRIVATE log_time log_time::operator+= (const timespec &T) { LIBLOG_ABI_PRIVATE log_time log_time::operator+=(const timespec& T) {
this->tv_nsec += (unsigned long int)T.tv_nsec; this->tv_nsec += (unsigned long int)T.tv_nsec;
if (this->tv_nsec >= NS_PER_SEC) { if (this->tv_nsec >= NS_PER_SEC) {
this->tv_nsec -= NS_PER_SEC; this->tv_nsec -= NS_PER_SEC;
++this->tv_sec; ++this->tv_sec;
} }
this->tv_sec += T.tv_sec; this->tv_sec += T.tv_sec;
return *this; return *this;
} }
LIBLOG_ABI_PRIVATE log_time log_time::operator-= (const log_time &T) { LIBLOG_ABI_PRIVATE log_time log_time::operator-=(const log_time& T) {
// No concept of negative time, clamp to EPOCH // No concept of negative time, clamp to EPOCH
if (*this <= T) { if (*this <= T) {
return *this = EPOCH; return *this = EPOCH;
} }
if (this->tv_nsec < T.tv_nsec) { if (this->tv_nsec < T.tv_nsec) {
--this->tv_sec; --this->tv_sec;
this->tv_nsec = NS_PER_SEC + this->tv_nsec - T.tv_nsec; this->tv_nsec = NS_PER_SEC + this->tv_nsec - T.tv_nsec;
} else { } else {
this->tv_nsec -= T.tv_nsec; this->tv_nsec -= T.tv_nsec;
} }
this->tv_sec -= T.tv_sec; this->tv_sec -= T.tv_sec;
return *this; return *this;
} }
LIBLOG_ABI_PRIVATE log_time log_time::operator+= (const log_time &T) { LIBLOG_ABI_PRIVATE log_time log_time::operator+=(const log_time& T) {
this->tv_nsec += T.tv_nsec; this->tv_nsec += T.tv_nsec;
if (this->tv_nsec >= NS_PER_SEC) { if (this->tv_nsec >= NS_PER_SEC) {
this->tv_nsec -= NS_PER_SEC; this->tv_nsec -= NS_PER_SEC;
++this->tv_sec; ++this->tv_sec;
} }
this->tv_sec += T.tv_sec; this->tv_sec += T.tv_sec;
return *this; return *this;
} }

File diff suppressed because it is too large Load diff

View file

@ -23,7 +23,7 @@
__BEGIN_DECLS __BEGIN_DECLS
LIBLOG_HIDDEN ssize_t __send_log_msg(char *buf, size_t buf_size); LIBLOG_HIDDEN ssize_t __send_log_msg(char* buf, size_t buf_size);
__END_DECLS __END_DECLS

View file

@ -24,9 +24,9 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
@ -40,260 +40,251 @@
#include "logger.h" #include "logger.h"
/* branchless on many architectures. */ /* branchless on many architectures. */
#define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y)))) #define min(x, y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
static int logdAvailable(log_id_t LogId); static int logdAvailable(log_id_t LogId);
static int logdOpen(); static int logdOpen();
static void logdClose(); static void logdClose();
static int logdWrite(log_id_t logId, struct timespec *ts, static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec,
struct iovec *vec, size_t nr); size_t nr);
LIBLOG_HIDDEN struct android_log_transport_write logdLoggerWrite = { LIBLOG_HIDDEN struct android_log_transport_write logdLoggerWrite = {
.node = { &logdLoggerWrite.node, &logdLoggerWrite.node }, .node = { &logdLoggerWrite.node, &logdLoggerWrite.node },
.context.sock = -EBADF, .context.sock = -EBADF,
.name = "logd", .name = "logd",
.available = logdAvailable, .available = logdAvailable,
.open = logdOpen, .open = logdOpen,
.close = logdClose, .close = logdClose,
.write = logdWrite, .write = logdWrite,
}; };
/* log_init_lock assumed */ /* log_init_lock assumed */
static int logdOpen() static int logdOpen() {
{ int i, ret = 0;
int i, ret = 0;
i = atomic_load(&logdLoggerWrite.context.sock); i = atomic_load(&logdLoggerWrite.context.sock);
if (i < 0) { if (i < 0) {
int sock = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | int sock = TEMP_FAILURE_RETRY(
SOCK_CLOEXEC | socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
SOCK_NONBLOCK, 0)); if (sock < 0) {
if (sock < 0) { ret = -errno;
ret = -errno; } else {
} else { struct sockaddr_un un;
struct sockaddr_un un; memset(&un, 0, sizeof(struct sockaddr_un));
memset(&un, 0, sizeof(struct sockaddr_un)); un.sun_family = AF_UNIX;
un.sun_family = AF_UNIX; strcpy(un.sun_path, "/dev/socket/logdw");
strcpy(un.sun_path, "/dev/socket/logdw");
if (TEMP_FAILURE_RETRY(connect(sock, (struct sockaddr *)&un, if (TEMP_FAILURE_RETRY(connect(sock, (struct sockaddr*)&un,
sizeof(struct sockaddr_un))) < 0) { sizeof(struct sockaddr_un))) < 0) {
ret = -errno; ret = -errno;
switch (ret) { switch (ret) {
case -ENOTCONN: case -ENOTCONN:
case -ECONNREFUSED: case -ECONNREFUSED:
case -ENOENT: case -ENOENT:
i = atomic_exchange(&logdLoggerWrite.context.sock, ret); i = atomic_exchange(&logdLoggerWrite.context.sock, ret);
/* FALLTHRU */ /* FALLTHRU */
default: default:
break;
}
close(sock);
} else {
ret = atomic_exchange(&logdLoggerWrite.context.sock, sock);
if ((ret >= 0) && (ret != sock)) {
close(ret);
}
ret = 0;
}
}
}
return ret;
}
static void __logdClose(int negative_errno)
{
int sock = atomic_exchange(&logdLoggerWrite.context.sock, negative_errno);
if (sock >= 0) {
close(sock);
}
}
static void logdClose()
{
__logdClose(-EBADF);
}
static int logdAvailable(log_id_t logId)
{
if (logId >= LOG_ID_MAX || logId == LOG_ID_KERNEL) {
return -EINVAL;
}
if (atomic_load(&logdLoggerWrite.context.sock) < 0) {
if (access("/dev/socket/logdw", W_OK) == 0) {
return 0;
}
return -EBADF;
}
return 1;
}
static int logdWrite(log_id_t logId, struct timespec *ts,
struct iovec *vec, size_t nr)
{
ssize_t ret;
int sock;
static const unsigned headerLength = 1;
struct iovec newVec[nr + headerLength];
android_log_header_t header;
size_t i, payloadSize;
static atomic_int_fast32_t dropped;
static atomic_int_fast32_t droppedSecurity;
sock = atomic_load(&logdLoggerWrite.context.sock);
if (sock < 0) switch (sock) {
case -ENOTCONN:
case -ECONNREFUSED:
case -ENOENT:
break;
default:
return -EBADF;
}
/* logd, after initialization and priv drop */
if (__android_log_uid() == AID_LOGD) {
/*
* ignore log messages we send to ourself (logd).
* Such log messages are often generated by libraries we depend on
* which use standard Android logging.
*/
return 0;
}
/*
* struct {
* // what we provide to socket
* android_log_header_t header;
* // caller provides
* union {
* struct {
* char prio;
* char payload[];
* } string;
* struct {
* uint32_t tag
* char payload[];
* } binary;
* };
* };
*/
header.tid = gettid();
header.realtime.tv_sec = ts->tv_sec;
header.realtime.tv_nsec = ts->tv_nsec;
newVec[0].iov_base = (unsigned char *)&header;
newVec[0].iov_len = sizeof(header);
if (sock >= 0) {
int32_t snapshot = atomic_exchange_explicit(&droppedSecurity, 0,
memory_order_relaxed);
if (snapshot) {
android_log_event_int_t buffer;
header.id = LOG_ID_SECURITY;
buffer.header.tag = htole32(LIBLOG_LOG_TAG);
buffer.payload.type = EVENT_TYPE_INT;
buffer.payload.data = htole32(snapshot);
newVec[headerLength].iov_base = &buffer;
newVec[headerLength].iov_len = sizeof(buffer);
ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
atomic_fetch_add_explicit(&droppedSecurity, snapshot,
memory_order_relaxed);
}
}
snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
if (snapshot && __android_log_is_loggable_len(ANDROID_LOG_INFO,
"liblog",
strlen("liblog"),
ANDROID_LOG_VERBOSE)) {
android_log_event_int_t buffer;
header.id = LOG_ID_EVENTS;
buffer.header.tag = htole32(LIBLOG_LOG_TAG);
buffer.payload.type = EVENT_TYPE_INT;
buffer.payload.data = htole32(snapshot);
newVec[headerLength].iov_base = &buffer;
newVec[headerLength].iov_len = sizeof(buffer);
ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
atomic_fetch_add_explicit(&dropped, snapshot,
memory_order_relaxed);
}
}
}
header.id = logId;
for (payloadSize = 0, i = headerLength; i < nr + headerLength; i++) {
newVec[i].iov_base = vec[i - headerLength].iov_base;
payloadSize += newVec[i].iov_len = vec[i - headerLength].iov_len;
if (payloadSize > LOGGER_ENTRY_MAX_PAYLOAD) {
newVec[i].iov_len -= payloadSize - LOGGER_ENTRY_MAX_PAYLOAD;
if (newVec[i].iov_len) {
++i;
}
break; break;
} }
close(sock);
} else {
ret = atomic_exchange(&logdLoggerWrite.context.sock, sock);
if ((ret >= 0) && (ret != sock)) {
close(ret);
}
ret = 0;
}
}
}
return ret;
}
static void __logdClose(int negative_errno) {
int sock = atomic_exchange(&logdLoggerWrite.context.sock, negative_errno);
if (sock >= 0) {
close(sock);
}
}
static void logdClose() {
__logdClose(-EBADF);
}
static int logdAvailable(log_id_t logId) {
if (logId >= LOG_ID_MAX || logId == LOG_ID_KERNEL) {
return -EINVAL;
}
if (atomic_load(&logdLoggerWrite.context.sock) < 0) {
if (access("/dev/socket/logdw", W_OK) == 0) {
return 0;
}
return -EBADF;
}
return 1;
}
static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec,
size_t nr) {
ssize_t ret;
int sock;
static const unsigned headerLength = 1;
struct iovec newVec[nr + headerLength];
android_log_header_t header;
size_t i, payloadSize;
static atomic_int_fast32_t dropped;
static atomic_int_fast32_t droppedSecurity;
sock = atomic_load(&logdLoggerWrite.context.sock);
if (sock < 0) switch (sock) {
case -ENOTCONN:
case -ECONNREFUSED:
case -ENOENT:
break;
default:
return -EBADF;
} }
/* logd, after initialization and priv drop */
if (__android_log_uid() == AID_LOGD) {
/* /*
* The write below could be lost, but will never block. * ignore log messages we send to ourself (logd).
* * Such log messages are often generated by libraries we depend on
* ENOTCONN occurs if logd has died. * which use standard Android logging.
* ENOENT occurs if logd is not running and socket is missing.
* ECONNREFUSED occurs if we can not reconnect to logd.
* EAGAIN occurs if logd is overloaded.
*/ */
if (sock < 0) { return 0;
ret = sock; }
} else {
ret = TEMP_FAILURE_RETRY(writev(sock, newVec, i)); /*
if (ret < 0) { * struct {
ret = -errno; * // what we provide to socket
} * android_log_header_t header;
* // caller provides
* union {
* struct {
* char prio;
* char payload[];
* } string;
* struct {
* uint32_t tag
* char payload[];
* } binary;
* };
* };
*/
header.tid = gettid();
header.realtime.tv_sec = ts->tv_sec;
header.realtime.tv_nsec = ts->tv_nsec;
newVec[0].iov_base = (unsigned char*)&header;
newVec[0].iov_len = sizeof(header);
if (sock >= 0) {
int32_t snapshot =
atomic_exchange_explicit(&droppedSecurity, 0, memory_order_relaxed);
if (snapshot) {
android_log_event_int_t buffer;
header.id = LOG_ID_SECURITY;
buffer.header.tag = htole32(LIBLOG_LOG_TAG);
buffer.payload.type = EVENT_TYPE_INT;
buffer.payload.data = htole32(snapshot);
newVec[headerLength].iov_base = &buffer;
newVec[headerLength].iov_len = sizeof(buffer);
ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
atomic_fetch_add_explicit(&droppedSecurity, snapshot,
memory_order_relaxed);
}
} }
switch(ret) { snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
if (snapshot &&
__android_log_is_loggable_len(ANDROID_LOG_INFO, "liblog",
strlen("liblog"), ANDROID_LOG_VERBOSE)) {
android_log_event_int_t buffer;
header.id = LOG_ID_EVENTS;
buffer.header.tag = htole32(LIBLOG_LOG_TAG);
buffer.payload.type = EVENT_TYPE_INT;
buffer.payload.data = htole32(snapshot);
newVec[headerLength].iov_base = &buffer;
newVec[headerLength].iov_len = sizeof(buffer);
ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
}
}
}
header.id = logId;
for (payloadSize = 0, i = headerLength; i < nr + headerLength; i++) {
newVec[i].iov_base = vec[i - headerLength].iov_base;
payloadSize += newVec[i].iov_len = vec[i - headerLength].iov_len;
if (payloadSize > LOGGER_ENTRY_MAX_PAYLOAD) {
newVec[i].iov_len -= payloadSize - LOGGER_ENTRY_MAX_PAYLOAD;
if (newVec[i].iov_len) {
++i;
}
break;
}
}
/*
* The write below could be lost, but will never block.
*
* ENOTCONN occurs if logd has died.
* ENOENT occurs if logd is not running and socket is missing.
* ECONNREFUSED occurs if we can not reconnect to logd.
* EAGAIN occurs if logd is overloaded.
*/
if (sock < 0) {
ret = sock;
} else {
ret = TEMP_FAILURE_RETRY(writev(sock, newVec, i));
if (ret < 0) {
ret = -errno;
}
}
switch (ret) {
case -ENOTCONN: case -ENOTCONN:
case -ECONNREFUSED: case -ECONNREFUSED:
case -ENOENT: case -ENOENT:
if (__android_log_trylock()) { if (__android_log_trylock()) {
return ret; /* in a signal handler? try again when less stressed */ return ret; /* in a signal handler? try again when less stressed */
} }
__logdClose(ret); __logdClose(ret);
ret = logdOpen(); ret = logdOpen();
__android_log_unlock(); __android_log_unlock();
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
ret = TEMP_FAILURE_RETRY(writev( ret = TEMP_FAILURE_RETRY(
atomic_load(&logdLoggerWrite.context.sock), newVec, i)); writev(atomic_load(&logdLoggerWrite.context.sock), newVec, i));
if (ret < 0) { if (ret < 0) {
ret = -errno; ret = -errno;
} }
/* FALLTHRU */ /* FALLTHRU */
default: default:
break; break;
} }
if (ret > (ssize_t)sizeof(header)) { if (ret > (ssize_t)sizeof(header)) {
ret -= sizeof(header); ret -= sizeof(header);
} else if (ret == -EAGAIN) { } else if (ret == -EAGAIN) {
atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed); atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
if (logId == LOG_ID_SECURITY) { if (logId == LOG_ID_SECURITY) {
atomic_fetch_add_explicit(&droppedSecurity, 1, atomic_fetch_add_explicit(&droppedSecurity, 1, memory_order_relaxed);
memory_order_relaxed);
}
} }
}
return ret; return ret;
} }

View file

@ -30,25 +30,25 @@ __BEGIN_DECLS
/* Union, sock or fd of zero is not allowed unless static initialized */ /* Union, sock or fd of zero is not allowed unless static initialized */
union android_log_context { union android_log_context {
void *private; void* priv;
atomic_int sock; atomic_int sock;
atomic_int fd; atomic_int fd;
struct listnode *node; struct listnode* node;
atomic_uintptr_t atomic_pointer; atomic_uintptr_t atomic_pointer;
}; };
struct android_log_transport_write { struct android_log_transport_write {
struct listnode node; struct listnode node;
const char *name; /* human name to describe the transport */ const char* name; /* human name to describe the transport */
unsigned logMask; /* mask cache of available() success */ unsigned logMask; /* mask cache of available() success */
union android_log_context context; /* Initialized by static allocation */ union android_log_context context; /* Initialized by static allocation */
int (*available)(log_id_t logId); /* Does not cause resources to be taken */ int (*available)(log_id_t logId); /* Does not cause resources to be taken */
int (*open)(); /* can be called multiple times, reusing current resources */ int (*open)(); /* can be called multiple times, reusing current resources */
void (*close)(); /* free up resources */ void (*close)(); /* free up resources */
/* write log to transport, returns number of bytes propagated, or -errno */ /* write log to transport, returns number of bytes propagated, or -errno */
int (*write)(log_id_t logId, struct timespec *ts, int (*write)(log_id_t logId, struct timespec* ts, struct iovec* vec,
struct iovec *vec, size_t nr); size_t nr);
}; };
struct android_log_logger_list; struct android_log_logger_list;
@ -57,45 +57,44 @@ struct android_log_logger;
struct android_log_transport_read { struct android_log_transport_read {
struct listnode node; struct listnode node;
const char *name; /* human name to describe the transport */ const char* name; /* human name to describe the transport */
/* Does not cause resources to be taken */ /* Does not cause resources to be taken */
int (*available)(log_id_t logId); int (*available)(log_id_t logId);
int (*version)(struct android_log_logger *logger, int (*version)(struct android_log_logger* logger,
struct android_log_transport_context *transp); struct android_log_transport_context* transp);
/* Release resources taken by the following interfaces */ /* Release resources taken by the following interfaces */
void (*close)(struct android_log_logger_list *logger_list, void (*close)(struct android_log_logger_list* logger_list,
struct android_log_transport_context *transp); struct android_log_transport_context* transp);
/* /*
* Expect all to instantiate open automagically on any call, * Expect all to instantiate open automagically on any call,
* so we do not have an explicit open call. * so we do not have an explicit open call.
*/ */
int (*read)(struct android_log_logger_list *logger_list, int (*read)(struct android_log_logger_list* logger_list,
struct android_log_transport_context *transp, struct android_log_transport_context* transp,
struct log_msg *log_msg); struct log_msg* log_msg);
/* Must only be called if not ANDROID_LOG_NONBLOCK (blocking) */ /* Must only be called if not ANDROID_LOG_NONBLOCK (blocking) */
int (*poll)(struct android_log_logger_list *logger_list, int (*poll)(struct android_log_logger_list* logger_list,
struct android_log_transport_context *transp); struct android_log_transport_context* transp);
int (*clear)(struct android_log_logger *logger, int (*clear)(struct android_log_logger* logger,
struct android_log_transport_context *transp); struct android_log_transport_context* transp);
ssize_t (*setSize)(struct android_log_logger *logger, ssize_t (*setSize)(struct android_log_logger* logger,
struct android_log_transport_context *transp, struct android_log_transport_context* transp, size_t size);
size_t size); ssize_t (*getSize)(struct android_log_logger* logger,
ssize_t (*getSize)(struct android_log_logger *logger, struct android_log_transport_context* transp);
struct android_log_transport_context *transp); ssize_t (*getReadableSize)(struct android_log_logger* logger,
ssize_t (*getReadableSize)(struct android_log_logger *logger, struct android_log_transport_context* transp);
struct android_log_transport_context *transp);
ssize_t (*getPrune)(struct android_log_logger_list *logger_list, ssize_t (*getPrune)(struct android_log_logger_list* logger_list,
struct android_log_transport_context *transp, struct android_log_transport_context* transp, char* buf,
char *buf, size_t len); size_t len);
ssize_t (*setPrune)(struct android_log_logger_list *logger_list, ssize_t (*setPrune)(struct android_log_logger_list* logger_list,
struct android_log_transport_context *transp, struct android_log_transport_context* transp, char* buf,
char *buf, size_t len); size_t len);
ssize_t (*getStats)(struct android_log_logger_list *logger_list, ssize_t (*getStats)(struct android_log_logger_list* logger_list,
struct android_log_transport_context *transp, struct android_log_transport_context* transp, char* buf,
char *buf, size_t len); size_t len);
}; };
struct android_log_logger_list { struct android_log_logger_list {
@ -110,7 +109,7 @@ struct android_log_logger_list {
struct android_log_logger { struct android_log_logger {
struct listnode node; struct listnode node;
struct android_log_logger_list *parent; struct android_log_logger_list* parent;
log_id_t logId; log_id_t logId;
}; };
@ -118,34 +117,32 @@ struct android_log_logger {
struct android_log_transport_context { struct android_log_transport_context {
struct listnode node; struct listnode node;
union android_log_context context; /* zero init per-transport context */ union android_log_context context; /* zero init per-transport context */
struct android_log_logger_list *parent; struct android_log_logger_list* parent;
struct android_log_transport_read *transport; struct android_log_transport_read* transport;
unsigned logMask; /* mask of requested log buffers */ unsigned logMask; /* mask of requested log buffers */
int ret; /* return value associated with following data */ int ret; /* return value associated with following data */
struct log_msg logMsg; /* peek at upcoming data, valid if logMsg.len != 0 */ struct log_msg logMsg; /* peek at upcoming data, valid if logMsg.len != 0 */
}; };
/* assumes caller has structures read-locked, single threaded, or fenced */ /* assumes caller has structures read-locked, single threaded, or fenced */
#define transport_context_for_each(transp, logger_list) \ #define transport_context_for_each(transp, logger_list) \
for ((transp) = node_to_item((logger_list)->transport.next, \ for ((transp) = node_to_item((logger_list)->transport.next, \
struct android_log_transport_context, \ struct android_log_transport_context, node); \
node); \ ((transp) != node_to_item(&(logger_list)->transport, \
((transp) != node_to_item(&(logger_list)->transport, \ struct android_log_transport_context, node)) && \
struct android_log_transport_context, \ ((transp)->parent == (logger_list)); \
node)) && \ (transp) = node_to_item((transp)->node.next, \
((transp)->parent == (logger_list)); \ struct android_log_transport_context, node))
(transp) = node_to_item((transp)->node.next, \
struct android_log_transport_context, node))
#define logger_for_each(logp, logger_list) \ #define logger_for_each(logp, logger_list) \
for ((logp) = node_to_item((logger_list)->logger.next, \ for ((logp) = node_to_item((logger_list)->logger.next, \
struct android_log_logger, node); \ struct android_log_logger, node); \
((logp) != node_to_item(&(logger_list)->logger, \ ((logp) != node_to_item(&(logger_list)->logger, \
struct android_log_logger, node)) && \ struct android_log_logger, node)) && \
((logp)->parent == (logger_list)); \ ((logp)->parent == (logger_list)); \
(logp) = node_to_item((logp)->node.next, \ (logp) = \
struct android_log_logger, node)) node_to_item((logp)->node.next, struct android_log_logger, node))
/* /*
* Global list of log readers. * Global list of log readers.
@ -168,35 +165,35 @@ LIBLOG_HIDDEN pthread_rwlock_t __android_log_readers_lock;
#endif #endif
/* Must be called with logger_list_rdlock() or logger_list_wrlock() held */ /* Must be called with logger_list_rdlock() or logger_list_wrlock() held */
#define logger_list_for_each(logger_list) \ #define logger_list_for_each(logger_list) \
for ((logger_list) = node_to_item(&__android_log_readers, \ for ((logger_list) = node_to_item(&__android_log_readers, \
struct android_log_logger_list, \ struct android_log_logger_list, node); \
node); \ (logger_list) != node_to_item(&__android_log_readers, \
(logger_list) != node_to_item(&__android_log_readers, \ struct android_log_logger_list, node) && \
struct android_log_logger_list, \ (logger_list) != node_to_item((logger_list)->node.next, \
node) && \ struct android_log_logger_list, node); \
(logger_list) != node_to_item((logger_list)->node.next, \ (logger_list) = node_to_item((logger_list)->node.next, \
struct android_log_logger_list, \ struct android_log_logger_list, node))
node); \
(logger_list) = node_to_item((logger_list)->node.next, \
struct android_log_logger_list, \
node))
/* OS specific dribs and drabs */ /* OS specific dribs and drabs */
#if defined(_WIN32) #if defined(_WIN32)
#include <private/android_filesystem_config.h> #include <private/android_filesystem_config.h>
typedef uint32_t uid_t; typedef uint32_t uid_t;
static inline uid_t __android_log_uid() { return AID_SYSTEM; } static inline uid_t __android_log_uid() {
return AID_SYSTEM;
}
#else #else
static inline uid_t __android_log_uid() { return getuid(); } static inline uid_t __android_log_uid() {
return getuid();
}
#endif #endif
LIBLOG_HIDDEN void __android_log_lock(); LIBLOG_HIDDEN void __android_log_lock();
LIBLOG_HIDDEN int __android_log_trylock(); LIBLOG_HIDDEN int __android_log_trylock();
LIBLOG_HIDDEN void __android_log_unlock(); LIBLOG_HIDDEN void __android_log_unlock();
LIBLOG_HIDDEN int __android_log_frontend; LIBLOG_HIDDEN int __android_log_transport;
__END_DECLS __END_DECLS

View file

@ -28,29 +28,26 @@
static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
#endif #endif
LIBLOG_HIDDEN void __android_log_lock() LIBLOG_HIDDEN void __android_log_lock() {
{
#if !defined(_WIN32) #if !defined(_WIN32)
/* /*
* If we trigger a signal handler in the middle of locked activity and the * If we trigger a signal handler in the middle of locked activity and the
* signal handler logs a message, we could get into a deadlock state. * signal handler logs a message, we could get into a deadlock state.
*/ */
pthread_mutex_lock(&log_init_lock); pthread_mutex_lock(&log_init_lock);
#endif #endif
} }
LIBLOG_HIDDEN int __android_log_trylock() LIBLOG_HIDDEN int __android_log_trylock() {
{
#if !defined(_WIN32) #if !defined(_WIN32)
return pthread_mutex_trylock(&log_init_lock); return pthread_mutex_trylock(&log_init_lock);
#else #else
return 0; return 0;
#endif #endif
} }
LIBLOG_HIDDEN void __android_log_unlock() LIBLOG_HIDDEN void __android_log_unlock() {
{
#if !defined(_WIN32) #if !defined(_WIN32)
pthread_mutex_unlock(&log_init_lock); pthread_mutex_unlock(&log_init_lock);
#endif #endif
} }

View file

@ -21,44 +21,44 @@
#include "log_portability.h" #include "log_portability.h"
/* In the future, we would like to make this list extensible */ /* In the future, we would like to make this list extensible */
static const char *LOG_NAME[LOG_ID_MAX] = { static const char* LOG_NAME[LOG_ID_MAX] = {
[LOG_ID_MAIN] = "main", /* clang-format off */
[LOG_ID_RADIO] = "radio", [LOG_ID_MAIN] = "main",
[LOG_ID_EVENTS] = "events", [LOG_ID_RADIO] = "radio",
[LOG_ID_SYSTEM] = "system", [LOG_ID_EVENTS] = "events",
[LOG_ID_CRASH] = "crash", [LOG_ID_SYSTEM] = "system",
[LOG_ID_SECURITY] = "security", [LOG_ID_CRASH] = "crash",
[LOG_ID_KERNEL] = "kernel", [LOG_ID_SECURITY] = "security",
[LOG_ID_KERNEL] = "kernel",
/* clang-format on */
}; };
LIBLOG_ABI_PUBLIC const char *android_log_id_to_name(log_id_t log_id) LIBLOG_ABI_PUBLIC const char* android_log_id_to_name(log_id_t log_id) {
{ if (log_id >= LOG_ID_MAX) {
if (log_id >= LOG_ID_MAX) { log_id = LOG_ID_MAIN;
log_id = LOG_ID_MAIN; }
} return LOG_NAME[log_id];
return LOG_NAME[log_id];
} }
LIBLOG_ABI_PUBLIC log_id_t android_name_to_log_id(const char *logName) LIBLOG_ABI_PUBLIC log_id_t android_name_to_log_id(const char* logName) {
{ const char* b;
const char *b; int ret;
int ret;
if (!logName) { if (!logName) {
return -1; /* NB: log_id_t is unsigned */ return -1; /* NB: log_id_t is unsigned */
} }
b = strrchr(logName, '/'); b = strrchr(logName, '/');
if (!b) { if (!b) {
b = logName; b = logName;
} else { } else {
++b; ++b;
} }
for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) { for (ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
const char *l = LOG_NAME[ret]; const char* l = LOG_NAME[ret];
if (l && !strcmp(b, l)) { if (l && !strcmp(b, l)) {
return ret; return ret;
}
} }
return -1; /* should never happen */ }
return -1; /* should never happen */
} }

View file

@ -33,135 +33,128 @@
/* android_logger_alloc unimplemented, no use case */ /* android_logger_alloc unimplemented, no use case */
/* android_logger_free not exported */ /* android_logger_free not exported */
static void android_logger_free(struct logger *logger) static void android_logger_free(struct logger* logger) {
{ struct android_log_logger* logger_internal =
struct android_log_logger *logger_internal = (struct android_log_logger*)logger;
(struct android_log_logger *)logger;
if (!logger_internal) { if (!logger_internal) {
return; return;
} }
list_remove(&logger_internal->node); list_remove(&logger_internal->node);
free(logger_internal); free(logger_internal);
} }
/* android_logger_alloc unimplemented, no use case */ /* android_logger_alloc unimplemented, no use case */
/* method for getting the associated sublog id */ /* method for getting the associated sublog id */
LIBLOG_ABI_PUBLIC log_id_t android_logger_get_id(struct logger *logger) LIBLOG_ABI_PUBLIC log_id_t android_logger_get_id(struct logger* logger) {
{ return ((struct android_log_logger*)logger)->logId;
return ((struct android_log_logger *)logger)->logId;
} }
static int init_transport_context(struct android_log_logger_list *logger_list) static int init_transport_context(struct android_log_logger_list* logger_list) {
{ struct android_log_transport_read* transport;
struct android_log_transport_read *transport; struct listnode* node;
struct listnode *node;
if (!logger_list) { if (!logger_list) {
return -EINVAL; return -EINVAL;
} }
if (list_empty(&logger_list->logger)) { if (list_empty(&logger_list->logger)) {
return -EINVAL; return -EINVAL;
} }
if (!list_empty(&logger_list->transport)) { if (!list_empty(&logger_list->transport)) {
return 0;
}
__android_log_lock();
/* mini __write_to_log_initialize() to populate transports */
if (list_empty(&__android_log_transport_read) &&
list_empty(&__android_log_persist_read)) {
__android_log_config_read();
}
__android_log_unlock();
node = (logger_list->mode & ANDROID_LOG_PSTORE) ?
&__android_log_persist_read : &__android_log_transport_read;
read_transport_for_each(transport, node) {
struct android_log_transport_context *transp;
struct android_log_logger *logger;
unsigned logMask = 0;
logger_for_each(logger, logger_list) {
log_id_t logId = logger->logId;
if ((logId == LOG_ID_SECURITY) &&
(__android_log_uid() != AID_SYSTEM)) {
continue;
}
if (transport->read &&
(!transport->available ||
(transport->available(logId) >= 0))) {
logMask |= 1 << logId;
}
}
if (!logMask) {
continue;
}
transp = calloc(1, sizeof(*transp));
if (!transp) {
return -ENOMEM;
}
transp->parent = logger_list;
transp->transport = transport;
transp->logMask = logMask;
transp->ret = 1;
list_add_tail(&logger_list->transport, &transp->node);
}
if (list_empty(&logger_list->transport)) {
return -ENODEV;
}
return 0; return 0;
}
__android_log_lock();
/* mini __write_to_log_initialize() to populate transports */
if (list_empty(&__android_log_transport_read) &&
list_empty(&__android_log_persist_read)) {
__android_log_config_read();
}
__android_log_unlock();
node = (logger_list->mode & ANDROID_LOG_PSTORE)
? &__android_log_persist_read
: &__android_log_transport_read;
read_transport_for_each(transport, node) {
struct android_log_transport_context* transp;
struct android_log_logger* logger;
unsigned logMask = 0;
logger_for_each(logger, logger_list) {
log_id_t logId = logger->logId;
if ((logId == LOG_ID_SECURITY) && (__android_log_uid() != AID_SYSTEM)) {
continue;
}
if (transport->read &&
(!transport->available || (transport->available(logId) >= 0))) {
logMask |= 1 << logId;
}
}
if (!logMask) {
continue;
}
transp = calloc(1, sizeof(*transp));
if (!transp) {
return -ENOMEM;
}
transp->parent = logger_list;
transp->transport = transport;
transp->logMask = logMask;
transp->ret = 1;
list_add_tail(&logger_list->transport, &transp->node);
}
if (list_empty(&logger_list->transport)) {
return -ENODEV;
}
return 0;
} }
#define LOGGER_FUNCTION(logger, def, func, args...) \ #define LOGGER_FUNCTION(logger, def, func, args...) \
ssize_t ret = -EINVAL; \ ssize_t ret = -EINVAL; \
struct android_log_transport_context *transp; \ struct android_log_transport_context* transp; \
struct android_log_logger *logger_internal = \ struct android_log_logger* logger_internal = \
(struct android_log_logger *)(logger); \ (struct android_log_logger*)(logger); \
\ \
if (!logger_internal) { \ if (!logger_internal) { \
return ret; \ return ret; \
} \ } \
ret = init_transport_context(logger_internal->parent); \ ret = init_transport_context(logger_internal->parent); \
if (ret < 0) { \ if (ret < 0) { \
return ret; \ return ret; \
} \ } \
\ \
ret = (def); \ ret = (def); \
transport_context_for_each(transp, logger_internal->parent) { \ transport_context_for_each(transp, logger_internal->parent) { \
if ((transp->logMask & (1 << logger_internal->logId)) && \ if ((transp->logMask & (1 << logger_internal->logId)) && \
transp->transport && transp->transport->func) { \ transp->transport && transp->transport->func) { \
ssize_t retval = (transp->transport->func)(logger_internal, \ ssize_t retval = \
transp, ## args); \ (transp->transport->func)(logger_internal, transp, ##args); \
if ((ret >= 0) || (ret == (def))) { \ if ((ret >= 0) || (ret == (def))) { \
ret = retval; \ ret = retval; \
} \ } \
} \ } \
} \ } \
return ret return ret
LIBLOG_ABI_PUBLIC int android_logger_clear(struct logger *logger) LIBLOG_ABI_PUBLIC int android_logger_clear(struct logger* logger) {
{ LOGGER_FUNCTION(logger, -ENODEV, clear);
LOGGER_FUNCTION(logger, -ENODEV, clear);
} }
/* returns the total size of the log's ring buffer */ /* returns the total size of the log's ring buffer */
LIBLOG_ABI_PUBLIC long android_logger_get_log_size(struct logger *logger) LIBLOG_ABI_PUBLIC long android_logger_get_log_size(struct logger* logger) {
{ LOGGER_FUNCTION(logger, -ENODEV, getSize);
LOGGER_FUNCTION(logger, -ENODEV, getSize);
} }
LIBLOG_ABI_PUBLIC int android_logger_set_log_size(struct logger *logger, LIBLOG_ABI_PUBLIC int android_logger_set_log_size(struct logger* logger,
unsigned long size) unsigned long size) {
{ LOGGER_FUNCTION(logger, -ENODEV, setSize, size);
LOGGER_FUNCTION(logger, -ENODEV, setSize, size);
} }
/* /*
@ -169,376 +162,338 @@ LIBLOG_ABI_PUBLIC int android_logger_set_log_size(struct logger *logger,
* log consumed) * log consumed)
*/ */
LIBLOG_ABI_PUBLIC long android_logger_get_log_readable_size( LIBLOG_ABI_PUBLIC long android_logger_get_log_readable_size(
struct logger *logger) struct logger* logger) {
{ LOGGER_FUNCTION(logger, -ENODEV, getReadableSize);
LOGGER_FUNCTION(logger, -ENODEV, getReadableSize);
} }
/* /*
* returns the logger version * returns the logger version
*/ */
LIBLOG_ABI_PUBLIC int android_logger_get_log_version(struct logger *logger) LIBLOG_ABI_PUBLIC int android_logger_get_log_version(struct logger* logger) {
{ LOGGER_FUNCTION(logger, 4, version);
LOGGER_FUNCTION(logger, 4, version);
} }
#define LOGGER_LIST_FUNCTION(logger_list, def, func, args...) \ #define LOGGER_LIST_FUNCTION(logger_list, def, func, args...) \
struct android_log_transport_context *transp; \ struct android_log_transport_context* transp; \
struct android_log_logger_list *logger_list_internal = \ struct android_log_logger_list* logger_list_internal = \
(struct android_log_logger_list *)(logger_list); \ (struct android_log_logger_list*)(logger_list); \
\ \
ssize_t ret = init_transport_context(logger_list_internal); \ ssize_t ret = init_transport_context(logger_list_internal); \
if (ret < 0) { \ if (ret < 0) { \
return ret; \ return ret; \
} \ } \
\ \
ret = (def); \ ret = (def); \
transport_context_for_each(transp, logger_list_internal) { \ transport_context_for_each(transp, logger_list_internal) { \
if (transp->transport && (transp->transport->func)) { \ if (transp->transport && (transp->transport->func)) { \
ssize_t retval = (transp->transport->func)(logger_list_internal, \ ssize_t retval = \
transp, ## args); \ (transp->transport->func)(logger_list_internal, transp, ##args); \
if ((ret >= 0) || (ret == (def))) { \ if ((ret >= 0) || (ret == (def))) { \
ret = retval; \ ret = retval; \
} \ } \
} \ } \
} \ } \
return ret return ret
/* /*
* returns statistics * returns statistics
*/ */
LIBLOG_ABI_PUBLIC ssize_t android_logger_get_statistics( LIBLOG_ABI_PUBLIC ssize_t android_logger_get_statistics(
struct logger_list *logger_list, struct logger_list* logger_list, char* buf, size_t len) {
char *buf, size_t len) LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getStats, buf, len);
{
LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getStats, buf, len);
} }
LIBLOG_ABI_PUBLIC ssize_t android_logger_get_prune_list( LIBLOG_ABI_PUBLIC ssize_t android_logger_get_prune_list(
struct logger_list *logger_list, struct logger_list* logger_list, char* buf, size_t len) {
char *buf, size_t len) LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getPrune, buf, len);
{
LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getPrune, buf, len);
} }
LIBLOG_ABI_PUBLIC int android_logger_set_prune_list( LIBLOG_ABI_PUBLIC int android_logger_set_prune_list(
struct logger_list *logger_list, struct logger_list* logger_list, char* buf, size_t len) {
char *buf, size_t len) LOGGER_LIST_FUNCTION(logger_list, -ENODEV, setPrune, buf, len);
{
LOGGER_LIST_FUNCTION(logger_list, -ENODEV, setPrune, buf, len);
} }
LIBLOG_HIDDEN struct listnode __android_log_readers = LIBLOG_HIDDEN struct listnode __android_log_readers = { &__android_log_readers,
{ &__android_log_readers, &__android_log_readers }; &__android_log_readers };
#if !defined(_WIN32) #if !defined(_WIN32)
LIBLOG_HIDDEN pthread_rwlock_t __android_log_readers_lock = LIBLOG_HIDDEN pthread_rwlock_t __android_log_readers_lock =
PTHREAD_RWLOCK_INITIALIZER; PTHREAD_RWLOCK_INITIALIZER;
#endif #endif
LIBLOG_ABI_PUBLIC struct logger_list *android_logger_list_alloc( LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_alloc(
int mode, int mode, unsigned int tail, pid_t pid) {
unsigned int tail, struct android_log_logger_list* logger_list;
pid_t pid)
{
struct android_log_logger_list *logger_list;
logger_list = calloc(1, sizeof(*logger_list)); logger_list = calloc(1, sizeof(*logger_list));
if (!logger_list) { if (!logger_list) {
return NULL; return NULL;
} }
list_init(&logger_list->logger); list_init(&logger_list->logger);
list_init(&logger_list->transport); list_init(&logger_list->transport);
logger_list->mode = mode; logger_list->mode = mode;
logger_list->tail = tail; logger_list->tail = tail;
logger_list->pid = pid; logger_list->pid = pid;
logger_list_wrlock(); logger_list_wrlock();
list_add_tail(&__android_log_readers, &logger_list->node); list_add_tail(&__android_log_readers, &logger_list->node);
logger_list_unlock(); logger_list_unlock();
return (struct logger_list *)logger_list; return (struct logger_list*)logger_list;
} }
LIBLOG_ABI_PUBLIC struct logger_list *android_logger_list_alloc_time( LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_alloc_time(
int mode, int mode, log_time start, pid_t pid) {
log_time start, struct android_log_logger_list* logger_list;
pid_t pid)
{
struct android_log_logger_list *logger_list;
logger_list = calloc(1, sizeof(*logger_list)); logger_list = calloc(1, sizeof(*logger_list));
if (!logger_list) { if (!logger_list) {
return NULL; return NULL;
} }
list_init(&logger_list->logger); list_init(&logger_list->logger);
list_init(&logger_list->transport); list_init(&logger_list->transport);
logger_list->mode = mode; logger_list->mode = mode;
logger_list->start = start; logger_list->start = start;
logger_list->pid = pid; logger_list->pid = pid;
logger_list_wrlock(); logger_list_wrlock();
list_add_tail(&__android_log_readers, &logger_list->node); list_add_tail(&__android_log_readers, &logger_list->node);
logger_list_unlock(); logger_list_unlock();
return (struct logger_list *)logger_list; return (struct logger_list*)logger_list;
} }
/* android_logger_list_register unimplemented, no use case */ /* android_logger_list_register unimplemented, no use case */
/* android_logger_list_unregister unimplemented, no use case */ /* android_logger_list_unregister unimplemented, no use case */
/* Open the named log and add it to the logger list */ /* Open the named log and add it to the logger list */
LIBLOG_ABI_PUBLIC struct logger *android_logger_open( LIBLOG_ABI_PUBLIC struct logger* android_logger_open(
struct logger_list *logger_list, struct logger_list* logger_list, log_id_t logId) {
log_id_t logId) struct android_log_logger_list* logger_list_internal =
{ (struct android_log_logger_list*)logger_list;
struct android_log_logger_list *logger_list_internal = struct android_log_logger* logger;
(struct android_log_logger_list *)logger_list;
struct android_log_logger *logger;
if (!logger_list_internal || (logId >= LOG_ID_MAX)) { if (!logger_list_internal || (logId >= LOG_ID_MAX)) {
goto err; goto err;
}
logger_for_each(logger, logger_list_internal) {
if (logger->logId == logId) {
goto ok;
} }
}
logger_for_each(logger, logger_list_internal) { logger = calloc(1, sizeof(*logger));
if (logger->logId == logId) { if (!logger) {
goto ok; goto err;
} }
}
logger = calloc(1, sizeof(*logger)); logger->logId = logId;
if (!logger) { list_add_tail(&logger_list_internal->logger, &logger->node);
goto err; logger->parent = logger_list_internal;
}
logger->logId = logId; /* Reset known transports to re-evaluate, we just added one */
list_add_tail(&logger_list_internal->logger, &logger->node); while (!list_empty(&logger_list_internal->transport)) {
logger->parent = logger_list_internal; struct listnode* node = list_head(&logger_list_internal->transport);
struct android_log_transport_context* transp =
node_to_item(node, struct android_log_transport_context, node);
/* Reset known transports to re-evaluate, we just added one */ list_remove(&transp->node);
while (!list_empty(&logger_list_internal->transport)) { free(transp);
struct listnode *node = list_head(&logger_list_internal->transport); }
struct android_log_transport_context *transp = goto ok;
node_to_item(node, struct android_log_transport_context, node);
list_remove(&transp->node);
free(transp);
}
goto ok;
err: err:
logger = NULL; logger = NULL;
ok: ok:
return (struct logger *)logger; return (struct logger*)logger;
} }
/* Open the single named log and make it part of a new logger list */ /* Open the single named log and make it part of a new logger list */
LIBLOG_ABI_PUBLIC struct logger_list *android_logger_list_open( LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_open(
log_id_t logId, log_id_t logId, int mode, unsigned int tail, pid_t pid) {
int mode, struct logger_list* logger_list = android_logger_list_alloc(mode, tail, pid);
unsigned int tail,
pid_t pid)
{
struct logger_list *logger_list =
android_logger_list_alloc(mode, tail, pid);
if (!logger_list) { if (!logger_list) {
return NULL; return NULL;
} }
if (!android_logger_open(logger_list, logId)) { if (!android_logger_open(logger_list, logId)) {
android_logger_list_free(logger_list); android_logger_list_free(logger_list);
return NULL; return NULL;
} }
return logger_list; return logger_list;
} }
/* Validate log_msg packet, read function has already been null checked */ /* Validate log_msg packet, read function has already been null checked */
static int android_transport_read(struct android_log_logger_list *logger_list, static int android_transport_read(struct android_log_logger_list* logger_list,
struct android_log_transport_context *transp, struct android_log_transport_context* transp,
struct log_msg *log_msg) struct log_msg* log_msg) {
{ int ret = (*transp->transport->read)(logger_list, transp, log_msg);
int ret = (*transp->transport->read)(logger_list, transp, log_msg);
if (ret > (int)sizeof(*log_msg)) { if (ret > (int)sizeof(*log_msg)) {
ret = sizeof(*log_msg); ret = sizeof(*log_msg);
}
transp->ret = ret;
/* propagate errors, or make sure len & hdr_size members visible */
if (ret < (int)(sizeof(log_msg->entry.len) + sizeof(log_msg->entry.hdr_size))) {
if (ret >= (int)sizeof(log_msg->entry.len)) {
log_msg->entry.len = 0;
} }
transp->ret = ret;
/* propagate errors, or make sure len & hdr_size members visible */
if (ret < (int)(sizeof(log_msg->entry.len) +
sizeof(log_msg->entry.hdr_size))) {
if (ret >= (int)sizeof(log_msg->entry.len)) {
log_msg->entry.len = 0;
}
return ret;
}
/* hdr_size correction (logger_entry -> logger_entry_v2+ conversion) */
if (log_msg->entry_v2.hdr_size == 0) {
log_msg->entry_v2.hdr_size = sizeof(struct logger_entry);
}
if ((log_msg->entry_v2.hdr_size < sizeof(log_msg->entry_v1)) ||
(log_msg->entry_v2.hdr_size > sizeof(log_msg->entry))) {
return -EINVAL;
}
/* len validation */
if (ret <= log_msg->entry_v2.hdr_size) {
log_msg->entry.len = 0;
} else {
log_msg->entry.len = ret - log_msg->entry_v2.hdr_size;
}
return ret; return ret;
}
/* hdr_size correction (logger_entry -> logger_entry_v2+ conversion) */
if (log_msg->entry_v2.hdr_size == 0) {
log_msg->entry_v2.hdr_size = sizeof(struct logger_entry);
}
if ((log_msg->entry_v2.hdr_size < sizeof(log_msg->entry_v1)) ||
(log_msg->entry_v2.hdr_size > sizeof(log_msg->entry))) {
return -EINVAL;
}
/* len validation */
if (ret <= log_msg->entry_v2.hdr_size) {
log_msg->entry.len = 0;
} else {
log_msg->entry.len = ret - log_msg->entry_v2.hdr_size;
}
return ret;
} }
/* Read from the selected logs */ /* Read from the selected logs */
LIBLOG_ABI_PUBLIC int android_logger_list_read(struct logger_list *logger_list, LIBLOG_ABI_PUBLIC int android_logger_list_read(struct logger_list* logger_list,
struct log_msg *log_msg) struct log_msg* log_msg) {
{ struct android_log_transport_context* transp;
struct android_log_transport_context *transp; struct android_log_logger_list* logger_list_internal =
struct android_log_logger_list *logger_list_internal = (struct android_log_logger_list*)logger_list;
(struct android_log_logger_list *)logger_list;
int ret = init_transport_context(logger_list_internal); int ret = init_transport_context(logger_list_internal);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
/* at least one transport */ /* at least one transport */
transp = node_to_item(logger_list_internal->transport.next, transp = node_to_item(logger_list_internal->transport.next,
struct android_log_transport_context, node); struct android_log_transport_context, node);
/* more than one transport? */ /* more than one transport? */
if (transp->node.next != &logger_list_internal->transport) { if (transp->node.next != &logger_list_internal->transport) {
/* Poll and merge sort the entries if from multiple transports */ /* Poll and merge sort the entries if from multiple transports */
struct android_log_transport_context *oldest = NULL; struct android_log_transport_context* oldest = NULL;
int ret; int ret;
int polled = 0; int polled = 0;
do { do {
if (polled) { if (polled) {
sched_yield(); sched_yield();
}
ret = -1000;
polled = 0;
do {
int retval = transp->ret;
if ((retval > 0) && !transp->logMsg.entry.len) {
if (!transp->transport->read) {
retval = transp->ret = 0;
} else if ((logger_list_internal->mode & ANDROID_LOG_NONBLOCK) ||
!transp->transport->poll) {
retval = android_transport_read(logger_list_internal, transp,
&transp->logMsg);
} else {
int pollval =
(*transp->transport->poll)(logger_list_internal, transp);
if (pollval <= 0) {
sched_yield();
pollval = (*transp->transport->poll)(logger_list_internal, transp);
} }
ret = -1000; polled = 1;
polled = 0; if (pollval < 0) {
do { if ((pollval == -EINTR) || (pollval == -EAGAIN)) {
int retval = transp->ret; return -EAGAIN;
if ((retval > 0) && !transp->logMsg.entry.len) { }
if (!transp->transport->read) { retval = transp->ret = pollval;
retval = transp->ret = 0; } else if (pollval > 0) {
} else if ((logger_list_internal->mode & retval = android_transport_read(logger_list_internal, transp,
ANDROID_LOG_NONBLOCK) || &transp->logMsg);
!transp->transport->poll) { }
retval = android_transport_read( }
logger_list_internal, }
transp, if (ret < retval) {
&transp->logMsg); ret = retval;
} else { }
int pollval = (*transp->transport->poll)( if ((transp->ret > 0) && transp->logMsg.entry.len &&
logger_list_internal, transp); (!oldest || (oldest->logMsg.entry.sec > transp->logMsg.entry.sec) ||
if (pollval <= 0) { ((oldest->logMsg.entry.sec == transp->logMsg.entry.sec) &&
sched_yield(); (oldest->logMsg.entry.nsec > transp->logMsg.entry.nsec)))) {
pollval = (*transp->transport->poll)( oldest = transp;
logger_list_internal, transp); }
} transp = node_to_item(transp->node.next,
polled = 1; struct android_log_transport_context, node);
if (pollval < 0) { } while (transp != node_to_item(&logger_list_internal->transport,
if ((pollval == -EINTR) || (pollval == -EAGAIN)) {
return -EAGAIN;
}
retval = transp->ret = pollval;
} else if (pollval > 0) {
retval = android_transport_read(
logger_list_internal,
transp,
&transp->logMsg);
}
}
}
if (ret < retval) {
ret = retval;
}
if ((transp->ret > 0) && transp->logMsg.entry.len &&
(!oldest ||
(oldest->logMsg.entry.sec >
transp->logMsg.entry.sec) ||
((oldest->logMsg.entry.sec ==
transp->logMsg.entry.sec) &&
(oldest->logMsg.entry.nsec >
transp->logMsg.entry.nsec)))) {
oldest = transp;
}
transp = node_to_item(transp->node.next,
struct android_log_transport_context, struct android_log_transport_context,
node); node));
} while (transp != node_to_item( if (!oldest && (logger_list_internal->mode & ANDROID_LOG_NONBLOCK)) {
&logger_list_internal->transport, return (ret < 0) ? ret : -EAGAIN;
struct android_log_transport_context, }
node)); transp = node_to_item(logger_list_internal->transport.next,
if (!oldest && struct android_log_transport_context, node);
(logger_list_internal->mode & ANDROID_LOG_NONBLOCK)) { } while (!oldest && (ret > 0));
return (ret < 0) ? ret : -EAGAIN; if (!oldest) {
} return ret;
transp = node_to_item(logger_list_internal->transport.next,
struct android_log_transport_context, node);
} while (!oldest && (ret > 0));
if (!oldest) {
return ret;
}
// ret is a positive value less than sizeof(struct log_msg)
ret = oldest->ret;
if (ret < oldest->logMsg.entry.hdr_size) {
// zero truncated header fields.
memset(log_msg, 0,
(oldest->logMsg.entry.hdr_size > sizeof(oldest->logMsg) ?
sizeof(oldest->logMsg) :
oldest->logMsg.entry.hdr_size));
}
memcpy(log_msg, &oldest->logMsg, ret);
oldest->logMsg.entry.len = 0; /* Mark it as copied */
return ret;
} }
// ret is a positive value less than sizeof(struct log_msg)
ret = oldest->ret;
if (ret < oldest->logMsg.entry.hdr_size) {
// zero truncated header fields.
memset(log_msg, 0,
(oldest->logMsg.entry.hdr_size > sizeof(oldest->logMsg)
? sizeof(oldest->logMsg)
: oldest->logMsg.entry.hdr_size));
}
memcpy(log_msg, &oldest->logMsg, ret);
oldest->logMsg.entry.len = 0; /* Mark it as copied */
return ret;
}
/* if only one, no need to copy into transport_context and merge-sort */ /* if only one, no need to copy into transport_context and merge-sort */
return android_transport_read(logger_list_internal, transp, log_msg); return android_transport_read(logger_list_internal, transp, log_msg);
} }
/* Close all the logs */ /* Close all the logs */
LIBLOG_ABI_PUBLIC void android_logger_list_free(struct logger_list *logger_list) LIBLOG_ABI_PUBLIC void android_logger_list_free(struct logger_list* logger_list) {
{ struct android_log_logger_list* logger_list_internal =
struct android_log_logger_list *logger_list_internal = (struct android_log_logger_list*)logger_list;
(struct android_log_logger_list *)logger_list;
if (logger_list_internal == NULL) { if (logger_list_internal == NULL) {
return; return;
}
logger_list_wrlock();
list_remove(&logger_list_internal->node);
logger_list_unlock();
while (!list_empty(&logger_list_internal->transport)) {
struct listnode* node = list_head(&logger_list_internal->transport);
struct android_log_transport_context* transp =
node_to_item(node, struct android_log_transport_context, node);
if (transp->transport && transp->transport->close) {
(*transp->transport->close)(logger_list_internal, transp);
} }
list_remove(&transp->node);
free(transp);
}
logger_list_wrlock(); while (!list_empty(&logger_list_internal->logger)) {
list_remove(&logger_list_internal->node); struct listnode* node = list_head(&logger_list_internal->logger);
logger_list_unlock(); struct android_log_logger* logger =
node_to_item(node, struct android_log_logger, node);
android_logger_free((struct logger*)logger);
}
while (!list_empty(&logger_list_internal->transport)) { free(logger_list_internal);
struct listnode *node = list_head(&logger_list_internal->transport);
struct android_log_transport_context *transp =
node_to_item(node, struct android_log_transport_context, node);
if (transp->transport && transp->transport->close) {
(*transp->transport->close)(logger_list_internal, transp);
}
list_remove(&transp->node);
free(transp);
}
while (!list_empty(&logger_list_internal->logger)) {
struct listnode *node = list_head(&logger_list_internal->logger);
struct android_log_logger *logger =
node_to_item(node, struct android_log_logger, node);
android_logger_free((struct logger *)logger);
}
free(logger_list_internal);
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -36,155 +36,149 @@
static int pmsgOpen(); static int pmsgOpen();
static void pmsgClose(); static void pmsgClose();
static int pmsgAvailable(log_id_t logId); static int pmsgAvailable(log_id_t logId);
static int pmsgWrite(log_id_t logId, struct timespec *ts, static int pmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec,
struct iovec *vec, size_t nr); size_t nr);
LIBLOG_HIDDEN struct android_log_transport_write pmsgLoggerWrite = { LIBLOG_HIDDEN struct android_log_transport_write pmsgLoggerWrite = {
.node = { &pmsgLoggerWrite.node, &pmsgLoggerWrite.node }, .node = { &pmsgLoggerWrite.node, &pmsgLoggerWrite.node },
.context.fd = -1, .context.fd = -1,
.name = "pmsg", .name = "pmsg",
.available = pmsgAvailable, .available = pmsgAvailable,
.open = pmsgOpen, .open = pmsgOpen,
.close = pmsgClose, .close = pmsgClose,
.write = pmsgWrite, .write = pmsgWrite,
}; };
static int pmsgOpen() static int pmsgOpen() {
{ int fd = atomic_load(&pmsgLoggerWrite.context.fd);
int fd = atomic_load(&pmsgLoggerWrite.context.fd); if (fd < 0) {
if (fd < 0) { int i;
int i;
fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC)); fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
i = atomic_exchange(&pmsgLoggerWrite.context.fd, fd); i = atomic_exchange(&pmsgLoggerWrite.context.fd, fd);
if ((i >= 0) && (i != fd)) { if ((i >= 0) && (i != fd)) {
close(i); close(i);
}
} }
}
return fd; return fd;
} }
static void pmsgClose() static void pmsgClose() {
{ int fd = atomic_exchange(&pmsgLoggerWrite.context.fd, -1);
int fd = atomic_exchange(&pmsgLoggerWrite.context.fd, -1); if (fd >= 0) {
if (fd >= 0) { close(fd);
close(fd); }
}
} }
static int pmsgAvailable(log_id_t logId) static int pmsgAvailable(log_id_t logId) {
{ if (logId > LOG_ID_SECURITY) {
if (logId > LOG_ID_SECURITY) { return -EINVAL;
return -EINVAL; }
if ((logId != LOG_ID_SECURITY) && (logId != LOG_ID_EVENTS) &&
!__android_log_is_debuggable()) {
return -EINVAL;
}
if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
if (access("/dev/pmsg0", W_OK) == 0) {
return 0;
} }
if ((logId != LOG_ID_SECURITY) && return -EBADF;
(logId != LOG_ID_EVENTS) && }
!__android_log_is_debuggable()) { return 1;
return -EINVAL;
}
if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
if (access("/dev/pmsg0", W_OK) == 0) {
return 0;
}
return -EBADF;
}
return 1;
} }
/* /*
* Extract a 4-byte value from a byte stream. * Extract a 4-byte value from a byte stream.
*/ */
static inline uint32_t get4LE(const uint8_t* src) static inline uint32_t get4LE(const uint8_t* src) {
{ return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
} }
static int pmsgWrite(log_id_t logId, struct timespec *ts, static int pmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec,
struct iovec *vec, size_t nr) size_t nr) {
{ static const unsigned headerLength = 2;
static const unsigned headerLength = 2; struct iovec newVec[nr + headerLength];
struct iovec newVec[nr + headerLength]; android_log_header_t header;
android_log_header_t header; android_pmsg_log_header_t pmsgHeader;
android_pmsg_log_header_t pmsgHeader; size_t i, payloadSize;
size_t i, payloadSize; ssize_t ret;
ssize_t ret;
if ((logId == LOG_ID_EVENTS) && !__android_log_is_debuggable()) { if ((logId == LOG_ID_EVENTS) && !__android_log_is_debuggable()) {
if (vec[0].iov_len < 4) { if (vec[0].iov_len < 4) {
return -EINVAL; return -EINVAL;
}
if (SNET_EVENT_LOG_TAG != get4LE(vec[0].iov_base)) {
return -EPERM;
}
} }
if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) { if (SNET_EVENT_LOG_TAG != get4LE(vec[0].iov_base)) {
return -EBADF; return -EPERM;
} }
}
/* if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
* struct { return -EBADF;
* // what we provide to pstore }
* android_pmsg_log_header_t pmsgHeader;
* // what we provide to file
* android_log_header_t header;
* // caller provides
* union {
* struct {
* char prio;
* char payload[];
* } string;
* struct {
* uint32_t tag
* char payload[];
* } binary;
* };
* };
*/
pmsgHeader.magic = LOGGER_MAGIC; /*
pmsgHeader.len = sizeof(pmsgHeader) + sizeof(header); * struct {
pmsgHeader.uid = __android_log_uid(); * // what we provide to pstore
pmsgHeader.pid = getpid(); * android_pmsg_log_header_t pmsgHeader;
* // what we provide to file
* android_log_header_t header;
* // caller provides
* union {
* struct {
* char prio;
* char payload[];
* } string;
* struct {
* uint32_t tag
* char payload[];
* } binary;
* };
* };
*/
header.id = logId; pmsgHeader.magic = LOGGER_MAGIC;
header.tid = gettid(); pmsgHeader.len = sizeof(pmsgHeader) + sizeof(header);
header.realtime.tv_sec = ts->tv_sec; pmsgHeader.uid = __android_log_uid();
header.realtime.tv_nsec = ts->tv_nsec; pmsgHeader.pid = getpid();
newVec[0].iov_base = (unsigned char *)&pmsgHeader; header.id = logId;
newVec[0].iov_len = sizeof(pmsgHeader); header.tid = gettid();
newVec[1].iov_base = (unsigned char *)&header; header.realtime.tv_sec = ts->tv_sec;
newVec[1].iov_len = sizeof(header); header.realtime.tv_nsec = ts->tv_nsec;
for (payloadSize = 0, i = headerLength; i < nr + headerLength; i++) { newVec[0].iov_base = (unsigned char*)&pmsgHeader;
newVec[i].iov_base = vec[i - headerLength].iov_base; newVec[0].iov_len = sizeof(pmsgHeader);
payloadSize += newVec[i].iov_len = vec[i - headerLength].iov_len; newVec[1].iov_base = (unsigned char*)&header;
newVec[1].iov_len = sizeof(header);
if (payloadSize > LOGGER_ENTRY_MAX_PAYLOAD) { for (payloadSize = 0, i = headerLength; i < nr + headerLength; i++) {
newVec[i].iov_len -= payloadSize - LOGGER_ENTRY_MAX_PAYLOAD; newVec[i].iov_base = vec[i - headerLength].iov_base;
if (newVec[i].iov_len) { payloadSize += newVec[i].iov_len = vec[i - headerLength].iov_len;
++i;
} if (payloadSize > LOGGER_ENTRY_MAX_PAYLOAD) {
payloadSize = LOGGER_ENTRY_MAX_PAYLOAD; newVec[i].iov_len -= payloadSize - LOGGER_ENTRY_MAX_PAYLOAD;
break; if (newVec[i].iov_len) {
} ++i;
}
payloadSize = LOGGER_ENTRY_MAX_PAYLOAD;
break;
} }
pmsgHeader.len += payloadSize; }
pmsgHeader.len += payloadSize;
ret = TEMP_FAILURE_RETRY(writev(atomic_load(&pmsgLoggerWrite.context.fd), ret = TEMP_FAILURE_RETRY(
newVec, i)); writev(atomic_load(&pmsgLoggerWrite.context.fd), newVec, i));
if (ret < 0) { if (ret < 0) {
ret = errno ? -errno : -ENOTCONN; ret = errno ? -errno : -ENOTCONN;
} }
if (ret > (ssize_t)(sizeof(header) + sizeof(pmsgHeader))) { if (ret > (ssize_t)(sizeof(header) + sizeof(pmsgHeader))) {
ret -= sizeof(header) - sizeof(pmsgHeader); ret -= sizeof(header) - sizeof(pmsgHeader);
} }
return ret; return ret;
} }
/* /*
@ -197,116 +191,116 @@ static int pmsgWrite(log_id_t logId, struct timespec *ts,
* Will hijack the header.realtime.tv_nsec field for a sequence number in usec. * Will hijack the header.realtime.tv_nsec field for a sequence number in usec.
*/ */
static inline const char *strnrchr(const char *buf, size_t len, char c) { static inline const char* strnrchr(const char* buf, size_t len, char c) {
const char *cp = buf + len; const char* cp = buf + len;
while ((--cp > buf) && (*cp != c)); while ((--cp > buf) && (*cp != c))
if (cp <= buf) { ;
return buf + len; if (cp <= buf) {
} return buf + len;
return cp; }
return cp;
} }
/* Write a buffer as filename references (tag = <basedir>:<basename>) */ /* Write a buffer as filename references (tag = <basedir>:<basename>) */
LIBLOG_ABI_PRIVATE ssize_t __android_log_pmsg_file_write( LIBLOG_ABI_PRIVATE ssize_t __android_log_pmsg_file_write(log_id_t logId,
log_id_t logId, char prio,
char prio, const char* filename,
const char *filename, const char* buf,
const char *buf, size_t len) { size_t len) {
bool weOpened; bool weOpened;
size_t length, packet_len; size_t length, packet_len;
const char *tag; const char* tag;
char *cp, *slash; char *cp, *slash;
struct timespec ts; struct timespec ts;
struct iovec vec[3]; struct iovec vec[3];
/* Make sure the logId value is not a bad idea */ /* Make sure the logId value is not a bad idea */
if ((logId == LOG_ID_KERNEL) || /* Verbotten */ if ((logId == LOG_ID_KERNEL) || /* Verbotten */
(logId == LOG_ID_EVENTS) || /* Do not support binary content */ (logId == LOG_ID_EVENTS) || /* Do not support binary content */
(logId == LOG_ID_SECURITY) || /* Bad idea to allow */ (logId == LOG_ID_SECURITY) || /* Bad idea to allow */
((unsigned)logId >= 32)) { /* fit within logMask on arch32 */ ((unsigned)logId >= 32)) { /* fit within logMask on arch32 */
return -EINVAL; return -EINVAL;
} }
clock_gettime(android_log_clockid(), &ts); clock_gettime(android_log_clockid(), &ts);
cp = strdup(filename); cp = strdup(filename);
if (!cp) { if (!cp) {
return -ENOMEM; return -ENOMEM;
} }
tag = cp; tag = cp;
slash = strrchr(cp, '/');
if (slash) {
*slash = ':';
slash = strrchr(cp, '/'); slash = strrchr(cp, '/');
if (slash) { if (slash) {
*slash = ':'; tag = slash + 1;
slash = strrchr(cp, '/'); }
if (slash) { }
tag = slash + 1;
} length = strlen(tag) + 1;
packet_len = LOGGER_ENTRY_MAX_PAYLOAD - sizeof(char) - length;
vec[0].iov_base = &prio;
vec[0].iov_len = sizeof(char);
vec[1].iov_base = (unsigned char*)tag;
vec[1].iov_len = length;
weOpened = false;
for (ts.tv_nsec = 0, length = len; length;
ts.tv_nsec += ANDROID_LOG_PMSG_FILE_SEQUENCE) {
ssize_t ret;
size_t transfer;
if ((ts.tv_nsec / ANDROID_LOG_PMSG_FILE_SEQUENCE) >=
ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE) {
len -= length;
break;
} }
length = strlen(tag) + 1; transfer = length;
packet_len = LOGGER_ENTRY_MAX_PAYLOAD - sizeof(char) - length; if (transfer > packet_len) {
transfer = strnrchr(buf, packet_len - 1, '\n') - buf;
vec[0].iov_base = &prio; if ((transfer < length) && (buf[transfer] == '\n')) {
vec[0].iov_len = sizeof(char); ++transfer;
vec[1].iov_base = (unsigned char *)tag; }
vec[1].iov_len = length;
weOpened = false;
for (ts.tv_nsec = 0, length = len;
length;
ts.tv_nsec += ANDROID_LOG_PMSG_FILE_SEQUENCE) {
ssize_t ret;
size_t transfer;
if ((ts.tv_nsec / ANDROID_LOG_PMSG_FILE_SEQUENCE) >=
ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE) {
len -= length;
break;
}
transfer = length;
if (transfer > packet_len) {
transfer = strnrchr(buf, packet_len - 1, '\n') - buf;
if ((transfer < length) && (buf[transfer] == '\n')) {
++transfer;
}
}
vec[2].iov_base = (unsigned char *)buf;
vec[2].iov_len = transfer;
if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
if (!weOpened) { /* Impossible for weOpened = true here */
__android_log_lock();
}
weOpened = atomic_load(&pmsgLoggerWrite.context.fd) < 0;
if (!weOpened) {
__android_log_unlock();
} else if (pmsgOpen() < 0) {
__android_log_unlock();
free(cp);
return -EBADF;
}
}
ret = pmsgWrite(logId, &ts, vec, sizeof(vec) / sizeof(vec[0]));
if (ret <= 0) {
if (weOpened) {
pmsgClose();
__android_log_unlock();
}
free(cp);
return ret ? ret : (len - length);
}
length -= transfer;
buf += transfer;
} }
if (weOpened) {
vec[2].iov_base = (unsigned char*)buf;
vec[2].iov_len = transfer;
if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
if (!weOpened) { /* Impossible for weOpened = true here */
__android_log_lock();
}
weOpened = atomic_load(&pmsgLoggerWrite.context.fd) < 0;
if (!weOpened) {
__android_log_unlock();
} else if (pmsgOpen() < 0) {
__android_log_unlock();
free(cp);
return -EBADF;
}
}
ret = pmsgWrite(logId, &ts, vec, sizeof(vec) / sizeof(vec[0]));
if (ret <= 0) {
if (weOpened) {
pmsgClose(); pmsgClose();
__android_log_unlock(); __android_log_unlock();
}
free(cp);
return ret ? ret : (len - length);
} }
free(cp); length -= transfer;
return len; buf += transfer;
}
if (weOpened) {
pmsgClose();
__android_log_unlock();
}
free(cp);
return len;
} }

File diff suppressed because it is too large Load diff

View file

@ -45,175 +45,168 @@
static int stderrOpen(); static int stderrOpen();
static void stderrClose(); static void stderrClose();
static int stderrAvailable(log_id_t logId); static int stderrAvailable(log_id_t logId);
static int stderrWrite(log_id_t logId, struct timespec* ts, static int stderrWrite(log_id_t logId, struct timespec* ts, struct iovec* vec,
struct iovec* vec, size_t nr); size_t nr);
struct stderrContext { struct stderrContext {
AndroidLogFormat* logformat; AndroidLogFormat* logformat;
#if defined(__ANDROID__) #if defined(__ANDROID__)
EventTagMap* eventTagMap; EventTagMap* eventTagMap;
#endif #endif
}; };
LIBLOG_HIDDEN struct android_log_transport_write stderrLoggerWrite = { LIBLOG_HIDDEN struct android_log_transport_write stderrLoggerWrite = {
.node = { &stderrLoggerWrite.node, &stderrLoggerWrite.node }, .node = { &stderrLoggerWrite.node, &stderrLoggerWrite.node },
.context.private = NULL, .context.priv = NULL,
.name = "stderr", .name = "stderr",
.available = stderrAvailable, .available = stderrAvailable,
.open = stderrOpen, .open = stderrOpen,
.close = stderrClose, .close = stderrClose,
.write = stderrWrite, .write = stderrWrite,
}; };
static int stderrOpen() static int stderrOpen() {
{ struct stderrContext* ctx;
struct stderrContext* ctx; const char* envStr;
const char* envStr; bool setFormat;
bool setFormat;
if (!stderr || (fileno(stderr) < 0)) { if (!stderr || (fileno(stderr) < 0)) {
return -EBADF; return -EBADF;
} }
if (stderrLoggerWrite.context.private) {
return fileno(stderr);
}
ctx = calloc(1, sizeof(struct stderrContext));
if (!ctx) {
return -ENOMEM;
}
ctx->logformat = android_log_format_new();
if (!ctx->logformat) {
free(ctx);
return -ENOMEM;
}
envStr = getenv("ANDROID_PRINTF_LOG");
setFormat = false;
if (envStr) {
char* formats = strdup(envStr);
char* sv = NULL;
char* arg = formats;
while (!!(arg = strtok_r(arg, ",:; \t\n\r\f", &sv))) {
AndroidLogPrintFormat format = android_log_formatFromString(arg);
arg = NULL;
if (format == FORMAT_OFF) {
continue;
}
if (android_log_setPrintFormat(ctx->logformat, format) <= 0) {
continue;
}
setFormat = true;
}
free(formats);
}
if (!setFormat) {
AndroidLogPrintFormat format = android_log_formatFromString(
"threadtime");
android_log_setPrintFormat(ctx->logformat, format);
}
envStr = getenv("ANDROID_LOG_TAGS");
if (envStr) {
android_log_addFilterString(ctx->logformat, envStr);
}
stderrLoggerWrite.context.private = ctx;
if (stderrLoggerWrite.context.priv) {
return fileno(stderr); return fileno(stderr);
}
ctx = calloc(1, sizeof(struct stderrContext));
if (!ctx) {
return -ENOMEM;
}
ctx->logformat = android_log_format_new();
if (!ctx->logformat) {
free(ctx);
return -ENOMEM;
}
envStr = getenv("ANDROID_PRINTF_LOG");
setFormat = false;
if (envStr) {
char* formats = strdup(envStr);
char* sv = NULL;
char* arg = formats;
while (!!(arg = strtok_r(arg, ",:; \t\n\r\f", &sv))) {
AndroidLogPrintFormat format = android_log_formatFromString(arg);
arg = NULL;
if (format == FORMAT_OFF) {
continue;
}
if (android_log_setPrintFormat(ctx->logformat, format) <= 0) {
continue;
}
setFormat = true;
}
free(formats);
}
if (!setFormat) {
AndroidLogPrintFormat format = android_log_formatFromString("threadtime");
android_log_setPrintFormat(ctx->logformat, format);
}
envStr = getenv("ANDROID_LOG_TAGS");
if (envStr) {
android_log_addFilterString(ctx->logformat, envStr);
}
stderrLoggerWrite.context.priv = ctx;
return fileno(stderr);
} }
static void stderrClose() static void stderrClose() {
{ struct stderrContext* ctx = stderrLoggerWrite.context.priv;
struct stderrContext* ctx = stderrLoggerWrite.context.private;
if (ctx) { if (ctx) {
stderrLoggerWrite.context.private = NULL; stderrLoggerWrite.context.priv = NULL;
if (ctx->logformat) { if (ctx->logformat) {
android_log_format_free(ctx->logformat); android_log_format_free(ctx->logformat);
ctx->logformat = NULL; ctx->logformat = NULL;
} }
#if defined(__ANDROID__) #if defined(__ANDROID__)
if (ctx->eventTagMap) { if (ctx->eventTagMap) {
android_closeEventTagMap(ctx->eventTagMap); android_closeEventTagMap(ctx->eventTagMap);
ctx->eventTagMap = NULL; ctx->eventTagMap = NULL;
} }
#endif #endif
} }
} }
static int stderrAvailable(log_id_t logId) static int stderrAvailable(log_id_t logId) {
{ if ((logId >= LOG_ID_MAX) || (logId == LOG_ID_KERNEL)) {
if ((logId >= LOG_ID_MAX) || (logId == LOG_ID_KERNEL)) { return -EINVAL;
return -EINVAL; }
} return 1;
return 1;
} }
static int stderrWrite(log_id_t logId, struct timespec* ts, static int stderrWrite(log_id_t logId, struct timespec* ts, struct iovec* vec,
struct iovec* vec, size_t nr) size_t nr) {
{ struct log_msg log_msg;
struct log_msg log_msg; AndroidLogEntry entry;
AndroidLogEntry entry; char binaryMsgBuf[1024];
char binaryMsgBuf[1024]; int err;
int err; size_t i;
size_t i; struct stderrContext* ctx = stderrLoggerWrite.context.priv;
struct stderrContext* ctx = stderrLoggerWrite.context.private;
if (!ctx) return -EBADF; if (!ctx) return -EBADF;
if (!vec || !nr) return -EINVAL; if (!vec || !nr) return -EINVAL;
log_msg.entry.len = 0; log_msg.entry.len = 0;
log_msg.entry.hdr_size = sizeof(log_msg.entry); log_msg.entry.hdr_size = sizeof(log_msg.entry);
log_msg.entry.pid = getpid(); log_msg.entry.pid = getpid();
#ifdef __BIONIC__ #ifdef __BIONIC__
log_msg.entry.tid = gettid(); log_msg.entry.tid = gettid();
#else #else
log_msg.entry.tid = getpid(); log_msg.entry.tid = getpid();
#endif #endif
log_msg.entry.sec = ts->tv_sec; log_msg.entry.sec = ts->tv_sec;
log_msg.entry.nsec = ts->tv_nsec; log_msg.entry.nsec = ts->tv_nsec;
log_msg.entry.lid = logId; log_msg.entry.lid = logId;
log_msg.entry.uid = __android_log_uid(); log_msg.entry.uid = __android_log_uid();
for (i = 0; i < nr; ++i) { for (i = 0; i < nr; ++i) {
size_t len = vec[i].iov_len; size_t len = vec[i].iov_len;
if ((log_msg.entry.len + len) > LOGGER_ENTRY_MAX_PAYLOAD) { if ((log_msg.entry.len + len) > LOGGER_ENTRY_MAX_PAYLOAD) {
len = LOGGER_ENTRY_MAX_PAYLOAD - log_msg.entry.len; len = LOGGER_ENTRY_MAX_PAYLOAD - log_msg.entry.len;
}
if (!len) continue;
memcpy(log_msg.entry.msg + log_msg.entry.len, vec[i].iov_base, len);
log_msg.entry.len += len;
} }
if (!len) continue;
memcpy(log_msg.entry.msg + log_msg.entry.len, vec[i].iov_base, len);
log_msg.entry.len += len;
}
if ((logId == LOG_ID_EVENTS) || (logId == LOG_ID_SECURITY)) { if ((logId == LOG_ID_EVENTS) || (logId == LOG_ID_SECURITY)) {
#if defined(__ANDROID__) #if defined(__ANDROID__)
if (!ctx->eventTagMap) { if (!ctx->eventTagMap) {
ctx->eventTagMap = android_openEventTagMap(NULL); ctx->eventTagMap = android_openEventTagMap(NULL);
} }
#endif #endif
err = android_log_processBinaryLogBuffer(&log_msg.entry_v1, err = android_log_processBinaryLogBuffer(&log_msg.entry_v1, &entry,
&entry,
#if defined(__ANDROID__) #if defined(__ANDROID__)
ctx->eventTagMap, ctx->eventTagMap,
#else #else
NULL, NULL,
#endif #endif
binaryMsgBuf, binaryMsgBuf, sizeof(binaryMsgBuf));
sizeof(binaryMsgBuf)); } else {
} else { err = android_log_processLogBuffer(&log_msg.entry_v1, &entry);
err = android_log_processLogBuffer(&log_msg.entry_v1, &entry); }
}
/* print known truncated data, in essence logcat --debug */ /* print known truncated data, in essence logcat --debug */
if ((err < 0) && !entry.message) return -EINVAL; if ((err < 0) && !entry.message) return -EINVAL;
if (!android_log_shouldPrintLine(ctx->logformat, entry.tag, entry.priority)) { if (!android_log_shouldPrintLine(ctx->logformat, entry.tag, entry.priority)) {
return log_msg.entry.len;
}
err = android_log_printLogLine(ctx->logformat, fileno(stderr), &entry);
if (err < 0) return errno ? -errno : -EINVAL;
return log_msg.entry.len; return log_msg.entry.len;
}
err = android_log_printLogLine(ctx->logformat, fileno(stderr), &entry);
if (err < 0) return errno ? -errno : -EINVAL;
return log_msg.entry.len;
} }

View file

@ -22,8 +22,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string>
#include <map> #include <map>
#include <string>
#include <vector> #include <vector>
static uint64_t gBytesProcessed; static uint64_t gBytesProcessed;
@ -32,21 +32,21 @@ static uint64_t gBenchmarkTotalTimeNsSquared;
static uint64_t gBenchmarkNum; static uint64_t gBenchmarkNum;
static uint64_t gBenchmarkStartTimeNs; static uint64_t gBenchmarkStartTimeNs;
typedef std::vector< ::testing::Benchmark* > BenchmarkList; typedef std::vector< ::testing::Benchmark*> BenchmarkList;
static BenchmarkList* gBenchmarks; static BenchmarkList* gBenchmarks;
static int Round(int n) { static int Round(int n) {
int base = 1; int base = 1;
while (base*10 < n) { while (base * 10 < n) {
base *= 10; base *= 10;
} }
if (n < 2*base) { if (n < 2 * base) {
return 2*base; return 2 * base;
} }
if (n < 5*base) { if (n < 5 * base) {
return 5*base; return 5 * base;
} }
return 10*base; return 10 * base;
} }
static uint64_t NanoTime() { static uint64_t NanoTime() {
@ -58,20 +58,19 @@ static uint64_t NanoTime() {
namespace testing { namespace testing {
int PrettyPrintInt(char* str, int len, unsigned int arg) int PrettyPrintInt(char* str, int len, unsigned int arg) {
{ if (arg >= (1 << 30) && arg % (1 << 30) == 0) {
if (arg >= (1<<30) && arg % (1<<30) == 0) { return snprintf(str, len, "%uGi", arg / (1 << 30));
return snprintf(str, len, "%uGi", arg/(1<<30)); } else if (arg >= (1 << 20) && arg % (1 << 20) == 0) {
} else if (arg >= (1<<20) && arg % (1<<20) == 0) { return snprintf(str, len, "%uMi", arg / (1 << 20));
return snprintf(str, len, "%uMi", arg/(1<<20)); } else if (arg >= (1 << 10) && arg % (1 << 10) == 0) {
} else if (arg >= (1<<10) && arg % (1<<10) == 0) { return snprintf(str, len, "%uKi", arg / (1 << 10));
return snprintf(str, len, "%uKi", arg/(1<<10));
} else if (arg >= 1000000000 && arg % 1000000000 == 0) { } else if (arg >= 1000000000 && arg % 1000000000 == 0) {
return snprintf(str, len, "%uG", arg/1000000000); return snprintf(str, len, "%uG", arg / 1000000000);
} else if (arg >= 1000000 && arg % 1000000 == 0) { } else if (arg >= 1000000 && arg % 1000000 == 0) {
return snprintf(str, len, "%uM", arg/1000000); return snprintf(str, len, "%uM", arg / 1000000);
} else if (arg >= 1000 && arg % 1000 == 0) { } else if (arg >= 1000 && arg % 1000 == 0) {
return snprintf(str, len, "%uK", arg/1000); return snprintf(str, len, "%uK", arg / 1000);
} else { } else {
return snprintf(str, len, "%u", arg); return snprintf(str, len, "%u", arg);
} }
@ -86,7 +85,8 @@ bool ShouldRun(Benchmark* b, int argc, char* argv[]) {
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
regex_t re; regex_t re;
if (regcomp(&re, argv[i], 0) != 0) { if (regcomp(&re, argv[i], 0) != 0) {
fprintf(stderr, "couldn't compile \"%s\" as a regular expression!\n", argv[i]); fprintf(stderr, "couldn't compile \"%s\" as a regular expression!\n",
argv[i]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
int match = regexec(&re, b->Name(), 0, NULL, 0); int match = regexec(&re, b->Name(), 0, NULL, 0);
@ -111,9 +111,8 @@ void RunRepeatedly(Benchmark* b, int iterations) {
uint64_t StartTimeNs = NanoTime(); uint64_t StartTimeNs = NanoTime();
b->RunFn(iterations); b->RunFn(iterations);
// Catch us if we fail to log anything. // Catch us if we fail to log anything.
if ((gBenchmarkTotalTimeNs == 0) if ((gBenchmarkTotalTimeNs == 0) && (StartTimeNs != 0) &&
&& (StartTimeNs != 0) (gBenchmarkStartTimeNs == 0)) {
&& (gBenchmarkStartTimeNs == 0)) {
gBenchmarkTotalTimeNs = NanoTime() - StartTimeNs; gBenchmarkTotalTimeNs = NanoTime() - StartTimeNs;
} }
} }
@ -126,12 +125,13 @@ void Run(Benchmark* b) {
s = NanoTime() - s; s = NanoTime() - s;
while (s < 2e9 && gBenchmarkTotalTimeNs < 1e9 && iterations < 1e9) { while (s < 2e9 && gBenchmarkTotalTimeNs < 1e9 && iterations < 1e9) {
unsigned last = iterations; unsigned last = iterations;
if (gBenchmarkTotalTimeNs/iterations == 0) { if (gBenchmarkTotalTimeNs / iterations == 0) {
iterations = 1e9; iterations = 1e9;
} else { } else {
iterations = 1e9 / (gBenchmarkTotalTimeNs/iterations); iterations = 1e9 / (gBenchmarkTotalTimeNs / iterations);
} }
iterations = std::max(last + 1, std::min(iterations + iterations/2, 100*last)); iterations =
std::max(last + 1, std::min(iterations + iterations / 2, 100 * last));
iterations = Round(iterations); iterations = Round(iterations);
s = NanoTime(); s = NanoTime();
RunRepeatedly(b, iterations); RunRepeatedly(b, iterations);
@ -141,30 +141,30 @@ void Run(Benchmark* b) {
char throughput[100]; char throughput[100];
throughput[0] = '\0'; throughput[0] = '\0';
if (gBenchmarkTotalTimeNs > 0 && gBytesProcessed > 0) { if (gBenchmarkTotalTimeNs > 0 && gBytesProcessed > 0) {
double mib_processed = static_cast<double>(gBytesProcessed)/1e6; double mib_processed = static_cast<double>(gBytesProcessed) / 1e6;
double seconds = static_cast<double>(gBenchmarkTotalTimeNs)/1e9; double seconds = static_cast<double>(gBenchmarkTotalTimeNs) / 1e9;
snprintf(throughput, sizeof(throughput), " %8.2f MiB/s", mib_processed/seconds); snprintf(throughput, sizeof(throughput), " %8.2f MiB/s",
mib_processed / seconds);
} }
char full_name[100]; char full_name[100];
snprintf(full_name, sizeof(full_name), "%s%s%s", b->Name(), snprintf(full_name, sizeof(full_name), "%s%s%s", b->Name(),
b->ArgName() ? "/" : "", b->ArgName() ? "/" : "", b->ArgName() ? b->ArgName() : "");
b->ArgName() ? b->ArgName() : "");
uint64_t mean = gBenchmarkTotalTimeNs / iterations; uint64_t mean = gBenchmarkTotalTimeNs / iterations;
uint64_t sdev = 0; uint64_t sdev = 0;
if (gBenchmarkNum == iterations) { if (gBenchmarkNum == iterations) {
mean = gBenchmarkTotalTimeNs / gBenchmarkNum; mean = gBenchmarkTotalTimeNs / gBenchmarkNum;
uint64_t nXvariance = gBenchmarkTotalTimeNsSquared * gBenchmarkNum uint64_t nXvariance = gBenchmarkTotalTimeNsSquared * gBenchmarkNum -
- (gBenchmarkTotalTimeNs * gBenchmarkTotalTimeNs); (gBenchmarkTotalTimeNs * gBenchmarkTotalTimeNs);
sdev = (sqrt((double)nXvariance) / gBenchmarkNum / gBenchmarkNum) + 0.5; sdev = (sqrt((double)nXvariance) / gBenchmarkNum / gBenchmarkNum) + 0.5;
} }
if (mean > (10000 * sdev)) { if (mean > (10000 * sdev)) {
printf("%-25s %10" PRIu64 " %10" PRIu64 "%s\n", full_name, printf("%-25s %10" PRIu64 " %10" PRIu64 "%s\n", full_name,
static_cast<uint64_t>(iterations), mean, throughput); static_cast<uint64_t>(iterations), mean, throughput);
} else { } else {
printf("%-25s %10" PRIu64 " %10" PRIu64 "(\317\203%" PRIu64 ")%s\n", full_name, printf("%-25s %10" PRIu64 " %10" PRIu64 "(\317\203%" PRIu64 ")%s\n",
static_cast<uint64_t>(iterations), mean, sdev, throughput); full_name, static_cast<uint64_t>(iterations), mean, sdev, throughput);
} }
fflush(stdout); fflush(stdout);
} }

View file

@ -21,29 +21,29 @@
TEST(libc, __pstore_append) { TEST(libc, __pstore_append) {
#ifdef __ANDROID__ #ifdef __ANDROID__
FILE *fp; FILE* fp;
ASSERT_TRUE(NULL != (fp = fopen("/dev/pmsg0", "a"))); ASSERT_TRUE(NULL != (fp = fopen("/dev/pmsg0", "a")));
static const char message[] = "libc.__pstore_append\n"; static const char message[] = "libc.__pstore_append\n";
ASSERT_EQ((size_t)1, fwrite(message, sizeof(message), 1, fp)); ASSERT_EQ((size_t)1, fwrite(message, sizeof(message), 1, fp));
int fflushReturn = fflush(fp); int fflushReturn = fflush(fp);
int fflushErrno = fflushReturn ? errno : 0; int fflushErrno = fflushReturn ? errno : 0;
ASSERT_EQ(0, fflushReturn); ASSERT_EQ(0, fflushReturn);
ASSERT_EQ(0, fflushErrno); ASSERT_EQ(0, fflushErrno);
int fcloseReturn = fclose(fp); int fcloseReturn = fclose(fp);
int fcloseErrno = fcloseReturn ? errno : 0; int fcloseErrno = fcloseReturn ? errno : 0;
ASSERT_EQ(0, fcloseReturn); ASSERT_EQ(0, fcloseReturn);
ASSERT_EQ(0, fcloseErrno); ASSERT_EQ(0, fcloseErrno);
if ((fcloseErrno == ENOMEM) || (fflushErrno == ENOMEM)) { if ((fcloseErrno == ENOMEM) || (fflushErrno == ENOMEM)) {
fprintf(stderr, fprintf(stderr,
"Kernel does not have space allocated to pmsg pstore driver configured\n" "Kernel does not have space allocated to pmsg pstore driver "
); "configured\n");
} }
if (!fcloseReturn && !fcloseErrno && !fflushReturn && !fflushReturn) { if (!fcloseReturn && !fcloseErrno && !fflushReturn && !fflushReturn) {
fprintf(stderr, fprintf(stderr,
"Reboot, ensure string libc.__pstore_append is in /sys/fs/pstore/pmsg-ramoops-0\n" "Reboot, ensure string libc.__pstore_append is in "
); "/sys/fs/pstore/pmsg-ramoops-0\n");
} }
#else #else
GTEST_LOG_(INFO) << "This test does nothing.\n"; GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif #endif
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
#ifdef __ANDROID__ #ifdef __ANDROID__
#include <log/log_frontend.h> #include <log/log_transport.h>
#define TEST_PREFIX android_set_log_frontend(LOGGER_DEFAULT); #define TEST_PREFIX android_set_log_transport(LOGGER_DEFAULT);
#endif #endif
#include "liblog_test.cpp" #include "liblog_test.cpp"

View file

@ -1,4 +1,4 @@
#include <log/log_frontend.h> #include <log/log_transport.h>
#define liblog liblog_local #define liblog liblog_local
#define TEST_PREFIX android_set_log_frontend(LOGGER_LOCAL); #define TEST_PREFIX android_set_log_transport(LOGGER_LOCAL);
#include "liblog_test.cpp" #include "liblog_test.cpp"

View file

@ -1,5 +1,5 @@
#include <log/log_frontend.h> #include <log/log_transport.h>
#define liblog liblog_stderr #define liblog liblog_stderr
#define TEST_PREFIX android_set_log_frontend(LOGGER_STDERR); #define TEST_PREFIX android_set_log_transport(LOGGER_STDERR);
#define USING_LOGGER_STDERR #define USING_LOGGER_STDERR
#include "liblog_test.cpp" #include "liblog_test.cpp"

View file

@ -1,4 +1,4 @@
#include <log/log_frontend.h> #include <log/log_transport.h>
#define liblog liblog_stderr_local #define liblog liblog_stderr_local
#define TEST_PREFIX android_set_log_frontend(LOGGER_LOCAL | LOGGER_STDERR); #define TEST_PREFIX android_set_log_transport(LOGGER_LOCAL | LOGGER_STDERR);
#include "liblog_test.cpp" #include "liblog_test.cpp"

View file

@ -27,81 +27,76 @@
// include file API purity. We do however want to allow the _option_ that // include file API purity. We do however want to allow the _option_ that
// log/log_id.h could include this file, or related content, in the future. // log/log_id.h could include this file, or related content, in the future.
#ifndef __android_LogPriority_defined #ifndef __android_LogPriority_defined
# define ANDROID_LOG_INFO 4 #define ANDROID_LOG_INFO 4
#endif #endif
TEST(liblog, log_id) { TEST(liblog, log_id) {
int count = 0; int count = 0;
for(int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) { for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
log_id_t id = static_cast<log_id_t>(i); log_id_t id = static_cast<log_id_t>(i);
const char *name = android_log_id_to_name(id); const char* name = android_log_id_to_name(id);
if (id != android_name_to_log_id(name)) { if (id != android_name_to_log_id(name)) {
continue; continue;
}
++count;
fprintf(stderr, "log buffer %s\r", name);
} }
ASSERT_EQ(LOG_ID_MAX, count); ++count;
fprintf(stderr, "log buffer %s\r", name);
}
ASSERT_EQ(LOG_ID_MAX, count);
} }
TEST(liblog, __android_log_buf_print) { TEST(liblog, __android_log_buf_print) {
EXPECT_LT(0, __android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, EXPECT_LT(0, __android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO,
"TEST__android_log_buf_print", "TEST__android_log_buf_print", "radio"));
"radio")); usleep(1000);
usleep(1000); EXPECT_LT(0,
EXPECT_LT(0, __android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, __android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO,
"TEST__android_log_buf_print", "TEST__android_log_buf_print", "system"));
"system")); usleep(1000);
usleep(1000); EXPECT_LT(0, __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO,
EXPECT_LT(0, __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO, "TEST__android_log_buf_print", "main"));
"TEST__android_log_buf_print", usleep(1000);
"main"));
usleep(1000);
} }
TEST(liblog, __android_log_buf_write) { TEST(liblog, __android_log_buf_write) {
EXPECT_LT(0, __android_log_buf_write(LOG_ID_RADIO, ANDROID_LOG_INFO, EXPECT_LT(0, __android_log_buf_write(LOG_ID_RADIO, ANDROID_LOG_INFO,
"TEST__android_log_buf_write", "TEST__android_log_buf_write", "radio"));
"radio")); usleep(1000);
usleep(1000); EXPECT_LT(0,
EXPECT_LT(0, __android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO, __android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO,
"TEST__android_log_buf_write", "TEST__android_log_buf_write", "system"));
"system")); usleep(1000);
usleep(1000); EXPECT_LT(0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO,
EXPECT_LT(0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO, "TEST__android_log_buf_write", "main"));
"TEST__android_log_buf_write", usleep(1000);
"main"));
usleep(1000);
} }
static void* ConcurrentPrintFn(void *arg) { static void* ConcurrentPrintFn(void* arg) {
int ret = __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO, int ret = __android_log_buf_print(
"TEST__android_log_print", "Concurrent %" PRIuPTR, LOG_ID_MAIN, ANDROID_LOG_INFO, "TEST__android_log_print",
reinterpret_cast<uintptr_t>(arg)); "Concurrent %" PRIuPTR, reinterpret_cast<uintptr_t>(arg));
return reinterpret_cast<void*>(ret); return reinterpret_cast<void*>(ret);
} }
#define NUM_CONCURRENT 64 #define NUM_CONCURRENT 64
#define _concurrent_name(a,n) a##__concurrent##n #define _concurrent_name(a, n) a##__concurrent##n
#define concurrent_name(a,n) _concurrent_name(a,n) #define concurrent_name(a, n) _concurrent_name(a, n)
TEST(liblog, concurrent_name(__android_log_buf_print, NUM_CONCURRENT)) { TEST(liblog, concurrent_name(__android_log_buf_print, NUM_CONCURRENT)) {
pthread_t t[NUM_CONCURRENT]; pthread_t t[NUM_CONCURRENT];
int i; int i;
for (i=0; i < NUM_CONCURRENT; i++) { for (i = 0; i < NUM_CONCURRENT; i++) {
ASSERT_EQ(0, pthread_create(&t[i], NULL, ASSERT_EQ(0, pthread_create(&t[i], NULL, ConcurrentPrintFn,
ConcurrentPrintFn, reinterpret_cast<void*>(i)));
reinterpret_cast<void *>(i))); }
int ret = 0;
for (i = 0; i < NUM_CONCURRENT; i++) {
void* result;
ASSERT_EQ(0, pthread_join(t[i], &result));
int this_result = reinterpret_cast<uintptr_t>(result);
if ((0 == ret) && (0 != this_result)) {
ret = this_result;
} }
int ret = 0; }
for (i=0; i < NUM_CONCURRENT; i++) { ASSERT_LT(0, ret);
void* result;
ASSERT_EQ(0, pthread_join(t[i], &result));
int this_result = reinterpret_cast<uintptr_t>(result);
if ((0 == ret) && (0 != this_result)) {
ret = this_result;
}
}
ASSERT_LT(0, ret);
} }

View file

@ -27,91 +27,93 @@
#include <log/log_radio.h> #include <log/log_radio.h>
TEST(liblog, RLOG) { TEST(liblog, RLOG) {
static const char content[] = "log_radio.h"; static const char content[] = "log_radio.h";
static const char content_false[] = "log_radio.h false"; static const char content_false[] = "log_radio.h false";
// ratelimit content to 10/s to keep away from spam filters // ratelimit content to 10/s to keep away from spam filters
// do not send identical content together to keep away from spam filters // do not send identical content together to keep away from spam filters
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__RLOGV" #define LOG_TAG "TEST__RLOGV"
RLOGV(content); RLOGV(content);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__RLOGD" #define LOG_TAG "TEST__RLOGD"
RLOGD(content); RLOGD(content);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__RLOGI" #define LOG_TAG "TEST__RLOGI"
RLOGI(content); RLOGI(content);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__RLOGW" #define LOG_TAG "TEST__RLOGW"
RLOGW(content); RLOGW(content);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__RLOGE" #define LOG_TAG "TEST__RLOGE"
RLOGE(content); RLOGE(content);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__RLOGV" #define LOG_TAG "TEST__RLOGV"
RLOGV_IF(true, content); RLOGV_IF(true, content);
usleep(100000); usleep(100000);
RLOGV_IF(false, content_false); RLOGV_IF(false, content_false);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__RLOGD" #define LOG_TAG "TEST__RLOGD"
RLOGD_IF(true, content); RLOGD_IF(true, content);
usleep(100000); usleep(100000);
RLOGD_IF(false, content_false); RLOGD_IF(false, content_false);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__RLOGI" #define LOG_TAG "TEST__RLOGI"
RLOGI_IF(true, content); RLOGI_IF(true, content);
usleep(100000); usleep(100000);
RLOGI_IF(false, content_false); RLOGI_IF(false, content_false);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__RLOGW" #define LOG_TAG "TEST__RLOGW"
RLOGW_IF(true, content); RLOGW_IF(true, content);
usleep(100000); usleep(100000);
RLOGW_IF(false, content_false); RLOGW_IF(false, content_false);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__RLOGE" #define LOG_TAG "TEST__RLOGE"
RLOGE_IF(true, content); RLOGE_IF(true, content);
usleep(100000); usleep(100000);
RLOGE_IF(false, content_false); RLOGE_IF(false, content_false);
#ifdef __ANDROID__ #ifdef __ANDROID__
// give time for content to long-path through logger // give time for content to long-path through logger
sleep(1); sleep(1);
std::string buf = android::base::StringPrintf( std::string buf = android::base::StringPrintf(
"logcat -b radio --pid=%u -d -s" "logcat -b radio --pid=%u -d -s"
" TEST__RLOGV TEST__RLOGD TEST__RLOGI TEST__RLOGW TEST__RLOGE", " TEST__RLOGV TEST__RLOGD TEST__RLOGI TEST__RLOGW TEST__RLOGE",
(unsigned)getpid()); (unsigned)getpid());
FILE* fp = popen(buf.c_str(), "r"); FILE* fp = popen(buf.c_str(), "r");
int count = 0; int count = 0;
int count_false = 0; int count_false = 0;
if (fp) { if (fp) {
if (!android::base::ReadFdToString(fileno(fp), &buf)) buf = ""; if (!android::base::ReadFdToString(fileno(fp), &buf)) buf = "";
pclose(fp); pclose(fp);
for (size_t pos = 0; (pos = buf.find(content, pos)) != std::string::npos; ++pos) { for (size_t pos = 0; (pos = buf.find(content, pos)) != std::string::npos;
++count; ++pos) {
} ++count;
for (size_t pos = 0; (pos = buf.find(content_false, pos)) != std::string::npos; ++pos) {
++count_false;
}
} }
EXPECT_EQ(0, count_false); for (size_t pos = 0;
(pos = buf.find(content_false, pos)) != std::string::npos; ++pos) {
++count_false;
}
}
EXPECT_EQ(0, count_false);
#if LOG_NDEBUG #if LOG_NDEBUG
ASSERT_EQ(8, count); ASSERT_EQ(8, count);
#else #else
ASSERT_EQ(10, count); ASSERT_EQ(10, count);
#endif #endif
#else #else
GTEST_LOG_(INFO) << "This test does not test end-to-end.\n"; GTEST_LOG_(INFO) << "This test does not test end-to-end.\n";
#endif #endif
} }

View file

@ -20,8 +20,8 @@
#include <string> #include <string>
#include <android/log.h> // minimal logging API
#include <android-base/stringprintf.h> #include <android-base/stringprintf.h>
#include <android/log.h> // minimal logging API
#include <gtest/gtest.h> #include <gtest/gtest.h>
// Test the APIs in this standalone include file // Test the APIs in this standalone include file
#include <log/log_read.h> #include <log/log_read.h>
@ -29,90 +29,90 @@
TEST(liblog, __android_log_write__android_logger_list_read) { TEST(liblog, __android_log_write__android_logger_list_read) {
#ifdef __ANDROID__ #ifdef __ANDROID__
pid_t pid = getpid(); pid_t pid = getpid();
struct logger_list *logger_list; struct logger_list* logger_list;
ASSERT_TRUE(NULL != (logger_list = android_logger_list_open( ASSERT_TRUE(
LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid))); NULL !=
(logger_list = android_logger_list_open(
LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
struct timespec ts; struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
std::string buf = android::base::StringPrintf("pid=%u ts=%ld.%09ld", std::string buf = android::base::StringPrintf("pid=%u ts=%ld.%09ld", pid,
pid, ts.tv_sec, ts.tv_nsec); ts.tv_sec, ts.tv_nsec);
static const char tag[] = "liblog.__android_log_write__android_logger_list_read"; static const char tag[] =
static const char prio = ANDROID_LOG_DEBUG; "liblog.__android_log_write__android_logger_list_read";
ASSERT_LT(0, __android_log_write(prio, tag, buf.c_str())); static const char prio = ANDROID_LOG_DEBUG;
usleep(1000000); ASSERT_LT(0, __android_log_write(prio, tag, buf.c_str()));
usleep(1000000);
buf = std::string(&prio, sizeof(prio)) + buf = std::string(&prio, sizeof(prio)) + tag + std::string("", 1) + buf +
tag + std::string("", 1);
std::string("", 1) +
buf +
std::string("", 1);
int count = 0; int count = 0;
for (;;) { for (;;) {
log_msg log_msg; log_msg log_msg;
if (android_logger_list_read(logger_list, &log_msg) <= 0) break; if (android_logger_list_read(logger_list, &log_msg) <= 0) break;
EXPECT_EQ(log_msg.entry.pid, pid); EXPECT_EQ(log_msg.entry.pid, pid);
// There may be a future where we leak "liblog" tagged LOG_ID_EVENT // There may be a future where we leak "liblog" tagged LOG_ID_EVENT
// binary messages through so that logger losses can be correlated? // binary messages through so that logger losses can be correlated?
EXPECT_EQ(log_msg.id(), LOG_ID_MAIN); EXPECT_EQ(log_msg.id(), LOG_ID_MAIN);
if (log_msg.entry.len != buf.length()) continue; if (log_msg.entry.len != buf.length()) continue;
if (buf != std::string(log_msg.msg(), log_msg.entry.len)) continue; if (buf != std::string(log_msg.msg(), log_msg.entry.len)) continue;
++count; ++count;
} }
android_logger_list_close(logger_list); android_logger_list_close(logger_list);
EXPECT_EQ(1, count); EXPECT_EQ(1, count);
#else #else
GTEST_LOG_(INFO) << "This test does nothing.\n"; GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif #endif
} }
TEST(liblog, android_logger_get_) { TEST(liblog, android_logger_get_) {
#ifdef __ANDROID__ #ifdef __ANDROID__
// This test assumes the log buffers are filled with noise from // This test assumes the log buffers are filled with noise from
// normal operations. It will fail if done immediately after a // normal operations. It will fail if done immediately after a
// logcat -c. // logcat -c.
struct logger_list * logger_list = android_logger_list_alloc(ANDROID_LOG_WRONLY, 0, 0); struct logger_list* logger_list =
android_logger_list_alloc(ANDROID_LOG_WRONLY, 0, 0);
for(int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) { for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
log_id_t id = static_cast<log_id_t>(i); log_id_t id = static_cast<log_id_t>(i);
const char *name = android_log_id_to_name(id); const char* name = android_log_id_to_name(id);
if (id != android_name_to_log_id(name)) { if (id != android_name_to_log_id(name)) {
continue; continue;
}
fprintf(stderr, "log buffer %s\r", name);
struct logger * logger;
EXPECT_TRUE(NULL != (logger = android_logger_open(logger_list, id)));
EXPECT_EQ(id, android_logger_get_id(logger));
ssize_t get_log_size = android_logger_get_log_size(logger);
/* security buffer is allowed to be denied */
if (strcmp("security", name)) {
EXPECT_LT(0, get_log_size);
/* crash buffer is allowed to be empty, that is actually healthy! */
EXPECT_LE((strcmp("crash", name)) != 0,
android_logger_get_log_readable_size(logger));
} else {
EXPECT_NE(0, get_log_size);
if (get_log_size < 0) {
EXPECT_GT(0, android_logger_get_log_readable_size(logger));
} else {
EXPECT_LE(0, android_logger_get_log_readable_size(logger));
}
}
EXPECT_LT(0, android_logger_get_log_version(logger));
} }
fprintf(stderr, "log buffer %s\r", name);
struct logger* logger;
EXPECT_TRUE(NULL != (logger = android_logger_open(logger_list, id)));
EXPECT_EQ(id, android_logger_get_id(logger));
ssize_t get_log_size = android_logger_get_log_size(logger);
/* security buffer is allowed to be denied */
if (strcmp("security", name)) {
EXPECT_LT(0, get_log_size);
/* crash buffer is allowed to be empty, that is actually healthy! */
EXPECT_LE((strcmp("crash", name)) != 0,
android_logger_get_log_readable_size(logger));
} else {
EXPECT_NE(0, get_log_size);
if (get_log_size < 0) {
EXPECT_GT(0, android_logger_get_log_readable_size(logger));
} else {
EXPECT_LE(0, android_logger_get_log_readable_size(logger));
}
}
EXPECT_LT(0, android_logger_get_log_version(logger));
}
android_logger_list_close(logger_list); android_logger_list_close(logger_list);
#else #else
GTEST_LOG_(INFO) << "This test does nothing.\n"; GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif #endif
} }

View file

@ -27,91 +27,93 @@
#include <log/log_system.h> #include <log/log_system.h>
TEST(liblog, SLOG) { TEST(liblog, SLOG) {
static const char content[] = "log_system.h"; static const char content[] = "log_system.h";
static const char content_false[] = "log_system.h false"; static const char content_false[] = "log_system.h false";
// ratelimit content to 10/s to keep away from spam filters // ratelimit content to 10/s to keep away from spam filters
// do not send identical content together to keep away from spam filters // do not send identical content together to keep away from spam filters
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__SLOGV" #define LOG_TAG "TEST__SLOGV"
SLOGV(content); SLOGV(content);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__SLOGD" #define LOG_TAG "TEST__SLOGD"
SLOGD(content); SLOGD(content);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__SLOGI" #define LOG_TAG "TEST__SLOGI"
SLOGI(content); SLOGI(content);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__SLOGW" #define LOG_TAG "TEST__SLOGW"
SLOGW(content); SLOGW(content);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__SLOGE" #define LOG_TAG "TEST__SLOGE"
SLOGE(content); SLOGE(content);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__SLOGV" #define LOG_TAG "TEST__SLOGV"
SLOGV_IF(true, content); SLOGV_IF(true, content);
usleep(100000); usleep(100000);
SLOGV_IF(false, content_false); SLOGV_IF(false, content_false);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__SLOGD" #define LOG_TAG "TEST__SLOGD"
SLOGD_IF(true, content); SLOGD_IF(true, content);
usleep(100000); usleep(100000);
SLOGD_IF(false, content_false); SLOGD_IF(false, content_false);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__SLOGI" #define LOG_TAG "TEST__SLOGI"
SLOGI_IF(true, content); SLOGI_IF(true, content);
usleep(100000); usleep(100000);
SLOGI_IF(false, content_false); SLOGI_IF(false, content_false);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__SLOGW" #define LOG_TAG "TEST__SLOGW"
SLOGW_IF(true, content); SLOGW_IF(true, content);
usleep(100000); usleep(100000);
SLOGW_IF(false, content_false); SLOGW_IF(false, content_false);
usleep(100000); usleep(100000);
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "TEST__SLOGE" #define LOG_TAG "TEST__SLOGE"
SLOGE_IF(true, content); SLOGE_IF(true, content);
usleep(100000); usleep(100000);
SLOGE_IF(false, content_false); SLOGE_IF(false, content_false);
#ifdef __ANDROID__ #ifdef __ANDROID__
// give time for content to long-path through logger // give time for content to long-path through logger
sleep(1); sleep(1);
std::string buf = android::base::StringPrintf( std::string buf = android::base::StringPrintf(
"logcat -b system --pid=%u -d -s" "logcat -b system --pid=%u -d -s"
" TEST__SLOGV TEST__SLOGD TEST__SLOGI TEST__SLOGW TEST__SLOGE", " TEST__SLOGV TEST__SLOGD TEST__SLOGI TEST__SLOGW TEST__SLOGE",
(unsigned)getpid()); (unsigned)getpid());
FILE* fp = popen(buf.c_str(), "r"); FILE* fp = popen(buf.c_str(), "r");
int count = 0; int count = 0;
int count_false = 0; int count_false = 0;
if (fp) { if (fp) {
if (!android::base::ReadFdToString(fileno(fp), &buf)) buf = ""; if (!android::base::ReadFdToString(fileno(fp), &buf)) buf = "";
pclose(fp); pclose(fp);
for (size_t pos = 0; (pos = buf.find(content, pos)) != std::string::npos; ++pos) { for (size_t pos = 0; (pos = buf.find(content, pos)) != std::string::npos;
++count; ++pos) {
} ++count;
for (size_t pos = 0; (pos = buf.find(content_false, pos)) != std::string::npos; ++pos) {
++count_false;
}
} }
EXPECT_EQ(0, count_false); for (size_t pos = 0;
(pos = buf.find(content_false, pos)) != std::string::npos; ++pos) {
++count_false;
}
}
EXPECT_EQ(0, count_false);
#if LOG_NDEBUG #if LOG_NDEBUG
ASSERT_EQ(8, count); ASSERT_EQ(8, count);
#else #else
ASSERT_EQ(10, count); ASSERT_EQ(10, count);
#endif #endif
#else #else
GTEST_LOG_(INFO) << "This test does not test end-to-end.\n"; GTEST_LOG_(INFO) << "This test does not test end-to-end.\n";
#endif #endif
} }

View file

@ -22,16 +22,16 @@
TEST(liblog, log_time) { TEST(liblog, log_time) {
#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_ #ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
log_time(CLOCK_MONOTONIC); log_time(CLOCK_MONOTONIC);
EXPECT_EQ(log_time, log_time::EPOCH); EXPECT_EQ(log_time, log_time::EPOCH);
#endif #endif
struct timespec ts; struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
log_time tl(ts); log_time tl(ts);
EXPECT_EQ(tl, ts); EXPECT_EQ(tl, ts);
EXPECT_GE(tl, ts); EXPECT_GE(tl, ts);
EXPECT_LE(tl, ts); EXPECT_LE(tl, ts);
} }

View file

@ -22,58 +22,52 @@
#include "log_portability.h" #include "log_portability.h"
LIBLOG_ABI_PUBLIC int readv(int fd, struct iovec *vecs, int count) LIBLOG_ABI_PUBLIC int readv(int fd, struct iovec* vecs, int count) {
{ int total = 0;
int total = 0;
for ( ; count > 0; count--, vecs++ ) { for (; count > 0; count--, vecs++) {
char* buf = vecs->iov_base; char* buf = vecs->iov_base;
int len = vecs->iov_len; int len = vecs->iov_len;
while (len > 0) { while (len > 0) {
int ret = read( fd, buf, len ); int ret = read(fd, buf, len);
if (ret < 0) { if (ret < 0) {
if (total == 0) if (total == 0) total = -1;
total = -1; goto Exit;
goto Exit; }
} if (ret == 0) goto Exit;
if (ret == 0)
goto Exit;
total += ret; total += ret;
buf += ret; buf += ret;
len -= ret; len -= ret;
}
} }
}
Exit: Exit:
return total; return total;
} }
LIBLOG_ABI_PUBLIC int writev(int fd, const struct iovec *vecs, int count) LIBLOG_ABI_PUBLIC int writev(int fd, const struct iovec* vecs, int count) {
{ int total = 0;
int total = 0;
for ( ; count > 0; count--, vecs++ ) { for (; count > 0; count--, vecs++) {
const char* buf = vecs->iov_base; const char* buf = vecs->iov_base;
int len = vecs->iov_len; int len = vecs->iov_len;
while (len > 0) { while (len > 0) {
int ret = write( fd, buf, len ); int ret = write(fd, buf, len);
if (ret < 0) { if (ret < 0) {
if (total == 0) if (total == 0) total = -1;
total = -1; goto Exit;
goto Exit; }
} if (ret == 0) goto Exit;
if (ret == 0)
goto Exit;
total += ret; total += ret;
buf += ret; buf += ret;
len -= ret; len -= ret;
}
} }
}
Exit: Exit:
return total; return total;
} }
#endif #endif