logd: logcat -L takes longer causing vold to timeout. am: e20e32a72b
am: 366513fc3f
Change-Id: Iab79f34aa6655295672fdd53dca7cef58b2574ee
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 9c68fca..e32f73c 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -24,7 +24,6 @@
]
liblog_host_sources = [
"fake_log_device.c",
- //"event.logtags",
"fake_writer.c",
]
liblog_target_sources = [
@@ -56,7 +55,9 @@
android: {
srcs: liblog_target_sources,
// AddressSanitizer runtime library depends on liblog.
- sanitize: ["never"],
+ sanitize: {
+ never: true,
+ },
},
android_arm: {
// TODO: This is to work around b/24465209. Remove after root cause is fixed
@@ -86,6 +87,7 @@
"-DLIBLOG_LOG_TAG=1005",
"-DSNET_EVENT_LOG_TAG=1397638484",
],
+ logtags: ["event.logtags"],
compile_multilib: "both",
stl: "none",
}
diff --git a/liblog/Android.mk b/liblog/Android.mk
index b24b489..6c4dff5 100644
--- a/liblog/Android.mk
+++ b/liblog/Android.mk
@@ -1,85 +1,3 @@
-#
-# Copyright (C) 2008-2014 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.
-#
LOCAL_PATH := $(my-dir)
-include $(CLEAR_VARS)
-
-# This is what we want to do:
-# liblog_cflags := $(shell \
-# sed -n \
-# 's/^\([0-9]*\)[ \t]*liblog[ \t].*/-DLIBLOG_LOG_TAG=\1/p' \
-# $(LOCAL_PATH)/event.logtags)
-# so make sure we do not regret hard-coding it as follows:
-liblog_cflags := -DLIBLOG_LOG_TAG=1005
-liblog_cflags += -DSNET_EVENT_LOG_TAG=1397638484
-
-liblog_sources := log_event_list.c log_event_write.c logger_write.c
-liblog_sources += config_write.c logger_name.c logger_lock.c
-liblog_host_sources := $(liblog_sources) fake_log_device.c event.logtags
-liblog_host_sources += fake_writer.c
-liblog_target_sources := $(liblog_sources) event_tag_map.c
-liblog_target_sources += config_read.c log_time.cpp log_is_loggable.c logprint.c
-liblog_target_sources += pmsg_reader.c pmsg_writer.c
-liblog_target_sources += logd_reader.c logd_writer.c logger_read.c
-
-# Shared and static library for host
-# ========================================================
-LOCAL_MODULE := liblog
-LOCAL_SRC_FILES := $(liblog_host_sources)
-# some files must not be compiled when building against Mingw
-# they correspond to features not used by our host development tools
-# which are also hard or even impossible to port to native Win32
-LOCAL_SRC_FILES_darwin := event_tag_map.c
-LOCAL_SRC_FILES_linux := event_tag_map.c
-LOCAL_SRC_FILES_windows := uio.c
-LOCAL_CFLAGS := -DFAKE_LOG_DEVICE=1 -Werror -fvisibility=hidden $(liblog_cflags)
-LOCAL_MULTILIB := both
-LOCAL_MODULE_HOST_OS := darwin linux windows
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := liblog
-LOCAL_WHOLE_STATIC_LIBRARIES := liblog
-LOCAL_LDLIBS_linux := -lrt
-LOCAL_MULTILIB := both
-LOCAL_CXX_STL := none
-LOCAL_MODULE_HOST_OS := darwin linux windows
-include $(BUILD_HOST_SHARED_LIBRARY)
-
-
-# Shared and static library for target
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := liblog
-LOCAL_SRC_FILES := $(liblog_target_sources)
-LOCAL_CFLAGS := -Werror -fvisibility=hidden $(liblog_cflags)
-# AddressSanitizer runtime library depends on liblog.
-LOCAL_SANITIZE := never
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := liblog
-LOCAL_WHOLE_STATIC_LIBRARIES := liblog
-LOCAL_CFLAGS := -Werror -fvisibility=hidden $(liblog_cflags)
-
-# TODO: This is to work around b/24465209. Remove after root cause is fixed
-LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
-
-LOCAL_SANITIZE := never
-LOCAL_CXX_STL := none
-
-include $(BUILD_SHARED_LIBRARY)
include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/liblog/config_read.h b/liblog/config_read.h
index 67f4c20..49a3b75 100644
--- a/liblog/config_read.h
+++ b/liblog/config_read.h
@@ -27,21 +27,21 @@
extern LIBLOG_HIDDEN struct listnode __android_log_persist_read;
#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); \
- (transp != node_to_item(transports, \
+ ((transp) != node_to_item(transports, \
struct android_log_transport_read, node)); \
- transp = node_to_item(transp->node.next, \
+ (transp) = node_to_item((transp)->node.next, \
struct android_log_transport_read, node)) \
#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), \
- n = transp->node.next; \
- (transp != node_to_item(transports, \
+ (n) = (transp)->node.next; \
+ ((transp) != node_to_item(transports, \
struct android_log_transport_read, node)); \
- transp = node_to_item(n, struct android_log_transport_read, node), \
- n = transp->node.next)
+ (transp) = node_to_item(n, struct android_log_transport_read, node), \
+ (n) = (transp)->node.next)
LIBLOG_HIDDEN void __android_log_config_read();
diff --git a/liblog/config_write.h b/liblog/config_write.h
index 3a02a4e..3b01a9a 100644
--- a/liblog/config_write.h
+++ b/liblog/config_write.h
@@ -27,21 +27,21 @@
extern LIBLOG_HIDDEN struct listnode __android_log_persist_write;
#define write_transport_for_each(transp, transports) \
- for (transp = node_to_item((transports)->next, \
- struct android_log_transport_write, node); \
- (transp != node_to_item(transports, \
+ for ((transp) = node_to_item((transports)->next, \
+ struct android_log_transport_write, node); \
+ ((transp) != node_to_item(transports, \
struct android_log_transport_write, node)); \
- transp = node_to_item(transp->node.next, \
- 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) \
- for (transp = node_to_item((transports)->next, \
- struct android_log_transport_write, node), \
- n = transp->node.next; \
- (transp != node_to_item(transports, \
- struct android_log_transport_write, node)); \
- transp = node_to_item(n, struct android_log_transport_write, node), \
- n = transp->node.next)
+ for ((transp) = node_to_item((transports)->next, \
+ struct android_log_transport_write, node), \
+ (n) = (transp)->node.next; \
+ ((transp) != node_to_item(transports, \
+ struct android_log_transport_write, node)); \
+ (transp) = node_to_item(n, struct android_log_transport_write, node), \
+ (n) = (transp)->node.next)
LIBLOG_HIDDEN void __android_log_config_write();
diff --git a/liblog/logger.h b/liblog/logger.h
index 0964756..2a4cfcb 100644
--- a/liblog/logger.h
+++ b/liblog/logger.h
@@ -124,23 +124,23 @@
/* assumes caller has structures read-locked, single threaded, or fenced */
#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, \
node); \
- (transp != node_to_item(&(logger_list)->transport, \
+ ((transp) != node_to_item(&(logger_list)->transport, \
struct android_log_transport_context, \
node)) && \
- (transp->parent == (logger_list)); \
- transp = node_to_item(transp->node.next, \
+ ((transp)->parent == (logger_list)); \
+ (transp) = node_to_item((transp)->node.next, \
struct android_log_transport_context, node))
#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); \
- (logp != node_to_item(&(logger_list)->logger, \
+ ((logp) != node_to_item(&(logger_list)->logger, \
struct android_log_logger, node)) && \
- (logp->parent == (logger_list)); \
- logp = node_to_item((logp)->node.next, \
+ ((logp)->parent == (logger_list)); \
+ (logp) = node_to_item((logp)->node.next, \
struct android_log_logger, node))
/* OS specific dribs and drabs */
diff --git a/liblog/logger_read.c b/liblog/logger_read.c
index 0d6ba08..00157b7 100644
--- a/liblog/logger_read.c
+++ b/liblog/logger_read.c
@@ -125,7 +125,7 @@
ssize_t ret = -EINVAL; \
struct android_log_transport_context *transp; \
struct android_log_logger *logger_internal = \
- (struct android_log_logger *)logger; \
+ (struct android_log_logger *)(logger); \
\
if (!logger_internal) { \
return ret; \
@@ -186,7 +186,7 @@
#define LOGGER_LIST_FUNCTION(logger_list, def, func, args...) \
struct android_log_transport_context *transp; \
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); \
if (ret < 0) { \
@@ -341,6 +341,43 @@
return logger_list;
}
+/* Validate log_msg packet, read function has already been null checked */
+static int android_transport_read(struct android_log_logger_list *logger_list,
+ struct android_log_transport_context *transp,
+ struct log_msg *log_msg)
+{
+ int ret = (*transp->transport->read)(logger_list, transp, log_msg);
+
+ if (ret > (int)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;
+ }
+ 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);
+ }
+
+ /* 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 */
LIBLOG_ABI_PUBLIC int android_logger_list_read(struct logger_list *logger_list,
struct log_msg *log_msg)
@@ -378,7 +415,7 @@
} else if ((logger_list_internal->mode &
ANDROID_LOG_NONBLOCK) ||
!transp->transport->poll) {
- retval = transp->ret = (*transp->transport->read)(
+ retval = android_transport_read(
logger_list_internal,
transp,
&transp->logMsg);
@@ -397,7 +434,7 @@
}
retval = transp->ret = pollval;
} else if (pollval > 0) {
- retval = transp->ret = (*transp->transport->read)(
+ retval = android_transport_read(
logger_list_internal,
transp,
&transp->logMsg);
@@ -434,16 +471,22 @@
if (!oldest) {
return ret;
}
- memcpy(log_msg, &oldest->logMsg, oldest->logMsg.entry.len +
- (oldest->logMsg.entry.hdr_size ?
- oldest->logMsg.entry.hdr_size :
- sizeof(struct logger_entry)));
+ // 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 oldest->ret;
+ return ret;
}
/* if only one, no need to copy into transport_context and merge-sort */
- return (transp->transport->read)(logger_list_internal, transp, log_msg);
+ return android_transport_read(logger_list_internal, transp, log_msg);
}
/* Close all the logs */
diff --git a/liblog/logprint.c b/liblog/logprint.c
index c8457f4..59bd479 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -21,6 +21,7 @@
#include <assert.h>
#include <ctype.h>
#include <errno.h>
+#include <pwd.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
@@ -28,11 +29,11 @@
#include <string.h>
#include <inttypes.h>
#include <sys/param.h>
+#include <sys/types.h>
#include <cutils/list.h>
#include <log/logd.h>
#include <log/logprint.h>
-#include <private/android_filesystem_config.h>
#include "log_portability.h"
@@ -1352,17 +1353,17 @@
uid[0] = '\0';
if (p_format->uid_output) {
if (entry->uid >= 0) {
- const struct android_id_info *info = android_ids;
- size_t i;
- for (i = 0; i < android_id_count; ++i) {
- if (info->aid == (unsigned int)entry->uid) {
- break;
- }
- ++info;
- }
- if ((i < android_id_count) && (strlen(info->name) <= 5)) {
- snprintf(uid, sizeof(uid), "%5s:", info->name);
+ /*
+ * This code is Android specific, bionic guarantees that
+ * calls to non-reentrant getpwuid() are thread safe.
+ */
+#ifndef __BIONIC__
+#warning "This code assumes that getpwuid is thread safe, only true with Bionic!"
+#endif
+ struct passwd* pwd = getpwuid(entry->uid);
+ if (pwd && (strlen(pwd->pw_name) <= 5)) {
+ snprintf(uid, sizeof(uid), "%5s:", pwd->pw_name);
} else {
// Not worth parsing package list, names all longer than 5
snprintf(uid, sizeof(uid), "%5d:", entry->uid);
diff --git a/liblog/pmsg_reader.c b/liblog/pmsg_reader.c
index 2e4fc5d..a4eec65 100644
--- a/liblog/pmsg_reader.c
+++ b/liblog/pmsg_reader.c
@@ -144,6 +144,7 @@
struct __attribute__((__packed__)) {
android_pmsg_log_header_t p;
android_log_header_t l;
+ uint8_t prio;
} buf;
static uint8_t preread_count;
bool is_system;
@@ -180,11 +181,16 @@
if (preread_count != sizeof(buf)) {
return preread_count ? -EIO : -EAGAIN;
}
- if ((buf.p.magic != LOGGER_MAGIC)
- || (buf.p.len <= sizeof(buf))
- || (buf.p.len > (sizeof(buf) + LOGGER_ENTRY_MAX_PAYLOAD))
- || (buf.l.id >= LOG_ID_MAX)
- || (buf.l.realtime.tv_nsec >= NS_PER_SEC)) {
+ if ((buf.p.magic != LOGGER_MAGIC) ||
+ (buf.p.len <= sizeof(buf)) ||
+ (buf.p.len > (sizeof(buf) + LOGGER_ENTRY_MAX_PAYLOAD)) ||
+ (buf.l.id >= LOG_ID_MAX) ||
+ (buf.l.realtime.tv_nsec >= NS_PER_SEC) ||
+ ((buf.l.id != LOG_ID_EVENTS) &&
+ (buf.l.id != LOG_ID_SECURITY) &&
+ ((buf.prio == ANDROID_LOG_UNKNOWN) ||
+ (buf.prio == ANDROID_LOG_DEFAULT) ||
+ (buf.prio >= ANDROID_LOG_SILENT)))) {
do {
memmove(&buf.p.magic, &buf.p.magic + 1, --preread_count);
} while (preread_count && (buf.p.magic != LOGGER_MAGIC));
@@ -202,10 +208,12 @@
uid = get_best_effective_uid();
is_system = uid_has_log_permission(uid);
if (is_system || (uid == buf.p.uid)) {
+ char *msg = is_system ?
+ log_msg->entry_v4.msg :
+ log_msg->entry_v3.msg;
+ *msg = buf.prio;
ret = TEMP_FAILURE_RETRY(read(transp->context.fd,
- is_system ?
- log_msg->entry_v4.msg :
- log_msg->entry_v3.msg,
+ msg + sizeof(buf.prio),
buf.p.len - sizeof(buf)));
if (ret < 0) {
return -errno;
@@ -214,7 +222,7 @@
return -EIO;
}
- log_msg->entry_v4.len = buf.p.len - sizeof(buf);
+ log_msg->entry_v4.len = buf.p.len - sizeof(buf) + sizeof(buf.prio);
log_msg->entry_v4.hdr_size = is_system ?
sizeof(log_msg->entry_v4) :
sizeof(log_msg->entry_v3);
@@ -227,7 +235,7 @@
log_msg->entry_v4.uid = buf.p.uid;
}
- return ret + log_msg->entry_v4.hdr_size;
+ return ret + sizeof(buf.prio) + log_msg->entry_v4.hdr_size;
}
}
diff --git a/liblog/tests/benchmark.h b/liblog/tests/benchmark.h
index 7f96e6d..e9280f6 100644
--- a/liblog/tests/benchmark.h
+++ b/liblog/tests/benchmark.h
@@ -38,7 +38,7 @@
Benchmark(const char* name, void (*fn)(int)) : name_(strdup(name)), fn_(fn) {
BenchmarkRegister(this);
}
- Benchmark(const char* name) : name_(strdup(name)), fn_(NULL) {}
+ explicit Benchmark(const char* name) : name_(strdup(name)), fn_(NULL) {}
virtual ~Benchmark() {
free(name_);
@@ -141,7 +141,7 @@
void StopBenchmarkTiming(uint64_t);
#define BENCHMARK(f) \
- static ::testing::Benchmark* _benchmark_##f __attribute__((unused)) = \
- (::testing::Benchmark*)::testing::BenchmarkFactory(#f, f)
+ static ::testing::Benchmark* _benchmark_##f __attribute__((unused)) = /* NOLINT */ \
+ (::testing::Benchmark*)::testing::BenchmarkFactory(#f, f) /* NOLINT */
#endif // BIONIC_BENCHMARK_H_
diff --git a/liblog/tests/libc_test.cpp b/liblog/tests/libc_test.cpp
index 9dd6f03..3d58147 100644
--- a/liblog/tests/libc_test.cpp
+++ b/liblog/tests/libc_test.cpp
@@ -14,126 +14,9 @@
* limitations under the License.
*/
-#include <fcntl.h>
-#include <sys/cdefs.h>
-
#include <gtest/gtest.h>
-// Should be in bionic test suite, *but* we are using liblog to confirm
-// end-to-end logging, so let the overly cute oedipus complex begin ...
-#include "../../../../bionic/libc/bionic/libc_logging.cpp" // not Standalone
-#define _ANDROID_LOG_H // Priorities redefined
-#define _LIBS_LOG_LOG_H // log ids redefined
-typedef unsigned char log_id_t; // log_id_t missing as a result
-#define _LIBS_LOG_LOG_READ_H // log_time redefined
-
-#include <log/log.h>
-#include <log/logger.h>
-#include <log/log_read.h>
-
-TEST(libc, __libc_android_log_event_int) {
- struct logger_list *logger_list;
-
- pid_t pid = getpid();
-
- ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- int value = ts.tv_nsec;
-
- __libc_android_log_event_int(0, value);
- usleep(1000000);
-
- int count = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- ASSERT_EQ(log_msg.entry.pid, pid);
-
- if ((log_msg.entry.len != (4 + 1 + 4))
- || ((int)log_msg.id() != LOG_ID_EVENTS)) {
- continue;
- }
-
- char *eventData = log_msg.msg();
-
- int incoming = (eventData[0] & 0xFF) |
- ((eventData[1] & 0xFF) << 8) |
- ((eventData[2] & 0xFF) << 16) |
- ((eventData[3] & 0xFF) << 24);
-
- if (incoming != 0) {
- continue;
- }
-
- if (eventData[4] != EVENT_TYPE_INT) {
- continue;
- }
-
- incoming = (eventData[4 + 1 + 0] & 0xFF) |
- ((eventData[4 + 1 + 1] & 0xFF) << 8) |
- ((eventData[4 + 1 + 2] & 0xFF) << 16) |
- ((eventData[4 + 1 + 3] & 0xFF) << 24);
-
- if (incoming == value) {
- ++count;
- }
- }
-
- EXPECT_EQ(1, count);
-
- android_logger_list_close(logger_list);
-}
-
-TEST(libc, __libc_fatal_no_abort) {
- struct logger_list *logger_list;
-
- pid_t pid = getpid();
-
- ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- (log_id_t)LOG_ID_CRASH, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
- char b[80];
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
-
- __libc_fatal_no_abort("%u.%09u", (unsigned)ts.tv_sec, (unsigned)ts.tv_nsec);
- snprintf(b, sizeof(b),"%u.%09u", (unsigned)ts.tv_sec, (unsigned)ts.tv_nsec);
- usleep(1000000);
-
- int count = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- ASSERT_EQ(log_msg.entry.pid, pid);
-
- if ((int)log_msg.id() != LOG_ID_CRASH) {
- continue;
- }
-
- char *data = log_msg.msg();
-
- if ((*data == ANDROID_LOG_FATAL)
- && !strcmp(data + 1, "libc")
- && !strcmp(data + 1 + strlen(data + 1) + 1, b)) {
- ++count;
- }
- }
-
- EXPECT_EQ(1, count);
-
- android_logger_list_close(logger_list);
-}
+#include <stdio.h>
TEST(libc, __pstore_append) {
FILE *fp;
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 01fb50f..1b66a56 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -205,7 +205,7 @@
android_log_header_t header;
android_log_event_int_t payload;
};
- char buf[sizeof(struct packet) + 8] __aligned(8);
+ alignas(8) char buf[sizeof(struct packet) + 8];
memset(buf, 0, sizeof(buf));
struct packet *buffer = (struct packet*)(((uintptr_t)buf + 7) & ~7);
if (((uintptr_t)&buffer->pmsg_header) & 7) {
@@ -281,7 +281,7 @@
android_log_header_t header;
android_log_event_int_t payload;
};
- char buf[sizeof(struct packet) + 8] __aligned(8);
+ alignas(8) char buf[sizeof(struct packet) + 8];
memset(buf, 0, sizeof(buf));
struct packet *buffer = (struct packet*)((((uintptr_t)buf + 7) & ~7) + 1);
if ((((uintptr_t)&buffer->pmsg_header) & 7) != 1) {
@@ -357,7 +357,7 @@
android_log_header_t header;
android_log_event_int_t payload;
};
- char buf[sizeof(struct packet) + 8 + LOGGER_ENTRY_MAX_PAYLOAD] __aligned(8);
+ alignas(8) char buf[sizeof(struct packet) + 8 + LOGGER_ENTRY_MAX_PAYLOAD];
memset(buf, 0, sizeof(buf));
struct packet *buffer = (struct packet*)(((uintptr_t)buf + 7) & ~7);
if (((uintptr_t)&buffer->pmsg_header) & 7) {
@@ -430,7 +430,7 @@
android_log_header_t header;
android_log_event_int_t payload;
};
- char buf[sizeof(struct packet) + 8 + LOGGER_ENTRY_MAX_PAYLOAD] __aligned(8);
+ alignas(8) char buf[sizeof(struct packet) + 8 + LOGGER_ENTRY_MAX_PAYLOAD];
memset(buf, 0, sizeof(buf));
struct packet *buffer = (struct packet*)((((uintptr_t)buf + 7) & ~7) + 1);
if ((((uintptr_t)&buffer->pmsg_header) & 7) != 1) {
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 6aa4fb7..df2c766 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -174,7 +174,7 @@
return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
}
-TEST(liblog, __android_log_bswrite) {
+static void bswrite_test(const char *message) {
struct logger_list *logger_list;
pid_t pid = getpid();
@@ -182,10 +182,30 @@
ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
- static const char buffer[] = "Hello World";
log_time ts(android_log_clockid());
- ASSERT_LT(0, __android_log_bswrite(0, buffer));
+ ASSERT_LT(0, __android_log_bswrite(0, message));
+ size_t num_lines = 1, size = 0, length = 0, total = 0;
+ const char *cp = message;
+ while (*cp) {
+ if (*cp == '\n') {
+ if (cp[1]) {
+ ++num_lines;
+ }
+ } else {
+ ++size;
+ }
+ ++cp;
+ ++total;
+ ++length;
+ if ((LOGGER_ENTRY_MAX_PAYLOAD - 4 - 1 - 4) <= length) {
+ break;
+ }
+ }
+ while (*cp) {
+ ++cp;
+ ++total;
+ }
usleep(1000000);
int count = 0;
@@ -200,7 +220,7 @@
if ((log_msg.entry.sec < (ts.tv_sec - 1))
|| ((ts.tv_sec + 1) < log_msg.entry.sec)
- || (log_msg.entry.len != (4 + 1 + 4 + sizeof(buffer) - 1))
+ || ((size_t)log_msg.entry.len != (4 + 1 + 4 + length))
|| (log_msg.id() != LOG_ID_EVENTS)) {
continue;
}
@@ -211,21 +231,22 @@
continue;
}
- int len = get4LE(eventData + 4 + 1);
- if (len == (sizeof(buffer) - 1)) {
+ size_t len = get4LE(eventData + 4 + 1);
+ if (len == total) {
++count;
AndroidLogFormat *logformat = android_log_format_new();
EXPECT_TRUE(NULL != logformat);
AndroidLogEntry entry;
char msgBuf[1024];
- EXPECT_EQ(0, android_log_processBinaryLogBuffer(&log_msg.entry_v1,
- &entry,
- NULL,
- msgBuf,
- sizeof(msgBuf)));
- fflush(stderr);
- EXPECT_EQ(31, android_log_printLogLine(logformat, fileno(stderr), &entry));
+ int processBinaryLogBuffer = android_log_processBinaryLogBuffer(
+ &log_msg.entry_v1, &entry, NULL, msgBuf, sizeof(msgBuf));
+ EXPECT_EQ((length == total) ? 0 : -1, processBinaryLogBuffer);
+ if (processBinaryLogBuffer == 0) {
+ fflush(stderr);
+ EXPECT_EQ((int)((20 * num_lines) + size),
+ android_log_printLogLine(logformat, fileno(stderr), &entry));
+ }
android_log_format_free(logformat);
}
}
@@ -235,18 +256,55 @@
android_logger_list_close(logger_list);
}
-TEST(liblog, __android_log_bswrite__empty_string) {
+TEST(liblog, __android_log_bswrite_and_print) {
+ bswrite_test("Hello World");
+}
+
+TEST(liblog, __android_log_bswrite_and_print__empty_string) {
+ bswrite_test("");
+}
+
+TEST(liblog, __android_log_bswrite_and_print__newline_prefix) {
+ bswrite_test("\nHello World\n");
+}
+
+TEST(liblog, __android_log_bswrite_and_print__newline_space_prefix) {
+ bswrite_test("\n Hello World \n");
+}
+
+TEST(liblog, __android_log_bswrite_and_print__multiple_newline) {
+ bswrite_test("one\ntwo\nthree\nfour\nfive\nsix\nseven\neight\nnine\nten");
+}
+
+static void buf_write_test(const char *message) {
struct logger_list *logger_list;
pid_t pid = getpid();
ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
+ LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
- static const char buffer[] = "";
+ static const char tag[] = "TEST__android_log_buf_write";
log_time ts(android_log_clockid());
- ASSERT_LT(0, __android_log_bswrite(0, buffer));
+ EXPECT_LT(0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO,
+ tag, message));
+ size_t num_lines = 1, size = 0, length = 0;
+ const char *cp = message;
+ while (*cp) {
+ if (*cp == '\n') {
+ if (cp[1]) {
+ ++num_lines;
+ }
+ } else {
+ ++size;
+ }
+ ++length;
+ if ((LOGGER_ENTRY_MAX_PAYLOAD - 2 - sizeof(tag)) <= length) {
+ break;
+ }
+ ++cp;
+ }
usleep(1000000);
int count = 0;
@@ -261,34 +319,25 @@
if ((log_msg.entry.sec < (ts.tv_sec - 1))
|| ((ts.tv_sec + 1) < log_msg.entry.sec)
- || (log_msg.entry.len != (4 + 1 + 4))
- || (log_msg.id() != LOG_ID_EVENTS)) {
+ || ((size_t)log_msg.entry.len != (sizeof(tag) + length + 2))
+ || (log_msg.id() != LOG_ID_MAIN)) {
continue;
}
- char *eventData = log_msg.msg();
+ ++count;
- if (eventData[4] != EVENT_TYPE_STRING) {
- continue;
- }
-
- int len = get4LE(eventData + 4 + 1);
- if (len == 0) {
- ++count;
-
- AndroidLogFormat *logformat = android_log_format_new();
- EXPECT_TRUE(NULL != logformat);
- AndroidLogEntry entry;
- char msgBuf[1024];
- EXPECT_EQ(0, android_log_processBinaryLogBuffer(&log_msg.entry_v1,
- &entry,
- NULL,
- msgBuf,
- sizeof(msgBuf)));
+ AndroidLogFormat *logformat = android_log_format_new();
+ EXPECT_TRUE(NULL != logformat);
+ AndroidLogEntry entry;
+ int processLogBuffer = android_log_processLogBuffer(&log_msg.entry_v1,
+ &entry);
+ EXPECT_EQ(0, processLogBuffer);
+ if (processLogBuffer == 0) {
fflush(stderr);
- EXPECT_EQ(20, android_log_printLogLine(logformat, fileno(stderr), &entry));
- android_log_format_free(logformat);
+ EXPECT_EQ((int)(((11 + sizeof(tag)) * num_lines) + size),
+ android_log_printLogLine(logformat, fileno(stderr), &entry));
}
+ android_log_format_free(logformat);
}
EXPECT_EQ(1, count);
@@ -296,6 +345,18 @@
android_logger_list_close(logger_list);
}
+TEST(liblog, __android_log_buf_write_and_print__empty) {
+ buf_write_test("");
+}
+
+TEST(liblog, __android_log_buf_write_and_print__newline_prefix) {
+ buf_write_test("\nHello World\n");
+}
+
+TEST(liblog, __android_log_buf_write_and_print__newline_space_prefix) {
+ buf_write_test("\n Hello World \n");
+}
+
TEST(liblog, __security) {
static const char persist_key[] = "persist.logd.security";
static const char readonly_key[] = "ro.device_owner";
@@ -767,7 +828,7 @@
EXPECT_GT(one_percent_ticks, user_ticks + system_ticks);
}
-static const char max_payload_tag[] = "TEST_max_payload_XXXX";
+static const char max_payload_tag[] = "TEST_max_payload_and_longish_tag_XXXX";
#define SIZEOF_MAX_PAYLOAD_BUF (LOGGER_ENTRY_MAX_PAYLOAD - \
sizeof(max_payload_tag) - 1)
static const char max_payload_buf[] = "LEONATO\n\
@@ -1307,6 +1368,7 @@
snprintf(key, sizeof(key), "%s%s", log_namespace, tag);
fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
i, j, key, buf);
+ usleep(20000);
property_set(key, buf);
bool android_log_is_loggable = __android_log_is_loggable(
levels[i].level, tag, ANDROID_LOG_DEBUG);
@@ -1332,6 +1394,7 @@
levels[i].level, tag, ANDROID_LOG_DEBUG));
}
}
+ usleep(20000);
property_set(key, "");
fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
@@ -1361,6 +1424,7 @@
levels[i].level, tag, ANDROID_LOG_DEBUG));
}
}
+ usleep(20000);
property_set(key + base_offset, "");
strcpy(key, log_namespace);
@@ -1392,6 +1456,7 @@
levels[i].level, tag, ANDROID_LOG_DEBUG));
}
}
+ usleep(20000);
property_set(key, "");
fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
@@ -1421,6 +1486,7 @@
levels[i].level, tag, ANDROID_LOG_DEBUG));
}
}
+ usleep(20000);
property_set(key + base_offset, "");
}
}
@@ -1428,6 +1494,7 @@
// All combinations of level and tag properties, but with global set to INFO
strcpy(key, log_namespace);
key[sizeof(log_namespace) - 2] = '\0';
+ usleep(20000);
property_set(key, "I");
snprintf(key, sizeof(key), "%s%s", log_namespace, tag);
for(size_t i = 0; i < (sizeof(levels) / sizeof(levels[0])); ++i) {
@@ -1441,6 +1508,7 @@
fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
i, j, key, buf);
+ usleep(20000);
property_set(key, buf);
bool android_log_is_loggable = __android_log_is_loggable(
levels[i].level, tag, ANDROID_LOG_DEBUG);
@@ -1466,6 +1534,7 @@
levels[i].level, tag, ANDROID_LOG_DEBUG));
}
}
+ usleep(20000);
property_set(key, "");
fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
@@ -1495,12 +1564,14 @@
levels[i].level, tag, ANDROID_LOG_DEBUG));
}
}
+ usleep(20000);
property_set(key + base_offset, "");
}
}
// reset parms
snprintf(key, sizeof(key), "%s%s", log_namespace, tag);
+ usleep(20000);
property_set(key, hold[0]);
property_set(key + base_offset, hold[1]);
strcpy(key, log_namespace);
@@ -1802,6 +1873,14 @@
android_logger_list_close(logger_list);
}
+TEST(liblog, __android_log_bswrite_and_print___max) {
+ bswrite_test(max_payload_buf);
+}
+
+TEST(liblog, __android_log_buf_write_and_print__max) {
+ buf_write_test(max_payload_buf);
+}
+
TEST(liblog, android_errorWriteLog__android_logger_list_read__success) {
const int TAG = 123456785;
const char SUBTAG[] = "test-subtag";
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 33f22dd..5bac717 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -35,7 +35,7 @@
#include <log/logd.h>
#include <log/logger.h>
#include <log/logprint.h>
-#include <utils/threads.h>
+#include <system/thread_defs.h>
#include <pcrecpp.h>
@@ -285,9 +285,10 @@
" -n <count>, --rotate-count=<count>\n"
" Sets max number of rotated logs to <count>, default 4\n"
" -v <format>, --format=<format>\n"
- " Sets the log print format, where <format> is:\n"
- " brief color epoch long monotonic printable process raw\n"
- " tag thread threadtime time uid usec UTC year zone\n"
+ " Sets log print format verb and adverbs, where <format> is:\n"
+ " brief long process raw tag thread threadtime time\n"
+ " and individually flagged modifying adverbs can be added:\n"
+ " color epoch monotonic printable uid usec UTC year zone\n"
" -D, --dividers Print dividers between each log buffer\n"
" -c, --clear Clear (flush) the entire log and exit\n"
" if Log to File specified, clear fileset instead\n"
@@ -392,7 +393,7 @@
}
/*String to unsigned int, returns -1 if it fails*/
-static bool getSizeTArg(char *ptr, size_t *val, size_t min = 0,
+static bool getSizeTArg(const char *ptr, size_t *val, size_t min = 0,
size_t max = SIZE_MAX)
{
if (!ptr) {
diff --git a/logcat/logpersist b/logcat/logpersist
index a0e27ce..f0e7d42 100755
--- a/logcat/logpersist
+++ b/logcat/logpersist
@@ -1,8 +1,8 @@
#! /system/bin/sh
# logpersist cat, start and stop handlers
progname="${0##*/}"
-case `getprop ro.build.type` in
-userdebug|eng) ;;
+case `getprop ro.debuggable` in
+1) ;;
*) echo "${progname} - Permission denied"
exit 1
;;
@@ -17,6 +17,7 @@
;;
esac
+log_tag_property=persist.log.tag
data=/data/misc/logd
service=logcatd
size_default=256
@@ -36,7 +37,7 @@
-b|--buffer) buffer="${2}" ; shift ;;
-h|--help|*)
LEAD_SPACE_="`echo ${progname%.*} | tr '[ -~]' ' '`"
- echo "${progname%.*}.cat - dump current ${service%d} logs"
+ echo "${progname%.*}.cat - dump current ${service} logs"
echo "${progname%.*}.start [--size=<size_in_kb>] [--buffer=<buffers>] [--clear]"
echo "${LEAD_SPACE_} - start ${service} service"
echo "${progname%.*}.stop [--clear] - stop ${service} service"
@@ -65,6 +66,9 @@
exit 1
fi
+log_tag="`getprop ${log_tag_property}`"
+logd_logpersistd="`getprop ${property}`"
+
case ${progname} in
*.cat)
if [ -n "${size}${buffer}" -o "true" = "${clear}" ]; then
@@ -123,13 +127,19 @@
while [ "clear" = "`getprop ${property#persist.}`" ]; do
continue
done
+ # Tell Settings that we are back on again if we turned logging off
+ tag="${log_tag#Settings}"
+ if [ X"${log_tag}" != X"${tag}" ]; then
+ echo "WARNING: enabling logd service" >&2
+ setprop ${log_tag_property} "${tag#,}"
+ fi
# ${service}.rc does the heavy lifting with the following trigger
setprop ${property} ${service}
# 20ms done, to permit process feedback check
sleep 1
getprop ${property#persist.}
- # also generate an error return code if not found running, bonus
- ps -t | grep "${data##*/}.*${service%d}"
+ # also generate an error return code if not found running
+ pgrep -u ${data##*/} ${service%d}
;;
*.stop)
if [ -n "${size}${buffer}" ]; then
@@ -158,3 +168,9 @@
echo "ERROR: Unexpected command ${0##*/} ${args}" >&2
exit 1
esac
+
+if [ X"${log_tag}" != X"`getprop ${log_tag_property}`" ] ||
+ [ X"${logd_logpersistd}" != X"`getprop ${property}`" ]; then
+ echo "WARNING: killing Settings" >&2
+ am force-stop com.android.settings
+fi
diff --git a/logcat/tests/logcat_benchmark.cpp b/logcat/tests/logcat_benchmark.cpp
index be815be..dd85164 100644
--- a/logcat/tests/logcat_benchmark.cpp
+++ b/logcat/tests/logcat_benchmark.cpp
@@ -49,7 +49,7 @@
}
}
- timestamp(const char *buffer)
+ explicit timestamp(const char *buffer)
{
init(buffer);
}
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index d79fc08..0043d1b 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -23,6 +23,8 @@
#include <sys/types.h>
#include <sys/wait.h>
+#include <memory>
+
#include <gtest/gtest.h>
#include <log/log.h>
#include <log/logger.h>
@@ -724,8 +726,8 @@
EXPECT_FALSE(system(command));
return;
}
- DIR *dir;
- EXPECT_TRUE(NULL != (dir = opendir(tmp_out_dir)));
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir), closedir);
+ EXPECT_NE(nullptr, dir);
if (!dir) {
snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
EXPECT_FALSE(system(command));
@@ -733,7 +735,7 @@
}
struct dirent *entry;
unsigned count = 0;
- while ((entry = readdir(dir))) {
+ while ((entry = readdir(dir.get()))) {
if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) {
continue;
}
@@ -756,7 +758,6 @@
free(line);
unlink(command);
}
- closedir(dir);
if (count > 1) {
char *brk = strpbrk(second_last_line, "\r\n");
if (!brk) {
@@ -876,12 +877,14 @@
ASSERT_TRUE(NULL != (fp = popen(
"( trap exit HUP QUIT INT PIPE KILL ; sleep 6; echo DONE )&"
" logcat -b events -c 2>&1 ;"
+ " logcat -b events -g 2>&1 ;"
" logcat -v brief -b events 2>&1",
"r")));
char buffer[BIG_BUFFER];
int count = 0;
+ int minus_g = 0;
int signals = 0;
@@ -899,6 +902,50 @@
break;
}
+ int size, consumed, max, payload;
+ char size_mult[3], consumed_mult[3];
+ size = consumed = max = payload = 0;
+ if (6 == sscanf(buffer, "events: ring buffer is %d%2s (%d%2s consumed),"
+ " max entry is %db, max payload is %db",
+ &size, size_mult, &consumed, consumed_mult,
+ &max, &payload)) {
+ long full_size = size, full_consumed = consumed;
+
+ switch(size_mult[0]) {
+ case 'G':
+ full_size *= 1024;
+ /* FALLTHRU */
+ case 'M':
+ full_size *= 1024;
+ /* FALLTHRU */
+ case 'K':
+ full_size *= 1024;
+ /* FALLTHRU */
+ case 'b':
+ break;
+ }
+ switch(consumed_mult[0]) {
+ case 'G':
+ full_consumed *= 1024;
+ /* FALLTHRU */
+ case 'M':
+ full_consumed *= 1024;
+ /* FALLTHRU */
+ case 'K':
+ full_consumed *= 1024;
+ /* FALLTHRU */
+ case 'b':
+ break;
+ }
+ EXPECT_GT(full_size, full_consumed);
+ EXPECT_GT(full_size, max);
+ EXPECT_GT(max, payload);
+ EXPECT_GT(max, full_consumed);
+
+ ++minus_g;
+ continue;
+ }
+
++count;
int p;
@@ -927,6 +974,7 @@
pclose(fp);
EXPECT_LE(1, count);
+ EXPECT_EQ(1, minus_g);
EXPECT_EQ(1, signals);
}
diff --git a/logd/Android.mk b/logd/Android.mk
index feca8d5..81637d2 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -28,7 +28,8 @@
liblog \
libcutils \
libbase \
- libpackagelistparser
+ libpackagelistparser \
+ libminijail
# This is what we want to do:
# event_logtags = $(shell \
@@ -38,7 +39,7 @@
# event_flag := $(call event_logtags,auditd)
# event_flag += $(call event_logtags,logd)
# so make sure we do not regret hard-coding it as follows:
-event_flag := -DAUDITD_LOG_TAG=1003 -DLOGD_LOG_TAG=1004
+event_flag := -DAUDITD_LOG_TAG=1003 -DCHATTY_LOG_TAG=1004
LOCAL_CFLAGS := -Werror $(event_flag)
diff --git a/logd/CommandListener.h b/logd/CommandListener.h
index 3877675..cbcd601 100644
--- a/logd/CommandListener.h
+++ b/logd/CommandListener.h
@@ -49,7 +49,7 @@
class name##Cmd : public LogCommand { \
LogBuffer &mBuf; \
public: \
- name##Cmd(LogBuffer *buf); \
+ explicit name##Cmd(LogBuffer *buf); \
virtual ~name##Cmd() {} \
int runCommand(SocketClient *c, int argc, char ** argv); \
};
diff --git a/logd/FlushCommand.h b/logd/FlushCommand.h
index 9224773..7172d5f 100644
--- a/logd/FlushCommand.h
+++ b/logd/FlushCommand.h
@@ -35,7 +35,7 @@
uint64_t mTimeout;
public:
- FlushCommand(LogReader &mReader,
+ explicit FlushCommand(LogReader &mReader,
bool nonBlock = false,
unsigned long tail = -1,
unsigned int logMask = -1,
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 24c3f52..cc140b0 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -102,16 +102,72 @@
struct iovec iov[3];
static const char log_info[] = { KMSG_PRIORITY(LOG_INFO) };
static const char log_warning[] = { KMSG_PRIORITY(LOG_WARNING) };
+ static const char newline[] = "\n";
- iov[0].iov_base = info ? const_cast<char *>(log_info)
- : const_cast<char *>(log_warning);
- iov[0].iov_len = info ? sizeof(log_info) : sizeof(log_warning);
- iov[1].iov_base = str;
- iov[1].iov_len = strlen(str);
- iov[2].iov_base = const_cast<char *>("\n");
- iov[2].iov_len = 1;
+ // Dedupe messages, checking for identical messages starting with avc:
+ static unsigned count;
+ static char *last_str;
+ static bool last_info;
- writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
+ if (last_str != NULL) {
+ static const char avc[] = "): avc: ";
+ char *avcl = strstr(last_str, avc);
+ bool skip = false;
+
+ if (avcl) {
+ char *avcr = strstr(str, avc);
+
+ skip = avcr && !strcmp(avcl + strlen(avc), avcr + strlen(avc));
+ if (skip) {
+ ++count;
+ free(last_str);
+ last_str = strdup(str);
+ last_info = info;
+ }
+ }
+ if (!skip) {
+ static const char resume[] = " duplicate messages suppressed\n";
+
+ iov[0].iov_base = last_info ?
+ const_cast<char *>(log_info) :
+ const_cast<char *>(log_warning);
+ iov[0].iov_len = last_info ?
+ sizeof(log_info) :
+ sizeof(log_warning);
+ iov[1].iov_base = last_str;
+ iov[1].iov_len = strlen(last_str);
+ if (count > 1) {
+ iov[2].iov_base = const_cast<char *>(resume);
+ iov[2].iov_len = strlen(resume);
+ } else {
+ iov[2].iov_base = const_cast<char *>(newline);
+ iov[2].iov_len = strlen(newline);
+ }
+
+ writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
+ free(last_str);
+ last_str = NULL;
+ }
+ }
+ if (last_str == NULL) {
+ count = 0;
+ last_str = strdup(str);
+ last_info = info;
+ }
+ if (count == 0) {
+ iov[0].iov_base = info ?
+ const_cast<char *>(log_info) :
+ const_cast<char *>(log_warning);
+ iov[0].iov_len = info ?
+ sizeof(log_info) :
+ sizeof(log_warning);
+ iov[1].iov_base = str;
+ iov[1].iov_len = strlen(str);
+ iov[2].iov_base = const_cast<char *>(newline);
+ iov[2].iov_len = strlen(newline);
+
+ writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
+ }
}
pid_t pid = getpid();
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 8c30f79..fa95733 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -313,16 +313,16 @@
LogBufferElement *element = *it;
log_id_t id = element->getLogId();
- { // start of scope for uid found iterator
- LogBufferIteratorMap::iterator found =
- mLastWorstUid[id].find(element->getUid());
- if ((found != mLastWorstUid[id].end())
- && (it == found->second)) {
- mLastWorstUid[id].erase(found);
+ { // start of scope for found iterator
+ int key = ((id == LOG_ID_EVENTS) || (id == LOG_ID_SECURITY)) ?
+ element->getTag() : element->getUid();
+ LogBufferIteratorMap::iterator found = mLastWorst[id].find(key);
+ if ((found != mLastWorst[id].end()) && (it == found->second)) {
+ mLastWorst[id].erase(found);
}
}
- if (element->getUid() == AID_SYSTEM) {
+ if ((id != LOG_ID_EVENTS) && (id != LOG_ID_SECURITY) && (element->getUid() == AID_SYSTEM)) {
// start of scope for pid found iterator
LogBufferPidIteratorMap::iterator found =
mLastWorstPidOfSystem[id].find(element->getPid());
@@ -380,7 +380,7 @@
tid(tid),
padding(0) {
}
- LogBufferElementKey(uint64_t key):value(key) { }
+ explicit LogBufferElementKey(uint64_t key):value(key) { }
uint64_t getKey() { return value; }
};
@@ -544,48 +544,31 @@
bool hasBlacklist = (id != LOG_ID_SECURITY) && mPrune.naughty();
while (!clearAll && (pruneRows > 0)) {
// recalculate the worst offender on every batched pass
- uid_t worst = (uid_t) -1;
+ int worst = -1; // not valid for getUid() or getKey()
size_t worst_sizes = 0;
size_t second_worst_sizes = 0;
pid_t worstPid = 0; // POSIX guarantees PID != 0
if (worstUidEnabledForLogid(id) && mPrune.worstUidEnabled()) {
- { // begin scope for UID sorted list
- std::unique_ptr<const UidEntry *[]> sorted = stats.sort(
- AID_ROOT, (pid_t)0, 2, id);
+ // Calculate threshold as 12.5% of available storage
+ size_t threshold = log_buffer_size(id) / 8;
- if (sorted.get() && sorted[0] && sorted[1]) {
- worst_sizes = sorted[0]->getSizes();
- // Calculate threshold as 12.5% of available storage
- size_t threshold = log_buffer_size(id) / 8;
- if ((worst_sizes > threshold)
- // Allow time horizon to extend roughly tenfold, assume
- // average entry length is 100 characters.
- && (worst_sizes > (10 * sorted[0]->getDropped()))) {
- worst = sorted[0]->getKey();
- second_worst_sizes = sorted[1]->getSizes();
- if (second_worst_sizes < threshold) {
- second_worst_sizes = threshold;
- }
- }
- }
- }
+ if ((id == LOG_ID_EVENTS) || (id == LOG_ID_SECURITY)) {
+ stats.sortTags(AID_ROOT, (pid_t)0, 2, id).findWorst(
+ worst, worst_sizes, second_worst_sizes, threshold);
+ } else {
+ stats.sort(AID_ROOT, (pid_t)0, 2, id).findWorst(
+ worst, worst_sizes, second_worst_sizes, threshold);
- if ((worst == AID_SYSTEM) && mPrune.worstPidOfSystemEnabled()) {
- // begin scope of PID sorted list
- std::unique_ptr<const PidEntry *[]> sorted = stats.sort(
- worst, (pid_t)0, 2, id, worst);
- if (sorted.get() && sorted[0] && sorted[1]) {
- worstPid = sorted[0]->getKey();
- second_worst_sizes = worst_sizes
- - sorted[0]->getSizes()
- + sorted[1]->getSizes();
+ if ((worst == AID_SYSTEM) && mPrune.worstPidOfSystemEnabled()) {
+ stats.sortPids(worst, (pid_t)0, 2, id).findWorst(
+ worstPid, worst_sizes, second_worst_sizes);
}
}
}
// skip if we have neither worst nor naughty filters
- if ((worst == (uid_t) -1) && !hasBlacklist) {
+ if ((worst == -1) && !hasBlacklist) {
break;
}
@@ -597,10 +580,10 @@
// - coalesce chatty tags
// - check age-out of preserved logs
bool gc = pruneRows <= 1;
- if (!gc && (worst != (uid_t) -1)) {
- { // begin scope for uid worst found iterator
- LogBufferIteratorMap::iterator found = mLastWorstUid[id].find(worst);
- if ((found != mLastWorstUid[id].end())
+ if (!gc && (worst != -1)) {
+ { // begin scope for worst found iterator
+ LogBufferIteratorMap::iterator found = mLastWorst[id].find(worst);
+ if ((found != mLastWorst[id].end())
&& (found->second != mLogElements.end())) {
leading = false;
it = found->second;
@@ -658,6 +641,10 @@
continue;
}
+ int key = ((id == LOG_ID_EVENTS) || (id == LOG_ID_SECURITY)) ?
+ element->getTag() :
+ element->getUid();
+
if (hasBlacklist && mPrune.naughty(element)) {
last.clear(element);
it = erase(it);
@@ -670,7 +657,7 @@
break;
}
- if (element->getUid() == worst) {
+ if (key == worst) {
kick = true;
if (worst_sizes < second_worst_sizes) {
break;
@@ -689,20 +676,19 @@
last.add(element);
if (worstPid
&& ((!gc && (element->getPid() == worstPid))
- || (mLastWorstPidOfSystem[id].find(element->getPid())
+ || (mLastWorstPidOfSystem[id].find(element->getPid())
== mLastWorstPidOfSystem[id].end()))) {
- mLastWorstPidOfSystem[id][element->getUid()] = it;
+ mLastWorstPidOfSystem[id][key] = it;
}
- if ((!gc && !worstPid && (element->getUid() == worst))
- || (mLastWorstUid[id].find(element->getUid())
- == mLastWorstUid[id].end())) {
- mLastWorstUid[id][element->getUid()] = it;
+ if ((!gc && !worstPid && (key == worst))
+ || (mLastWorst[id].find(key) == mLastWorst[id].end())) {
+ mLastWorst[id][key] = it;
}
++it;
continue;
}
- if ((element->getUid() != worst)
+ if ((key != worst)
|| (worstPid && (element->getPid() != worstPid))) {
leading = false;
last.clear(element);
@@ -734,9 +720,9 @@
== mLastWorstPidOfSystem[id].end()))) {
mLastWorstPidOfSystem[id][worstPid] = it;
}
- if ((!gc && !worstPid) || (mLastWorstUid[id].find(worst)
- == mLastWorstUid[id].end())) {
- mLastWorstUid[id][worst] = it;
+ if ((!gc && !worstPid) ||
+ (mLastWorst[id].find(worst) == mLastWorst[id].end())) {
+ mLastWorst[id][worst] = it;
}
++it;
}
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index 7e99236..162c189 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -89,7 +89,7 @@
typedef std::unordered_map<uid_t,
LogBufferElementCollection::iterator>
LogBufferIteratorMap;
- LogBufferIteratorMap mLastWorstUid[LOG_ID_MAX];
+ LogBufferIteratorMap mLastWorst[LOG_ID_MAX];
// watermark of any worst/chatty pid of system processing
typedef std::unordered_map<pid_t,
LogBufferElementCollection::iterator>
@@ -103,7 +103,7 @@
public:
LastLogTimes &mTimes;
- LogBuffer(LastLogTimes *times);
+ explicit LogBuffer(LastLogTimes *times);
void init();
bool isMonotonic() { return monotonic; }
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index eb5194c..3e6e586 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -181,7 +181,7 @@
android_log_event_string_t *event =
reinterpret_cast<android_log_event_string_t *>(buffer);
- event->header.tag = htole32(LOGD_LOG_TAG);
+ event->header.tag = htole32(CHATTY_LOG_TAG);
event->type = EVENT_TYPE_STRING;
event->length = htole32(len);
} else {
diff --git a/logd/LogCommand.h b/logd/LogCommand.h
index c944478..0adc2a1 100644
--- a/logd/LogCommand.h
+++ b/logd/LogCommand.h
@@ -22,7 +22,7 @@
class LogCommand : public FrameworkCommand {
public:
- LogCommand(const char *cmd);
+ explicit LogCommand(const char *cmd);
virtual ~LogCommand() {}
};
diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp
index 39dd227..61b7fd8 100644
--- a/logd/LogListener.cpp
+++ b/logd/LogListener.cpp
@@ -48,7 +48,7 @@
+ LOGGER_ENTRY_MAX_PAYLOAD];
struct iovec iov = { buffer, sizeof(buffer) };
- char control[CMSG_SPACE(sizeof(struct ucred))] __aligned(4);
+ alignas(4) char control[CMSG_SPACE(sizeof(struct ucred))];
struct msghdr hdr = {
NULL,
0,
diff --git a/logd/LogReader.h b/logd/LogReader.h
index 98674b8..fdcedf1 100644
--- a/logd/LogReader.h
+++ b/logd/LogReader.h
@@ -27,7 +27,7 @@
LogBuffer &mLogbuf;
public:
- LogReader(LogBuffer *logbuf);
+ explicit LogReader(LogBuffer *logbuf);
void notifyNewLog();
LogBuffer &logbuf(void) const { return mLogbuf; }
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 2b02bc1..86d33b2 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -15,8 +15,10 @@
*/
#include <fcntl.h>
+#include <pwd.h>
#include <stdio.h>
#include <string.h>
+#include <sys/types.h>
#include <unistd.h>
#include <log/logger.h>
@@ -150,6 +152,15 @@
pidTable.drop(element->getPid(), element);
tidTable.drop(element->getTid(), element);
+
+ uint32_t tag = element->getTag();
+ if (tag) {
+ if (log_id == LOG_ID_SECURITY) {
+ securityTagTable.drop(tag, element);
+ } else {
+ tagTable.drop(tag, element);
+ }
+ }
}
// caller must own and free character string
@@ -159,14 +170,13 @@
return strdup("auditd");
}
- // Android hard coded
- const struct android_id_info *info = android_ids;
-
- for (size_t i = 0; i < android_id_count; ++i) {
- if (info->aid == uid) {
- return strdup(info->name);
+ // Android system
+ if (uid < AID_APP) {
+ // in bionic, thread safe as long as we copy the results
+ struct passwd *pwd = getpwuid(uid);
+ if (pwd) {
+ return strdup(pwd->pw_name);
}
- ++info;
}
// Parse /data/system/packages.list
@@ -179,6 +189,14 @@
return name;
}
+ // Android application
+ if (uid >= AID_APP) {
+ struct passwd *pwd = getpwuid(uid);
+ if (pwd) {
+ return strdup(pwd->pw_name);
+ }
+ }
+
// report uid -> pid(s) -> pidToName if unique
for(pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end(); ++it) {
const PidEntry &entry = it->second;
@@ -275,7 +293,7 @@
if ((spaces <= 0) && pruned.length()) {
spaces = 1;
}
- if (spaces > 0) {
+ if ((spaces > 0) && (pruned.length() != 0)) {
change += android::base::StringPrintf("%*s", (int)spaces, "");
}
pruned = change + pruned;
@@ -429,6 +447,10 @@
getSizes());
std::string pruned = "";
+ size_t dropped = getDropped();
+ if (dropped) {
+ pruned = android::base::StringPrintf("%zu", dropped);
+ }
return formatLine(name, size, pruned);
}
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 6f7d264..878c333 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -33,7 +33,7 @@
#include "LogUtils.h"
#define log_id_for_each(i) \
- for (log_id_t i = LOG_ID_MIN; i < LOG_ID_MAX; i = (log_id_t) (i + 1))
+ for (log_id_t i = LOG_ID_MIN; (i) < LOG_ID_MAX; (i) = (log_id_t) ((i) + 1))
class LogStatistics;
@@ -166,7 +166,7 @@
size_t size;
EntryBase():size(0) { }
- EntryBase(LogBufferElement *element):size(element->getMsgLen()) { }
+ explicit EntryBase(LogBufferElement *element):size(element->getMsgLen()) { }
size_t getSizes() const { return size; }
@@ -201,9 +201,9 @@
size_t dropped;
EntryBaseDropped():dropped(0) { }
- EntryBaseDropped(LogBufferElement *element):
+ explicit EntryBaseDropped(LogBufferElement *element):
EntryBase(element),
- dropped(element->getDropped()){
+ dropped(element->getDropped()) {
}
size_t getDropped() const { return dropped; }
@@ -226,7 +226,7 @@
const uid_t uid;
pid_t pid;
- UidEntry(LogBufferElement *element):
+ explicit UidEntry(LogBufferElement *element):
EntryBaseDropped(element),
uid(element->getUid()),
pid(element->getPid()) {
@@ -256,13 +256,13 @@
uid_t uid;
char *name;
- PidEntry(pid_t pid):
+ explicit PidEntry(pid_t pid):
EntryBaseDropped(),
pid(pid),
uid(android::pidToUid(pid)),
name(android::pidToName(pid)) {
}
- PidEntry(LogBufferElement *element):
+ explicit PidEntry(LogBufferElement *element):
EntryBaseDropped(element),
pid(element->getPid()),
uid(element->getUid()),
@@ -320,7 +320,7 @@
uid(android::pidToUid(tid)),
name(android::tidToName(tid)) {
}
- TidEntry(LogBufferElement *element):
+ explicit TidEntry(LogBufferElement *element):
EntryBaseDropped(element),
tid(element->getTid()),
pid(element->getPid()),
@@ -370,13 +370,13 @@
std::string format(const LogStatistics &stat, log_id_t id) const;
};
-struct TagEntry : public EntryBase {
+struct TagEntry : public EntryBaseDropped {
const uint32_t tag;
pid_t pid;
uid_t uid;
- TagEntry(LogBufferElement *element):
- EntryBase(element),
+ explicit TagEntry(LogBufferElement *element):
+ EntryBaseDropped(element),
tag(element->getTag()),
pid(element->getPid()),
uid(element->getUid()) {
@@ -401,6 +401,43 @@
std::string format(const LogStatistics &stat, log_id_t id) const;
};
+template <typename TEntry>
+class LogFindWorst {
+ std::unique_ptr<const TEntry *[]> sorted;
+
+public:
+
+ explicit LogFindWorst(std::unique_ptr<const TEntry *[]> &&sorted) : sorted(std::move(sorted)) { }
+
+ void findWorst(int &worst,
+ size_t &worst_sizes, size_t &second_worst_sizes,
+ size_t threshold) {
+ if (sorted.get() && sorted[0] && sorted[1]) {
+ worst_sizes = sorted[0]->getSizes();
+ if ((worst_sizes > threshold)
+ // Allow time horizon to extend roughly tenfold, assume
+ // average entry length is 100 characters.
+ && (worst_sizes > (10 * sorted[0]->getDropped()))) {
+ worst = sorted[0]->getKey();
+ second_worst_sizes = sorted[1]->getSizes();
+ if (second_worst_sizes < threshold) {
+ second_worst_sizes = threshold;
+ }
+ }
+ }
+ }
+
+ void findWorst(int &worst,
+ size_t worst_sizes, size_t &second_worst_sizes) {
+ if (sorted.get() && sorted[0] && sorted[1]) {
+ worst = sorted[0]->getKey();
+ second_worst_sizes = worst_sizes
+ - sorted[0]->getSizes()
+ + sorted[1]->getSizes();
+ }
+ }
+};
+
// Log Statistics
class LogStatistics {
friend UidEntry;
@@ -451,13 +488,14 @@
--mDroppedElements[log_id];
}
- std::unique_ptr<const UidEntry *[]> sort(uid_t uid, pid_t pid,
- size_t len, log_id id) {
- return uidTable[id].sort(uid, pid, len);
+ LogFindWorst<UidEntry> sort(uid_t uid, pid_t pid, size_t len, log_id id) {
+ return LogFindWorst<UidEntry>(uidTable[id].sort(uid, pid, len));
}
- std::unique_ptr<const PidEntry *[]> sort(uid_t uid, pid_t pid,
- size_t len, log_id id, uid_t) {
- return pidSystemTable[id].sort(uid, pid, len);
+ LogFindWorst<PidEntry> sortPids(uid_t uid, pid_t pid, size_t len, log_id id) {
+ return LogFindWorst<PidEntry>(pidSystemTable[id].sort(uid, pid, len));
+ }
+ LogFindWorst<TagEntry> sortTags(uid_t uid, pid_t pid, size_t len, log_id) {
+ return LogFindWorst<TagEntry>(tagTable.sort(uid, pid, len));
}
// fast track current value by id only
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
index fd4800e..fc66330 100644
--- a/logd/LogUtils.h
+++ b/logd/LogUtils.h
@@ -17,6 +17,7 @@
#ifndef _LOGD_LOG_UTILS_H__
#define _LOGD_LOG_UTILS_H__
+#include <sys/cdefs.h>
#include <sys/types.h>
#include <log/log.h>
@@ -29,6 +30,7 @@
// Furnished in main.cpp. Caller must own and free returned value
char *uidToName(uid_t uid);
+void prdebug(const char *fmt, ...) __printflike(1, 2);
// Furnished in LogStatistics.cpp. Caller must own and free returned value
char *pidToName(pid_t pid);
@@ -54,7 +56,8 @@
bool property_get_bool(const char *key, int def);
static inline bool worstUidEnabledForLogid(log_id_t id) {
- return (id == LOG_ID_MAIN) || (id == LOG_ID_SYSTEM) || (id == LOG_ID_RADIO);
+ return (id == LOG_ID_MAIN) || (id == LOG_ID_SYSTEM) ||
+ (id == LOG_ID_RADIO) || (id == LOG_ID_EVENTS);
}
template <int (*cmp)(const char *l, const char *r, const size_t s)>
diff --git a/logd/README.property b/logd/README.property
index b2708e4..791b1d5 100644
--- a/logd/README.property
+++ b/logd/README.property
@@ -8,7 +8,7 @@
ro.device_owner bool false Override persist.logd.security to false
ro.logd.kernel bool+ svelte+ Enable klogd daemon
ro.logd.statistics bool+ svelte+ Enable logcat -S statistics.
-ro.build.type string if user, logd.statistics &
+ro.debuggable number if not "1", logd.statistics &
ro.logd.kernel default false.
logd.logpersistd.enable bool auto Safe to start logpersist daemon service
logd.logpersistd string persist Enable logpersist daemon, "logcatd"
@@ -55,10 +55,10 @@
NB:
- auto - managed by /init
- bool+ - "true", "false" and comma separated list of "eng" (forced false if
- ro.build.type is "user") or "svelte" (forced false if ro.config.low_ram is
+ ro.debuggable is not "1") or "svelte" (forced false if ro.config.low_ram is
true).
- svelte - see ro.config.low_ram for details.
-- svelte+ - see ro.config.low_ram and ro.build.type for details.
+- svelte+ - see ro.config.low_ram and ro.debuggable for details.
- ro - <base property> temporary override, ro.<base property> platform default.
- persist - <base property> override, persist.<base property> platform default.
- build - VERBOSE for native, DEBUG for jvm isLoggable, or developer option.
diff --git a/logd/event.logtags b/logd/event.logtags
index db8c19b..0d24df0 100644
--- a/logd/event.logtags
+++ b/logd/event.logtags
@@ -34,4 +34,4 @@
# TODO: generate ".java" and ".h" files with integer constants from this file.
1003 auditd (avc|3)
-1004 logd (dropped|3)
+1004 chatty (dropped|3)
diff --git a/logd/main.cpp b/logd/main.cpp
index 8aa1abb..77a6973 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -36,12 +36,15 @@
#include <cstdbool>
#include <memory>
+#include <android-base/macros.h>
#include <cutils/properties.h>
#include <cutils/sched_policy.h>
#include <cutils/sockets.h>
+#include <libminijail.h>
#include <log/event_tag_map.h>
#include <packagelistparser/packagelistparser.h>
#include <private/android_filesystem_config.h>
+#include <scoped_minijail.h>
#include <utils/threads.h>
#include "CommandListener.h"
@@ -58,14 +61,14 @@
'>'
//
-// The service is designed to be run by init, it does not respond well
+// The service is designed to be run by init, it does not respond well
// to starting up manually. When starting up manually the sockets will
// fail to open typically for one of the following reasons:
// EADDRINUSE if logger is running.
// EACCESS if started without precautions (below)
//
// Here is a cookbook procedure for starting up logd manually assuming
-// init is out of the way, pedantically all permissions and selinux
+// init is out of the way, pedantically all permissions and SELinux
// security is put back in place:
//
// setenforce 0
@@ -102,43 +105,13 @@
return -1;
}
- if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
- return -1;
- }
-
gid_t groups[] = { AID_READPROC };
-
- if (setgroups(sizeof(groups) / sizeof(groups[0]), groups) == -1) {
- return -1;
- }
-
- if (setgid(AID_LOGD) != 0) {
- return -1;
- }
-
- if (setuid(AID_LOGD) != 0) {
- return -1;
- }
-
- struct __user_cap_header_struct capheader;
- struct __user_cap_data_struct capdata[2];
- memset(&capheader, 0, sizeof(capheader));
- memset(&capdata, 0, sizeof(capdata));
- capheader.version = _LINUX_CAPABILITY_VERSION_3;
- capheader.pid = 0;
-
- capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
- capdata[CAP_TO_INDEX(CAP_AUDIT_CONTROL)].permitted |= CAP_TO_MASK(CAP_AUDIT_CONTROL);
-
- capdata[0].effective = capdata[0].permitted;
- capdata[1].effective = capdata[1].permitted;
- capdata[0].inheritable = 0;
- capdata[1].inheritable = 0;
-
- if (capset(&capheader, &capdata[0]) < 0) {
- return -1;
- }
-
+ ScopedMinijail j(minijail_new());
+ minijail_set_supplementary_gids(j.get(), arraysize(groups), groups);
+ minijail_change_uid(j.get(), AID_LOGD);
+ minijail_change_gid(j.get(), AID_LOGD);
+ minijail_use_caps(j.get(), CAP_TO_MASK(CAP_SYSLOG) | CAP_TO_MASK(CAP_AUDIT_CONTROL));
+ minijail_enter(j.get());
return 0;
}
@@ -202,8 +175,8 @@
return false;
}
if (flag & BOOL_DEFAULT_FLAG_ENG) {
- property_get("ro.build.type", property, "");
- if (!strcmp(property, "user")) {
+ property_get("ro.debuggable", property, "");
+ if (strcmp(property, "1")) {
return false;
}
}
@@ -211,10 +184,32 @@
return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
}
-// Remove the static, and use this variable
-// globally for debugging if necessary. eg:
-// write(fdDmesg, "I am here\n", 10);
static int fdDmesg = -1;
+void android::prdebug(const char *fmt, ...) {
+ if (fdDmesg < 0) {
+ return;
+ }
+
+ static const char message[] = {
+ KMSG_PRIORITY(LOG_DEBUG), 'l', 'o', 'g', 'd', ':', ' '
+ };
+ char buffer[256];
+ memcpy(buffer, message, sizeof(message));
+
+ va_list ap;
+ va_start(ap, fmt);
+ int n = vsnprintf(buffer + sizeof(message),
+ sizeof(buffer) - sizeof(message), fmt, ap);
+ va_end(ap);
+ if (n > 0) {
+ buffer[sizeof(buffer) - 1] = '\0';
+ if (!strchr(buffer, '\n')) {
+ buffer[sizeof(buffer) - 2] = '\0';
+ strlcat(buffer, "\n", sizeof(buffer));
+ }
+ write(fdDmesg, buffer, strlen(buffer));
+ }
+}
static sem_t uidName;
static uid_t uid;
diff --git a/logwrapper/Android.bp b/logwrapper/Android.bp
new file mode 100644
index 0000000..41f0726
--- /dev/null
+++ b/logwrapper/Android.bp
@@ -0,0 +1,36 @@
+
+
+// ========================================================
+// Static and shared library
+// ========================================================
+cc_library {
+ name: "liblogwrap",
+ srcs: ["logwrap.c"],
+ shared_libs: [
+ "libcutils",
+ "liblog",
+ ],
+ export_include_dirs: ["include"],
+ local_include_dirs: ["include"],
+ cflags: [
+ "-Werror",
+ "-std=gnu99",
+ ],
+}
+
+// ========================================================
+// Executable
+// ========================================================
+cc_binary {
+ name: "logwrapper",
+ srcs: ["logwrapper.c"],
+ static_libs: [
+ "liblog",
+ "liblogwrap",
+ "libcutils",
+ ],
+ cflags: [
+ "-Werror",
+ "-std=gnu99",
+ ],
+}
diff --git a/logwrapper/Android.mk b/logwrapper/Android.mk
deleted file mode 100644
index ad45b2c..0000000
--- a/logwrapper/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# ========================================================
-# Static library
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := liblogwrap
-LOCAL_SRC_FILES := logwrap.c
-LOCAL_SHARED_LIBRARIES := libcutils liblog
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror -std=gnu99
-include $(BUILD_STATIC_LIBRARY)
-
-# ========================================================
-# Shared library
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := liblogwrap
-LOCAL_SHARED_LIBRARIES := libcutils liblog
-LOCAL_WHOLE_STATIC_LIBRARIES := liblogwrap
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror -std=gnu99
-include $(BUILD_SHARED_LIBRARY)
-
-# ========================================================
-# Executable
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= logwrapper.c
-LOCAL_MODULE := logwrapper
-LOCAL_STATIC_LIBRARIES := liblog liblogwrap libcutils
-LOCAL_CFLAGS := -Werror -std=gnu99
-include $(BUILD_EXECUTABLE)
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
index 28d6de7..ccbe0bf 100644
--- a/logwrapper/logwrap.c
+++ b/logwrapper/logwrap.c
@@ -408,7 +408,7 @@
if (poll_fds[0].revents & POLLHUP) {
int ret;
- ret = waitpid(pid, &status, WNOHANG);
+ ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
if (ret < 0) {
rc = errno;
ALOG(LOG_ERROR, "logwrap", "waitpid failed with %s\n", strerror(errno));