diff --git a/libstats/socket/Android.bp b/libstats/socket/Android.bp index b7c07b624..beb009cbe 100644 --- a/libstats/socket/Android.bp +++ b/libstats/socket/Android.bp @@ -20,7 +20,10 @@ cc_library { name: "libstatssocket", srcs: [ + "stats_buffer_writer.c", "stats_event.c", + // TODO(b/145573568): Remove stats_event_list once stats_event + // migration is complete. "stats_event_list.c", "statsd_writer.c", ], diff --git a/libstats/socket/include/stats_buffer_writer.h b/libstats/socket/include/stats_buffer_writer.h new file mode 100644 index 000000000..de4a5e21d --- /dev/null +++ b/libstats/socket/include/stats_buffer_writer.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif // __CPLUSPLUS +void stats_log_close(); +int write_buffer_to_statsd(void* buffer, size_t size, uint32_t atomId); +#ifdef __cplusplus +} +#endif // __CPLUSPLUS diff --git a/libstats/socket/include/stats_event.h b/libstats/socket/include/stats_event.h index 89cb420bd..1760e7e12 100644 --- a/libstats/socket/include/stats_event.h +++ b/libstats/socket/include/stats_event.h @@ -76,7 +76,7 @@ #ifdef __cplusplus extern "C" { -#endif +#endif // __CPLUSPLUS struct stats_event; @@ -132,6 +132,6 @@ uint32_t stats_event_get_errors(struct stats_event* event); #ifdef __cplusplus } -#endif +#endif // __CPLUSPLUS #endif // ANDROID_STATS_LOG_STATS_EVENT_H diff --git a/libstats/socket/include/stats_event_list.h b/libstats/socket/include/stats_event_list.h index b7ada0cfd..7a26536d8 100644 --- a/libstats/socket/include/stats_event_list.h +++ b/libstats/socket/include/stats_event_list.h @@ -24,11 +24,9 @@ extern "C" { #endif void reset_log_context(android_log_context ctx); int write_to_logger(android_log_context context, log_id_t id); -void note_log_drop(int error, int atom_tag); +void note_log_drop(int error, int atomId); void stats_log_close(); int android_log_write_char_array(android_log_context ctx, const char* value, size_t len); -extern int (*write_to_statsd)(struct iovec* vec, size_t nr); - #ifdef __cplusplus } #endif diff --git a/libstats/socket/stats_buffer_writer.c b/libstats/socket/stats_buffer_writer.c new file mode 100644 index 000000000..c5c591d78 --- /dev/null +++ b/libstats/socket/stats_buffer_writer.c @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "include/stats_buffer_writer.h" +#ifdef __ANDROID__ +#include +#endif +#include +#include +#include +#include "statsd_writer.h" + +static const uint32_t kStatsEventTag = 1937006964; + +extern struct android_log_transport_write statsdLoggerWrite; + +static int __write_to_statsd_init(struct iovec* vec, size_t nr); +static int (*__write_to_statsd)(struct iovec* vec, size_t nr) = __write_to_statsd_init; + +void note_log_drop(int error, int atomId) { + statsdLoggerWrite.noteDrop(error, atomId); +} + +void stats_log_close() { + statsd_writer_init_lock(); + __write_to_statsd = __write_to_statsd_init; + if (statsdLoggerWrite.close) { + (*statsdLoggerWrite.close)(); + } + statsd_writer_init_unlock(); +} + +int write_buffer_to_statsd(void* buffer, size_t size, uint32_t atomId) { + int ret = 1; + +#ifdef __ANDROID__ + bool statsdEnabled = property_get_bool("ro.statsd.enable", true); +#else + bool statsdEnabled = false; +#endif + + if (statsdEnabled) { + struct iovec vecs[2]; + vecs[0].iov_base = (void*)&kStatsEventTag; + vecs[0].iov_len = sizeof(kStatsEventTag); + vecs[1].iov_base = buffer; + vecs[1].iov_len = size; + + ret = __write_to_statsd(vecs, 2); + + if (ret < 0) { + note_log_drop(ret, atomId); + } + } + + return ret; +} + +static int __write_to_stats_daemon(struct iovec* vec, size_t nr) { + int save_errno; + struct timespec ts; + size_t len, i; + + for (len = i = 0; i < nr; ++i) { + len += vec[i].iov_len; + } + if (!len) { + return -EINVAL; + } + + save_errno = errno; +#if defined(__ANDROID__) + clock_gettime(CLOCK_REALTIME, &ts); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; +#endif + + int ret = (int)(*statsdLoggerWrite.write)(&ts, vec, nr); + errno = save_errno; + return ret; +} + +static int __write_to_statsd_initialize_locked() { + if (!statsdLoggerWrite.open || ((*statsdLoggerWrite.open)() < 0)) { + if (statsdLoggerWrite.close) { + (*statsdLoggerWrite.close)(); + return -ENODEV; + } + } + return 1; +} + +static int __write_to_statsd_init(struct iovec* vec, size_t nr) { + int ret, save_errno = errno; + + statsd_writer_init_lock(); + + if (__write_to_statsd == __write_to_statsd_init) { + ret = __write_to_statsd_initialize_locked(); + if (ret < 0) { + statsd_writer_init_unlock(); + errno = save_errno; + return ret; + } + + __write_to_statsd = __write_to_stats_daemon; + } + + statsd_writer_init_unlock(); + + ret = __write_to_statsd(vec, nr); + errno = save_errno; + return ret; +} diff --git a/libstats/socket/stats_event.c b/libstats/socket/stats_event.c index 35081dc3f..dfd587ada 100644 --- a/libstats/socket/stats_event.c +++ b/libstats/socket/stats_event.c @@ -18,7 +18,7 @@ #include #include #include -#include "include/stats_event_list.h" +#include "stats_buffer_writer.h" #define STATS_EVENT_TAG 1937006964 #define LOGGER_ENTRY_MAX_PAYLOAD 4068 @@ -323,11 +323,5 @@ void stats_event_build(struct stats_event* event) { void stats_event_write(struct stats_event* event) { stats_event_build(event); - // Prepare iovecs for write to statsd. - struct iovec vecs[2]; - vecs[0].iov_base = &event->tag; - vecs[0].iov_len = sizeof(event->tag); - vecs[1].iov_base = &event->buf; - vecs[1].iov_len = event->size; - write_to_statsd(vecs, 2); + write_buffer_to_statsd(&event->buf, event->size, event->atomId); } diff --git a/libstats/socket/stats_event_list.c b/libstats/socket/stats_event_list.c index ae12cbeaa..661a2237f 100644 --- a/libstats/socket/stats_event_list.c +++ b/libstats/socket/stats_event_list.c @@ -18,7 +18,7 @@ #include #include -#include "statsd_writer.h" +#include "stats_buffer_writer.h" #define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t)) @@ -38,11 +38,6 @@ typedef struct { uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD]; } android_log_context_internal; -extern struct android_log_transport_write statsdLoggerWrite; - -static int __write_to_statsd_init(struct iovec* vec, size_t nr); -int (*write_to_statsd)(struct iovec* vec, size_t nr) = __write_to_statsd_init; - // Similar to create_android_logger(), but instead of allocation a new buffer, // this function resets the buffer for resuse. void reset_log_context(android_log_context ctx) { @@ -92,12 +87,7 @@ int stats_write_list(android_log_context ctx) { msg += sizeof(uint8_t) + sizeof(uint8_t); } - struct iovec vec[2]; - vec[0].iov_base = &context->tag; - vec[0].iov_len = sizeof(context->tag); - vec[1].iov_base = (void*)msg; - vec[1].iov_len = len; - return write_to_statsd(vec, 2); + return write_buffer_to_statsd((void*)msg, len, 0); } int write_to_logger(android_log_context ctx, log_id_t id) { @@ -120,80 +110,6 @@ int write_to_logger(android_log_context ctx, log_id_t id) { return retValue; } -void note_log_drop(int error, int tag) { - statsdLoggerWrite.noteDrop(error, tag); -} - -void stats_log_close() { - statsd_writer_init_lock(); - write_to_statsd = __write_to_statsd_init; - if (statsdLoggerWrite.close) { - (*statsdLoggerWrite.close)(); - } - statsd_writer_init_unlock(); -} - -/* log_init_lock assumed */ -static int __write_to_statsd_initialize_locked() { - if (!statsdLoggerWrite.open || ((*statsdLoggerWrite.open)() < 0)) { - if (statsdLoggerWrite.close) { - (*statsdLoggerWrite.close)(); - return -ENODEV; - } - } - return 1; -} - -static int __write_to_stats_daemon(struct iovec* vec, size_t nr) { - int save_errno; - struct timespec ts; - size_t len, i; - - for (len = i = 0; i < nr; ++i) { - len += vec[i].iov_len; - } - if (!len) { - return -EINVAL; - } - - save_errno = errno; -#if defined(__ANDROID__) - clock_gettime(CLOCK_REALTIME, &ts); -#else - struct timeval tv; - gettimeofday(&tv, NULL); - ts.tv_sec = tv.tv_sec; - ts.tv_nsec = tv.tv_usec * 1000; -#endif - - int ret = (int)(*statsdLoggerWrite.write)(&ts, vec, nr); - errno = save_errno; - return ret; -} - -static int __write_to_statsd_init(struct iovec* vec, size_t nr) { - int ret, save_errno = errno; - - statsd_writer_init_lock(); - - if (write_to_statsd == __write_to_statsd_init) { - ret = __write_to_statsd_initialize_locked(); - if (ret < 0) { - statsd_writer_init_unlock(); - errno = save_errno; - return ret; - } - - write_to_statsd = __write_to_stats_daemon; - } - - statsd_writer_init_unlock(); - - ret = write_to_statsd(vec, nr); - errno = save_errno; - return ret; -} - static inline void copy4LE(uint8_t* buf, uint32_t val) { buf[0] = val & 0xFF; buf[1] = (val >> 8) & 0xFF;