1 /* 2 * Copyright (C) 2007 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 #include <time.h> 17 #include <stdio.h> 18 #ifdef HAVE_PTHREADS 19 #include <pthread.h> 20 #endif 21 #include <unistd.h> 22 #include <errno.h> 23 #include <fcntl.h> 24 #include <string.h> 25 #include <stdlib.h> 26 #include <stdarg.h> 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 30 #include <cutils/logger.h> 31 #include <cutils/logd.h> 32 #include <cutils/log.h> 33 34 #define LOG_BUF_SIZE 1024 35 36 #if FAKE_LOG_DEVICE 37 // This will be defined when building for the host. 38 #define log_open(pathname, flags) fakeLogOpen(pathname, flags) 39 #define log_writev(filedes, vector, count) fakeLogWritev(filedes, vector, count) 40 #define log_close(filedes) fakeLogClose(filedes) 41 #else 42 #define log_open(pathname, flags) open(pathname, (flags) | O_CLOEXEC) 43 #define log_writev(filedes, vector, count) writev(filedes, vector, count) 44 #define log_close(filedes) close(filedes) 45 #endif 46 47 static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr); 48 static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init; 49 #ifdef HAVE_PTHREADS 50 static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER; 51 #endif 52 53 static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1 }; 54 55 /* 56 * This is used by the C++ code to decide if it should write logs through 57 * the C code. Basically, if /dev/log/... is available, we're running in 58 * the simulator rather than a desktop tool and want to use the device. 59 */ 60 static enum { 61 kLogUninitialized, kLogNotAvailable, kLogAvailable 62 } g_log_status = kLogUninitialized; 63 int __android_log_dev_available(void) 64 { 65 if (g_log_status == kLogUninitialized) { 66 if (access("/dev/"LOGGER_LOG_MAIN, W_OK) == 0) 67 g_log_status = kLogAvailable; 68 else 69 g_log_status = kLogNotAvailable; 70 } 71 72 return (g_log_status == kLogAvailable); 73 } 74 75 static int __write_to_log_null(log_id_t log_fd, struct iovec *vec, size_t nr) 76 { 77 return -1; 78 } 79 80 static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr) 81 { 82 ssize_t ret; 83 int log_fd; 84 85 if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) { 86 log_fd = log_fds[(int)log_id]; 87 } else { 88 return EBADF; 89 } 90 91 do { 92 ret = log_writev(log_fd, vec, nr); 93 } while (ret < 0 && errno == EINTR); 94 95 return ret; 96 } 97 98 static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) 99 { 100 #ifdef HAVE_PTHREADS 101 pthread_mutex_lock(&log_init_lock); 102 #endif 103 104 if (write_to_log == __write_to_log_init) { 105 log_fds[LOG_ID_MAIN] = log_open("/dev/"LOGGER_LOG_MAIN, O_WRONLY); 106 log_fds[LOG_ID_RADIO] = log_open("/dev/"LOGGER_LOG_RADIO, O_WRONLY); 107 log_fds[LOG_ID_EVENTS] = log_open("/dev/"LOGGER_LOG_EVENTS, O_WRONLY); 108 log_fds[LOG_ID_SYSTEM] = log_open("/dev/"LOGGER_LOG_SYSTEM, O_WRONLY); 109 110 write_to_log = __write_to_log_kernel; 111 112 if (log_fds[LOG_ID_MAIN] < 0 || log_fds[LOG_ID_RADIO] < 0 || 113 log_fds[LOG_ID_EVENTS] < 0) { 114 log_close(log_fds[LOG_ID_MAIN]); 115 log_close(log_fds[LOG_ID_RADIO]); 116 log_close(log_fds[LOG_ID_EVENTS]); 117 log_fds[LOG_ID_MAIN] = -1; 118 log_fds[LOG_ID_RADIO] = -1; 119 log_fds[LOG_ID_EVENTS] = -1; 120 write_to_log = __write_to_log_null; 121 } 122 123 if (log_fds[LOG_ID_SYSTEM] < 0) { 124 log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN]; 125 } 126 } 127 128 #ifdef HAVE_PTHREADS 129 pthread_mutex_unlock(&log_init_lock); 130 #endif 131 132 return write_to_log(log_id, vec, nr); 133 } 134 135 int __android_log_write(int prio, const char *tag, const char *msg) 136 { 137 struct iovec vec[3]; 138 log_id_t log_id = LOG_ID_MAIN; 139 char tmp_tag[32]; 140 141 if (!tag) 142 tag = ""; 143 144 /* XXX: This needs to go! */ 145 if (!strcmp(tag, "HTC_RIL") || 146 !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */ 147 !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */ 148 !strcmp(tag, "AT") || 149 !strcmp(tag, "GSM") || 150 !strcmp(tag, "STK") || 151 !strcmp(tag, "CDMA") || 152 !strcmp(tag, "PHONE") || 153 !strcmp(tag, "SMS")) { 154 log_id = LOG_ID_RADIO; 155 // Inform third party apps/ril/radio.. to use Rlog or RLOG 156 snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag); 157 tag = tmp_tag; 158 } 159 160 vec[0].iov_base = (unsigned char *) &prio; 161 vec[0].iov_len = 1; 162 vec[1].iov_base = (void *) tag; 163 vec[1].iov_len = strlen(tag) + 1; 164 vec[2].iov_base = (void *) msg; 165 vec[2].iov_len = strlen(msg) + 1; 166 167 return write_to_log(log_id, vec, 3); 168 } 169 170 int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg) 171 { 172 struct iovec vec[3]; 173 char tmp_tag[32]; 174 175 if (!tag) 176 tag = ""; 177 178 /* XXX: This needs to go! */ 179 if ((bufID != LOG_ID_RADIO) && 180 (!strcmp(tag, "HTC_RIL") || 181 !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */ 182 !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */ 183 !strcmp(tag, "AT") || 184 !strcmp(tag, "GSM") || 185 !strcmp(tag, "STK") || 186 !strcmp(tag, "CDMA") || 187 !strcmp(tag, "PHONE") || 188 !strcmp(tag, "SMS"))) { 189 bufID = LOG_ID_RADIO; 190 // Inform third party apps/ril/radio.. to use Rlog or RLOG 191 snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag); 192 tag = tmp_tag; 193 } 194 195 vec[0].iov_base = (unsigned char *) &prio; 196 vec[0].iov_len = 1; 197 vec[1].iov_base = (void *) tag; 198 vec[1].iov_len = strlen(tag) + 1; 199 vec[2].iov_base = (void *) msg; 200 vec[2].iov_len = strlen(msg) + 1; 201 202 return write_to_log(bufID, vec, 3); 203 } 204 205 int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap) 206 { 207 char buf[LOG_BUF_SIZE]; 208 209 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 210 211 return __android_log_write(prio, tag, buf); 212 } 213 214 int __android_log_print(int prio, const char *tag, const char *fmt, ...) 215 { 216 va_list ap; 217 char buf[LOG_BUF_SIZE]; 218 219 va_start(ap, fmt); 220 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 221 va_end(ap); 222 223 return __android_log_write(prio, tag, buf); 224 } 225 226 int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...) 227 { 228 va_list ap; 229 char buf[LOG_BUF_SIZE]; 230 231 va_start(ap, fmt); 232 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 233 va_end(ap); 234 235 return __android_log_buf_write(bufID, prio, tag, buf); 236 } 237 238 void __android_log_assert(const char *cond, const char *tag, 239 const char *fmt, ...) 240 { 241 char buf[LOG_BUF_SIZE]; 242 243 if (fmt) { 244 va_list ap; 245 va_start(ap, fmt); 246 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); 247 va_end(ap); 248 } else { 249 /* Msg not provided, log condition. N.B. Do not use cond directly as 250 * format string as it could contain spurious '%' syntax (e.g. 251 * "%d" in "blocks%devs == 0"). 252 */ 253 if (cond) 254 snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond); 255 else 256 strcpy(buf, "Unspecified assertion failed"); 257 } 258 259 __android_log_write(ANDROID_LOG_FATAL, tag, buf); 260 261 __builtin_trap(); /* trap so we have a chance to debug the situation */ 262 } 263 264 int __android_log_bwrite(int32_t tag, const void *payload, size_t len) 265 { 266 struct iovec vec[2]; 267 268 vec[0].iov_base = &tag; 269 vec[0].iov_len = sizeof(tag); 270 vec[1].iov_base = (void*)payload; 271 vec[1].iov_len = len; 272 273 return write_to_log(LOG_ID_EVENTS, vec, 2); 274 } 275 276 /* 277 * Like __android_log_bwrite, but takes the type as well. Doesn't work 278 * for the general case where we're generating lists of stuff, but very 279 * handy if we just want to dump an integer into the log. 280 */ 281 int __android_log_btwrite(int32_t tag, char type, const void *payload, 282 size_t len) 283 { 284 struct iovec vec[3]; 285 286 vec[0].iov_base = &tag; 287 vec[0].iov_len = sizeof(tag); 288 vec[1].iov_base = &type; 289 vec[1].iov_len = sizeof(type); 290 vec[2].iov_base = (void*)payload; 291 vec[2].iov_len = len; 292 293 return write_to_log(LOG_ID_EVENTS, vec, 3); 294 } 295