blob: 5406c50e1c6dcdaa4990e8685ac38c5c80f0f64b [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
Mark Salyzyne9c41962014-01-02 13:52:29 -08002 * Copyright (C) 2007-2014 The Android Open Source Project
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08003 *
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 */
Mark Salyzyn31dd00f2015-03-04 17:01:30 -080016#if (FAKE_LOG_DEVICE == 0)
Mark Salyzynd45d36e2015-02-12 15:14:26 -080017#include <endian.h>
Mark Salyzyn31dd00f2015-03-04 17:01:30 -080018#endif
Mark Salyzyn154f4602014-02-20 14:59:07 -080019#include <errno.h>
20#include <fcntl.h>
Yabin Cui4a6e5a32015-01-26 19:48:54 -080021#if !defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080022#include <pthread.h>
23#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080024#include <stdarg.h>
Mark Salyzynd45d36e2015-02-12 15:14:26 -080025#include <stdatomic.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080026#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
Nick Kralevicha1703222013-03-15 09:45:12 -070029#include <sys/stat.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080030#include <sys/types.h>
31#if (FAKE_LOG_DEVICE == 0)
32#include <sys/socket.h>
33#include <sys/un.h>
34#endif
35#include <time.h>
36#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080037
Dan Albertc68fedc2014-08-18 17:29:34 -070038#ifdef __BIONIC__
39#include <android/set_abort_message.h>
40#endif
41
Mark Salyzyna0140042015-03-13 06:50:32 -070042#include <log/event_tag_map.h>
Colin Cross9227bd32013-07-23 16:59:20 -070043#include <log/logd.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080044#include <log/logger.h>
45#include <log/log_read.h>
46#include <private/android_filesystem_config.h>
Mark Salyzyn7a809402015-01-16 13:38:07 -080047#include <private/android_logger.h>
Mark Salyzyne9c41962014-01-02 13:52:29 -080048
Mark Salyzyncf4aa032013-11-22 07:54:30 -080049#define LOG_BUF_SIZE 1024
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050
51#if FAKE_LOG_DEVICE
Mark Salyzyn154f4602014-02-20 14:59:07 -080052/* This will be defined when building for the host. */
Kristian Monsenb5a98902014-01-28 11:26:56 -080053#include "fake_log_device.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080054#endif
55
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080056static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -080057static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080058
Mark Salyzyna04464a2014-04-30 08:50:53 -070059#ifndef __unused
60#define __unused __attribute__((__unused__))
61#endif
Kristian Monsenb5a98902014-01-28 11:26:56 -080062
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080063#if !defined(_WIN32)
64static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
65
66static void lock()
67{
68 /*
69 * If we trigger a signal handler in the middle of locked activity and the
70 * signal handler logs a message, we could get into a deadlock state.
71 */
72 pthread_mutex_lock(&log_init_lock);
73}
74
Mark Salyzyna0140042015-03-13 06:50:32 -070075static int trylock()
76{
77 return pthread_mutex_trylock(&log_init_lock);
78}
79
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080080static void unlock()
81{
82 pthread_mutex_unlock(&log_init_lock);
83}
84
85#else /* !defined(_WIN32) */
86
87#define lock() ((void)0)
Mark Salyzyna0140042015-03-13 06:50:32 -070088#define trylock() (0) /* success */
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -080089#define unlock() ((void)0)
90
91#endif /* !defined(_WIN32) */
92
Mark Salyzyn154f4602014-02-20 14:59:07 -080093#if FAKE_LOG_DEVICE
Mark Salyzyn083b0372015-12-04 10:59:45 -080094static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1, -1 };
Mark Salyzyna04464a2014-04-30 08:50:53 -070095#else
96static int logd_fd = -1;
Mark Salyzynd91ab582014-12-15 10:52:12 -080097static int pstore_fd = -1;
Mark Salyzyn154f4602014-02-20 14:59:07 -080098#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080099
100/*
101 * This is used by the C++ code to decide if it should write logs through
Mark Salyzyn154f4602014-02-20 14:59:07 -0800102 * the C code. Basically, if /dev/socket/logd is available, we're running in
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800103 * the simulator rather than a desktop tool and want to use the device.
104 */
105static enum {
Chris Pearson19299902010-06-02 16:25:35 -0700106 kLogUninitialized, kLogNotAvailable, kLogAvailable
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800107} g_log_status = kLogUninitialized;
Mark Salyzyn53016d82015-02-04 12:28:47 -0800108
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800109int __android_log_dev_available(void)
110{
111 if (g_log_status == kLogUninitialized) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800112 if (access("/dev/socket/logdw", W_OK) == 0)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800113 g_log_status = kLogAvailable;
114 else
115 g_log_status = kLogNotAvailable;
116 }
117
118 return (g_log_status == kLogAvailable);
119}
120
Mark Salyzyn8245af12014-03-25 13:45:33 -0700121/* log_init_lock assumed */
122static int __write_to_log_initialize()
123{
124 int i, ret = 0;
125
126#if FAKE_LOG_DEVICE
127 for (i = 0; i < LOG_ID_MAX; i++) {
128 char buf[sizeof("/dev/log_system")];
129 snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i));
130 log_fds[i] = fakeLogOpen(buf, O_WRONLY);
131 }
132#else
Mark Salyzyn0d00a442015-03-13 12:15:57 -0700133 if (pstore_fd < 0) {
134 pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY));
Mark Salyzyn8245af12014-03-25 13:45:33 -0700135 }
136
Mark Salyzyn0d00a442015-03-13 12:15:57 -0700137 if (logd_fd < 0) {
138 i = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0));
139 if (i < 0) {
140 ret = -errno;
141 } else if (TEMP_FAILURE_RETRY(fcntl(i, F_SETFL, O_NONBLOCK)) < 0) {
Mark Salyzyn8245af12014-03-25 13:45:33 -0700142 ret = -errno;
143 close(i);
Mark Salyzyn0d00a442015-03-13 12:15:57 -0700144 } else {
145 struct sockaddr_un un;
146 memset(&un, 0, sizeof(struct sockaddr_un));
147 un.sun_family = AF_UNIX;
148 strcpy(un.sun_path, "/dev/socket/logdw");
149
150 if (TEMP_FAILURE_RETRY(connect(i, (struct sockaddr *)&un,
151 sizeof(struct sockaddr_un))) < 0) {
152 ret = -errno;
153 close(i);
154 } else {
155 logd_fd = i;
156 }
Mark Salyzyn8245af12014-03-25 13:45:33 -0700157 }
158 }
Mark Salyzyn8245af12014-03-25 13:45:33 -0700159#endif
160
161 return ret;
162}
163
Mark Salyzyn53016d82015-02-04 12:28:47 -0800164static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800165{
166 ssize_t ret;
Mark Salyzyn8245af12014-03-25 13:45:33 -0700167#if FAKE_LOG_DEVICE
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800168 int log_fd;
169
170 if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) {
171 log_fd = log_fds[(int)log_id];
172 } else {
Mark Salyzyn8245af12014-03-25 13:45:33 -0700173 return -EBADF;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800174 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800175 do {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800176 ret = fakeLogWritev(log_fd, vec, nr);
Mark Salyzyn8245af12014-03-25 13:45:33 -0700177 if (ret < 0) {
178 ret = -errno;
179 }
180 } while (ret == -EINTR);
Mark Salyzyn154f4602014-02-20 14:59:07 -0800181#else
Mark Salyzynd91ab582014-12-15 10:52:12 -0800182 static const unsigned header_length = 2;
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700183 struct iovec newVec[nr + header_length];
Mark Salyzynd91ab582014-12-15 10:52:12 -0800184 android_log_header_t header;
185 android_pmsg_log_header_t pmsg_header;
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700186 struct timespec ts;
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700187 size_t i, payload_size;
Mark Salyzyn076ba812014-05-29 17:53:41 -0700188 static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */
Mark Salyzynd91ab582014-12-15 10:52:12 -0800189 static pid_t last_pid = (pid_t) -1;
Mark Salyzynd45d36e2015-02-12 15:14:26 -0800190 static atomic_int_fast32_t dropped;
Mark Salyzyn083b0372015-12-04 10:59:45 -0800191 static atomic_int_fast32_t dropped_security;
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700192
Mark Salyzyn31f7df52015-03-13 15:57:11 -0700193 if (!nr) {
194 return -EINVAL;
195 }
196
Mark Salyzyn076ba812014-05-29 17:53:41 -0700197 if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */
198 last_uid = getuid();
199 }
Mark Salyzynd91ab582014-12-15 10:52:12 -0800200 if (last_pid == (pid_t) -1) {
201 last_pid = getpid();
Mark Salyzyn154f4602014-02-20 14:59:07 -0800202 }
Mark Salyzyn083b0372015-12-04 10:59:45 -0800203 if (log_id == LOG_ID_SECURITY) {
Mark Salyzyna0140042015-03-13 06:50:32 -0700204 if (vec[0].iov_len < 4) {
205 return -EINVAL;
206 }
Mark Salyzyn083b0372015-12-04 10:59:45 -0800207 if ((last_uid != AID_SYSTEM) && (last_uid != AID_ROOT)) {
208 uid_t uid = geteuid();
209 if ((uid != AID_SYSTEM) && (uid != AID_ROOT)) {
210 gid_t gid = getgid();
211 if ((gid != AID_SYSTEM) && (gid != AID_ROOT)) {
212 gid = getegid();
213 if ((gid != AID_SYSTEM) && (gid != AID_ROOT)) {
214 return -EPERM;
215 }
216 }
217 }
218 }
219 if (!__android_log_security()) {
Mark Salyzyna0140042015-03-13 06:50:32 -0700220 atomic_store(&dropped_security, 0);
221 return -EPERM;
222 }
223 } else if (log_id == LOG_ID_EVENTS) {
Mark Salyzyn0ee8de32016-01-06 21:17:43 +0000224 static atomic_uintptr_t map;
225 int ret;
226 const char *tag;
227 EventTagMap *m, *f;
228
Mark Salyzyna0140042015-03-13 06:50:32 -0700229 if (vec[0].iov_len < 4) {
230 return -EINVAL;
231 }
232
Mark Salyzyn0ee8de32016-01-06 21:17:43 +0000233 tag = NULL;
234 f = NULL;
235 m = (EventTagMap *)atomic_load(&map);
236
237 if (!m) {
238 ret = trylock();
239 m = (EventTagMap *)atomic_load(&map); /* trylock flush cache */
Mark Salyzyna0140042015-03-13 06:50:32 -0700240 if (!m) {
Mark Salyzyn0ee8de32016-01-06 21:17:43 +0000241 m = android_openEventTagMap(EVENT_TAG_MAP_FILE);
242 if (ret) { /* trylock failed, use local copy, mark for close */
243 f = m;
244 } else {
245 if (!m) { /* One chance to open map file */
246 m = (EventTagMap *)(uintptr_t)-1LL;
Mark Salyzyna0140042015-03-13 06:50:32 -0700247 }
Mark Salyzyn0ee8de32016-01-06 21:17:43 +0000248 atomic_store(&map, (uintptr_t)m);
Mark Salyzyna0140042015-03-13 06:50:32 -0700249 }
250 }
Mark Salyzyn0ee8de32016-01-06 21:17:43 +0000251 if (!ret) { /* trylock succeeded, unlock */
252 unlock();
253 }
254 }
255 if (m && (m != (EventTagMap *)(uintptr_t)-1LL)) {
256 tag = android_lookupEventTag(
Mark Salyzyna0140042015-03-13 06:50:32 -0700257 m,
258 htole32(((uint32_t *)vec[0].iov_base)[0]));
Mark Salyzyn0ee8de32016-01-06 21:17:43 +0000259 }
260 ret = __android_log_is_loggable(ANDROID_LOG_INFO,
261 tag,
262 ANDROID_LOG_VERBOSE);
263 if (f) { /* local copy marked for close */
264 android_closeEventTagMap(f);
265 }
266 if (!ret) {
267 return -EPERM;
Mark Salyzyna0140042015-03-13 06:50:32 -0700268 }
269 } else {
270 /* Validate the incoming tag, tag content can not split across iovec */
271 char prio = ANDROID_LOG_VERBOSE;
272 const char *tag = vec[0].iov_base;
273 size_t len = vec[0].iov_len;
274 if (!tag) {
275 len = 0;
276 }
277 if (len > 0) {
278 prio = *tag;
279 if (len > 1) {
280 --len;
281 ++tag;
282 } else {
283 len = vec[1].iov_len;
284 tag = ((const char *)vec[1].iov_base);
285 if (!tag) {
286 len = 0;
287 }
288 }
289 }
290 /* tag must be nul terminated */
291 if (strnlen(tag, len) >= len) {
292 tag = NULL;
293 }
294
295 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800296 return -EPERM;
297 }
298 }
Mark Salyzyna0140042015-03-13 06:50:32 -0700299
Mark Salyzynb992d0d2014-03-20 16:09:38 -0700300 /*
301 * struct {
Mark Salyzyn53016d82015-02-04 12:28:47 -0800302 * // what we provide to pstore
Mark Salyzynd91ab582014-12-15 10:52:12 -0800303 * android_pmsg_log_header_t pmsg_header;
304 * // what we provide to socket
Mark Salyzyn7a809402015-01-16 13:38:07 -0800305 * android_log_header_t header;
Mark Salyzynb992d0d2014-03-20 16:09:38 -0700306 * // caller provides
307 * union {
308 * struct {
309 * char prio;
310 * char payload[];
311 * } string;
312 * struct {
313 * uint32_t tag
314 * char payload[];
315 * } binary;
316 * };
317 * };
318 */
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700319
Mark Salyzynba7a9a02015-12-01 15:57:25 -0800320 clock_gettime(android_log_clockid(), &ts);
Mark Salyzyn076ba812014-05-29 17:53:41 -0700321
Mark Salyzynd91ab582014-12-15 10:52:12 -0800322 pmsg_header.magic = LOGGER_MAGIC;
323 pmsg_header.len = sizeof(pmsg_header) + sizeof(header);
324 pmsg_header.uid = last_uid;
325 pmsg_header.pid = last_pid;
326
Mark Salyzyn7a809402015-01-16 13:38:07 -0800327 header.tid = gettid();
328 header.realtime.tv_sec = ts.tv_sec;
329 header.realtime.tv_nsec = ts.tv_nsec;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800330
Mark Salyzynd91ab582014-12-15 10:52:12 -0800331 newVec[0].iov_base = (unsigned char *) &pmsg_header;
332 newVec[0].iov_len = sizeof(pmsg_header);
333 newVec[1].iov_base = (unsigned char *) &header;
334 newVec[1].iov_len = sizeof(header);
Mark Salyzyn154f4602014-02-20 14:59:07 -0800335
Mark Salyzynd45d36e2015-02-12 15:14:26 -0800336 if (logd_fd > 0) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800337 int32_t snapshot = atomic_exchange_explicit(&dropped_security, 0,
338 memory_order_relaxed);
339 if (snapshot) {
340 android_log_event_int_t buffer;
341
342 header.id = LOG_ID_SECURITY;
343 buffer.header.tag = htole32(LIBLOG_LOG_TAG);
344 buffer.payload.type = EVENT_TYPE_INT;
345 buffer.payload.data = htole32(snapshot);
346
347 newVec[2].iov_base = &buffer;
348 newVec[2].iov_len = sizeof(buffer);
349
350 ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2));
351 if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
352 atomic_fetch_add_explicit(&dropped_security, snapshot,
353 memory_order_relaxed);
354 }
355 }
356 snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
Mark Salyzyna0140042015-03-13 06:50:32 -0700357 if (snapshot && __android_log_is_loggable(ANDROID_LOG_INFO,
358 "liblog",
359 ANDROID_LOG_VERBOSE)) {
Mark Salyzynd45d36e2015-02-12 15:14:26 -0800360 android_log_event_int_t buffer;
361
362 header.id = LOG_ID_EVENTS;
363 buffer.header.tag = htole32(LIBLOG_LOG_TAG);
364 buffer.payload.type = EVENT_TYPE_INT;
365 buffer.payload.data = htole32(snapshot);
366
367 newVec[2].iov_base = &buffer;
368 newVec[2].iov_len = sizeof(buffer);
369
370 ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2));
371 if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800372 atomic_fetch_add_explicit(&dropped, snapshot,
373 memory_order_relaxed);
Mark Salyzynd45d36e2015-02-12 15:14:26 -0800374 }
375 }
376 }
377
378 header.id = log_id;
379
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700380 for (payload_size = 0, i = header_length; i < nr + header_length; i++) {
381 newVec[i].iov_base = vec[i - header_length].iov_base;
382 payload_size += newVec[i].iov_len = vec[i - header_length].iov_len;
383
384 if (payload_size > LOGGER_ENTRY_MAX_PAYLOAD) {
385 newVec[i].iov_len -= payload_size - LOGGER_ENTRY_MAX_PAYLOAD;
386 if (newVec[i].iov_len) {
387 ++i;
388 }
Mark Salyzynd91ab582014-12-15 10:52:12 -0800389 payload_size = LOGGER_ENTRY_MAX_PAYLOAD;
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700390 break;
391 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800392 }
Mark Salyzynd91ab582014-12-15 10:52:12 -0800393 pmsg_header.len += payload_size;
394
395 if (pstore_fd >= 0) {
396 TEMP_FAILURE_RETRY(writev(pstore_fd, newVec, i));
397 }
398
399 if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */
400 /*
401 * ignore log messages we send to ourself (logd).
402 * Such log messages are often generated by libraries we depend on
403 * which use standard Android logging.
404 */
405 return 0;
406 }
407
408 if (logd_fd < 0) {
409 return -EBADF;
410 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800411
Mark Salyzyn8245af12014-03-25 13:45:33 -0700412 /*
413 * The write below could be lost, but will never block.
414 *
Mark Salyzynd91ab582014-12-15 10:52:12 -0800415 * To logd, we drop the pmsg_header
416 *
Mark Salyzyn8245af12014-03-25 13:45:33 -0700417 * ENOTCONN occurs if logd dies.
418 * EAGAIN occurs if logd is overloaded.
419 */
Mark Salyzynd91ab582014-12-15 10:52:12 -0800420 ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
Mark Salyzyn8245af12014-03-25 13:45:33 -0700421 if (ret < 0) {
422 ret = -errno;
423 if (ret == -ENOTCONN) {
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800424 lock();
Mark Salyzyn0d00a442015-03-13 12:15:57 -0700425 close(logd_fd);
426 logd_fd = -1;
Mark Salyzyn8245af12014-03-25 13:45:33 -0700427 ret = __write_to_log_initialize();
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800428 unlock();
Mark Salyzyn8245af12014-03-25 13:45:33 -0700429
430 if (ret < 0) {
431 return ret;
432 }
433
Mark Salyzynd91ab582014-12-15 10:52:12 -0800434 ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
Mark Salyzyn8245af12014-03-25 13:45:33 -0700435 if (ret < 0) {
436 ret = -errno;
437 }
438 }
439 }
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700440
Mark Salyzyn7a809402015-01-16 13:38:07 -0800441 if (ret > (ssize_t)sizeof(header)) {
442 ret -= sizeof(header);
Mark Salyzynd45d36e2015-02-12 15:14:26 -0800443 } else if (ret == -EAGAIN) {
444 atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800445 if (log_id == LOG_ID_SECURITY) {
446 atomic_fetch_add_explicit(&dropped_security, 1,
447 memory_order_relaxed);
448 }
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700449 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800450#endif
Mark Salyzyn8444eb82014-04-24 09:43:23 -0700451
452 return ret;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800453}
454
Mark Salyzyn154f4602014-02-20 14:59:07 -0800455#if FAKE_LOG_DEVICE
456static const char *LOG_NAME[LOG_ID_MAX] = {
457 [LOG_ID_MAIN] = "main",
458 [LOG_ID_RADIO] = "radio",
459 [LOG_ID_EVENTS] = "events",
Mark Salyzyn99f47a92014-04-07 14:58:08 -0700460 [LOG_ID_SYSTEM] = "system",
Mark Salyzyn440e1092014-10-10 15:13:15 -0700461 [LOG_ID_CRASH] = "crash",
Mark Salyzyn083b0372015-12-04 10:59:45 -0800462 [LOG_ID_SECURITY] = "security",
Mark Salyzyn440e1092014-10-10 15:13:15 -0700463 [LOG_ID_KERNEL] = "kernel",
Mark Salyzyn154f4602014-02-20 14:59:07 -0800464};
465
Adam Lesinskia1ac84c2014-10-20 12:31:30 -0700466const char *android_log_id_to_name(log_id_t log_id)
Mark Salyzyn154f4602014-02-20 14:59:07 -0800467{
468 if (log_id >= LOG_ID_MAX) {
469 log_id = LOG_ID_MAIN;
470 }
471 return LOG_NAME[log_id];
472}
473#endif
474
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800475static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
476{
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800477 lock();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800478
479 if (write_to_log == __write_to_log_init) {
Mark Salyzyn8245af12014-03-25 13:45:33 -0700480 int ret;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800481
Mark Salyzyn8245af12014-03-25 13:45:33 -0700482 ret = __write_to_log_initialize();
483 if (ret < 0) {
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800484 unlock();
Mark Salyzyn0d00a442015-03-13 12:15:57 -0700485#if (FAKE_LOG_DEVICE == 0)
486 if (pstore_fd >= 0) {
487 __write_to_log_daemon(log_id, vec, nr);
488 }
489#endif
Mark Salyzyn8245af12014-03-25 13:45:33 -0700490 return ret;
491 }
492
Mark Salyzyn53016d82015-02-04 12:28:47 -0800493 write_to_log = __write_to_log_daemon;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800494 }
495
Mark Salyzyn2d2e0a52015-11-06 12:26:52 -0800496 unlock();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800497
498 return write_to_log(log_id, vec, nr);
499}
500
501int __android_log_write(int prio, const char *tag, const char *msg)
502{
Dan Albertc7aadc42015-04-02 10:32:44 -0700503 return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800504}
505
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800506int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
507{
508 struct iovec vec[3];
Wink Saville3761e962012-11-28 12:20:19 -0800509 char tmp_tag[32];
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800510
511 if (!tag)
512 tag = "";
513
514 /* XXX: This needs to go! */
Wink Saville3761e962012-11-28 12:20:19 -0800515 if ((bufID != LOG_ID_RADIO) &&
516 (!strcmp(tag, "HTC_RIL") ||
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800517 !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
Jeff Sharkey84dcf092012-08-13 11:27:30 -0700518 !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800519 !strcmp(tag, "AT") ||
520 !strcmp(tag, "GSM") ||
521 !strcmp(tag, "STK") ||
522 !strcmp(tag, "CDMA") ||
523 !strcmp(tag, "PHONE") ||
Wink Saville3761e962012-11-28 12:20:19 -0800524 !strcmp(tag, "SMS"))) {
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800525 bufID = LOG_ID_RADIO;
Mark Salyzyn8245af12014-03-25 13:45:33 -0700526 /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
Wink Saville3761e962012-11-28 12:20:19 -0800527 snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
528 tag = tmp_tag;
529 }
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800530
Dan Albertc7aadc42015-04-02 10:32:44 -0700531#if __BIONIC__
532 if (prio == ANDROID_LOG_FATAL) {
533 android_set_abort_message(msg);
534 }
535#endif
536
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800537 vec[0].iov_base = (unsigned char *) &prio;
538 vec[0].iov_len = 1;
539 vec[1].iov_base = (void *) tag;
540 vec[1].iov_len = strlen(tag) + 1;
541 vec[2].iov_base = (void *) msg;
542 vec[2].iov_len = strlen(msg) + 1;
543
544 return write_to_log(bufID, vec, 3);
545}
546
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800547int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap)
548{
Chris Pearson19299902010-06-02 16:25:35 -0700549 char buf[LOG_BUF_SIZE];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800550
551 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
552
553 return __android_log_write(prio, tag, buf);
554}
555
556int __android_log_print(int prio, const char *tag, const char *fmt, ...)
557{
558 va_list ap;
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800559 char buf[LOG_BUF_SIZE];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800560
561 va_start(ap, fmt);
562 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
563 va_end(ap);
564
565 return __android_log_write(prio, tag, buf);
566}
567
Joe Onoratoe2bf2ea2010-03-01 09:11:54 -0800568int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...)
569{
570 va_list ap;
571 char buf[LOG_BUF_SIZE];
572
573 va_start(ap, fmt);
574 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
575 va_end(ap);
576
577 return __android_log_buf_write(bufID, prio, tag, buf);
578}
579
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800580void __android_log_assert(const char *cond, const char *tag,
Mark Salyzyncf4aa032013-11-22 07:54:30 -0800581 const char *fmt, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800582{
Chris Pearson19299902010-06-02 16:25:35 -0700583 char buf[LOG_BUF_SIZE];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800584
Chris Pearson19299902010-06-02 16:25:35 -0700585 if (fmt) {
586 va_list ap;
587 va_start(ap, fmt);
588 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
589 va_end(ap);
590 } else {
591 /* Msg not provided, log condition. N.B. Do not use cond directly as
592 * format string as it could contain spurious '%' syntax (e.g.
593 * "%d" in "blocks%devs == 0").
594 */
595 if (cond)
596 snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
597 else
598 strcpy(buf, "Unspecified assertion failed");
599 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800600
601 __android_log_write(ANDROID_LOG_FATAL, tag, buf);
Elliott Hughes02ff4b82015-03-07 11:21:37 -0800602 abort(); /* abort so we have a chance to debug the situation */
Elliott Hughesda6b2e22014-04-23 14:57:32 -0700603 /* NOTREACHED */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800604}
605
606int __android_log_bwrite(int32_t tag, const void *payload, size_t len)
607{
608 struct iovec vec[2];
609
610 vec[0].iov_base = &tag;
611 vec[0].iov_len = sizeof(tag);
612 vec[1].iov_base = (void*)payload;
613 vec[1].iov_len = len;
614
615 return write_to_log(LOG_ID_EVENTS, vec, 2);
616}
617
Mark Salyzyn083b0372015-12-04 10:59:45 -0800618int __android_log_security_bwrite(int32_t tag, const void *payload, size_t len)
619{
620 struct iovec vec[2];
621
622 vec[0].iov_base = &tag;
623 vec[0].iov_len = sizeof(tag);
624 vec[1].iov_base = (void*)payload;
625 vec[1].iov_len = len;
626
627 return write_to_log(LOG_ID_SECURITY, vec, 2);
628}
629
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800630/*
631 * Like __android_log_bwrite, but takes the type as well. Doesn't work
632 * for the general case where we're generating lists of stuff, but very
633 * handy if we just want to dump an integer into the log.
634 */
635int __android_log_btwrite(int32_t tag, char type, const void *payload,
Mark Salyzyn154f4602014-02-20 14:59:07 -0800636 size_t len)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800637{
638 struct iovec vec[3];
639
640 vec[0].iov_base = &tag;
641 vec[0].iov_len = sizeof(tag);
642 vec[1].iov_base = &type;
643 vec[1].iov_len = sizeof(type);
644 vec[2].iov_base = (void*)payload;
645 vec[2].iov_len = len;
646
647 return write_to_log(LOG_ID_EVENTS, vec, 3);
648}
Nick Kralevich2a4d05a2014-07-01 10:57:16 -0700649
650/*
651 * Like __android_log_bwrite, but used for writing strings to the
652 * event log.
653 */
654int __android_log_bswrite(int32_t tag, const char *payload)
655{
656 struct iovec vec[4];
657 char type = EVENT_TYPE_STRING;
658 uint32_t len = strlen(payload);
659
660 vec[0].iov_base = &tag;
661 vec[0].iov_len = sizeof(tag);
662 vec[1].iov_base = &type;
663 vec[1].iov_len = sizeof(type);
664 vec[2].iov_base = &len;
665 vec[2].iov_len = sizeof(len);
666 vec[3].iov_base = (void*)payload;
667 vec[3].iov_len = len;
668
669 return write_to_log(LOG_ID_EVENTS, vec, 4);
670}