1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "include/stats_buffer_writer.h" 18 #include <errno.h> 19 #include <sys/time.h> 20 #include <sys/uio.h> 21 #include "statsd_writer.h" 22 23 static const uint32_t kStatsEventTag = 1937006964; 24 25 extern struct android_log_transport_write statsdLoggerWrite; 26 27 static int __write_to_statsd_init(struct iovec* vec, size_t nr); 28 static int (*__write_to_statsd)(struct iovec* vec, size_t nr) = __write_to_statsd_init; 29 30 void note_log_drop(int error, int atomId) { 31 statsdLoggerWrite.noteDrop(error, atomId); 32 } 33 34 void stats_log_close() { 35 statsd_writer_init_lock(); 36 __write_to_statsd = __write_to_statsd_init; 37 if (statsdLoggerWrite.close) { 38 (*statsdLoggerWrite.close)(); 39 } 40 statsd_writer_init_unlock(); 41 } 42 43 int stats_log_is_closed() { 44 return statsdLoggerWrite.isClosed && (*statsdLoggerWrite.isClosed)(); 45 } 46 47 int write_buffer_to_statsd(void* buffer, size_t size, uint32_t atomId) { 48 int ret = 1; 49 50 struct iovec vecs[2]; 51 vecs[0].iov_base = (void*)&kStatsEventTag; 52 vecs[0].iov_len = sizeof(kStatsEventTag); 53 vecs[1].iov_base = buffer; 54 vecs[1].iov_len = size; 55 56 ret = __write_to_statsd(vecs, 2); 57 58 if (ret < 0) { 59 note_log_drop(ret, atomId); 60 } 61 62 return ret; 63 } 64 65 static int __write_to_stats_daemon(struct iovec* vec, size_t nr) { 66 int save_errno; 67 struct timespec ts; 68 size_t len, i; 69 70 for (len = i = 0; i < nr; ++i) { 71 len += vec[i].iov_len; 72 } 73 if (!len) { 74 return -EINVAL; 75 } 76 77 save_errno = errno; 78 #if defined(__ANDROID__) 79 clock_gettime(CLOCK_REALTIME, &ts); 80 #else 81 struct timeval tv; 82 gettimeofday(&tv, NULL); 83 ts.tv_sec = tv.tv_sec; 84 ts.tv_nsec = tv.tv_usec * 1000; 85 #endif 86 87 int ret = (int)(*statsdLoggerWrite.write)(&ts, vec, nr); 88 errno = save_errno; 89 return ret; 90 } 91 92 static int __write_to_statsd_initialize_locked() { 93 if (!statsdLoggerWrite.open || ((*statsdLoggerWrite.open)() < 0)) { 94 if (statsdLoggerWrite.close) { 95 (*statsdLoggerWrite.close)(); 96 return -ENODEV; 97 } 98 } 99 return 1; 100 } 101 102 static int __write_to_statsd_init(struct iovec* vec, size_t nr) { 103 int ret, save_errno = errno; 104 105 statsd_writer_init_lock(); 106 107 if (__write_to_statsd == __write_to_statsd_init) { 108 ret = __write_to_statsd_initialize_locked(); 109 if (ret < 0) { 110 statsd_writer_init_unlock(); 111 errno = save_errno; 112 return ret; 113 } 114 115 __write_to_statsd = __write_to_stats_daemon; 116 } 117 118 statsd_writer_init_unlock(); 119 120 ret = __write_to_statsd(vec, nr); 121 errno = save_errno; 122 return ret; 123 } 124