liblog: add private android_log_write_list_buffer()
Allows us to compose an event message for our own in-memory purposes.
Will be used to compose an event message in logd and directly write
it to just the pmsg buffer. Provide an internal enhanced C++ wrapper
for event handling.
Test: gTest liblog-unit-tests --gtest_filter=liblog.android_log_write_list_buffer
Bug: 31456426
Change-Id: I98246898ba580f9e506baba8af2fd1b26a2a8aae
diff --git a/include/log/log_event_list.h b/include/log/log_event_list.h
index 04c1cd6..31d49b2 100644
--- a/include/log/log_event_list.h
+++ b/include/log/log_event_list.h
@@ -116,6 +116,7 @@
/* android_log_list C++ helpers */
extern "C++" {
class android_log_event_list {
+friend class __android_log_event_list;
private:
android_log_context ctx;
diff --git a/include/private/android_logger.h b/include/private/android_logger.h
index f3c6cf7..9f81b1f 100644
--- a/include/private/android_logger.h
+++ b/include/private/android_logger.h
@@ -25,6 +25,13 @@
#include <stdint.h>
#include <sys/types.h>
+#if (defined(__cplusplus) && defined(_USING_LIBCXX))
+extern "C++" {
+#include <string>
+}
+#endif
+
+#include <log/log_event_list.h>
#include <log/log.h>
#define LOGGER_MAGIC 'l'
@@ -146,6 +153,40 @@
unsigned long __android_logger_get_buffer_size(log_id_t logId);
bool __android_logger_valid_buffer_size(unsigned long value);
+/* Retrieve the composed event buffer */
+int android_log_write_list_buffer(android_log_context ctx, const char** msg);
+
+#ifdef __cplusplus
+#ifdef __class_android_log_event_list_defined
+#ifndef __class_android_log_event_list_private_defined
+#define __class_android_log_event_list_private_defined
+/* android_log_context C++ helpers */
+extern "C++" {
+class __android_log_event_list : public android_log_event_list {
+ __android_log_event_list(const android_log_event_list&) = delete;
+ void operator =(const __android_log_event_list&) = delete;
+
+public:
+ explicit __android_log_event_list(int tag) : android_log_event_list(tag) { }
+ explicit __android_log_event_list(log_msg& log_msg) : android_log_event_list(log_msg) { }
+
+#if defined(_USING_LIBCXX)
+ operator std::string() {
+ if (ret) return std::string("");
+ const char* cp = NULL;
+ ssize_t len = android_log_write_list_buffer(ctx, &cp);
+ if (len < 0) ret = len;
+ if (!cp || (len <= 0)) return std::string("");
+ return std::string(cp, len);
+ }
+#endif
+
+};
+}
+#endif
+#endif
+#endif
+
#if defined(__cplusplus)
}
#endif
diff --git a/liblog/log_event_list.c b/liblog/log_event_list.c
index 8303b63..9ac1d30 100644
--- a/liblog/log_event_list.c
+++ b/liblog/log_event_list.c
@@ -320,7 +320,7 @@
context->storage[1] = context->count[0];
len = context->len = context->pos;
msg = (const char *)context->storage;
- /* it'snot a list */
+ /* it's not a list */
if (context->count[0] <= 1) {
len -= sizeof(uint8_t) + sizeof(uint8_t);
if (len < 0) {
@@ -333,6 +333,38 @@
__android_log_security_bwrite(context->tag, msg, len);
}
+LIBLOG_ABI_PRIVATE int android_log_write_list_buffer(android_log_context ctx,
+ const char **buffer) {
+ android_log_context_internal *context;
+ const char *msg;
+ ssize_t len;
+
+ context = (android_log_context_internal *)ctx;
+ if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
+ return -EBADF;
+ }
+ if (context->list_nest_depth) {
+ return -EIO;
+ }
+ if (buffer == NULL) {
+ return -EFAULT;
+ }
+ /* NB: if there was overflow, then log is truncated. Nothing reported */
+ context->storage[1] = context->count[0];
+ len = context->len = context->pos;
+ msg = (const char *)context->storage;
+ /* it's not a list */
+ if (context->count[0] <= 1) {
+ len -= sizeof(uint8_t) + sizeof(uint8_t);
+ if (len < 0) {
+ len = 0;
+ }
+ msg += sizeof(uint8_t) + sizeof(uint8_t);
+ }
+ *buffer = msg;
+ return len;
+}
+
/*
* Extract a 4-byte value from a byte stream.
*/
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 9c418c1..02a572d 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -2651,6 +2651,19 @@
ASSERT_TRUE(NULL == ctx);
}
+TEST(liblog, android_log_write_list_buffer) {
+ __android_log_event_list ctx(1005);
+ ctx << 1005 << "tag_def" << "(tag|1),(name|3),(format|3)";
+ std::string buffer(ctx);
+ ctx.close();
+
+ char msgBuf[1024];
+ memset(msgBuf, 0, sizeof(msgBuf));
+ EXPECT_EQ(android_log_buffer_to_string(buffer.data(), buffer.length(),
+ msgBuf, sizeof(msgBuf)), 0);
+ EXPECT_STREQ(msgBuf, "[1005,tag_def,(tag|1),(name|3),(format|3)]");
+}
+
static const char __pmsg_file[] =
"/data/william-shakespeare/MuchAdoAboutNothing.txt";