liblog: Add functions to reset log context

Add android_log_parser_reset and android_log_reset to reset reader/writer
log context. This allows to generate multiple log messages of the same
format without context reallocation.

Change-Id: Icb0f15855378aa4e66fc671ffefd15d9df6fee1e
diff --git a/liblog/include/log/log_event_list.h b/liblog/include/log/log_event_list.h
index bb1ce34..1b7c377 100644
--- a/liblog/include/log/log_event_list.h
+++ b/liblog/include/log/log_event_list.h
@@ -108,6 +108,13 @@
 android_log_list_element android_log_read_next(android_log_context ctx);
 android_log_list_element android_log_peek_next(android_log_context ctx);
 
+/* Reset writer context */
+int android_log_reset(android_log_context ctx);
+
+/* Reset reader context */
+int android_log_parser_reset(android_log_context ctx,
+                             const char* msg, size_t len);
+
 /* Finished with reader or writer context */
 int android_log_destroy(android_log_context* ctx);
 
diff --git a/liblog/include_vndk/log/log_event_list.h b/liblog/include_vndk/log/log_event_list.h
index cbd3091..9f74534 100644
--- a/liblog/include_vndk/log/log_event_list.h
+++ b/liblog/include_vndk/log/log_event_list.h
@@ -63,6 +63,13 @@
 /* NB: LOG_ID_EVENTS and LOG_ID_SECURITY only valid binary buffers */
 int android_log_write_list(android_log_context ctx, log_id_t id);
 
+/* Reset writer context */
+int android_log_reset(android_log_context ctx);
+
+/* Reset reader context */
+int android_log_parser_reset(android_log_context ctx,
+                             const char* msg, size_t len);
+
 /* Finished with reader or writer context */
 int android_log_destroy(android_log_context* ctx);
 
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
index 66670fe..015c9cb 100644
--- a/liblog/liblog.map.txt
+++ b/liblog/liblog.map.txt
@@ -53,3 +53,9 @@
     __android_log_is_loggable_len;
     __android_log_is_debuggable; # vndk
 };
+
+LIBLOG_Q {
+  global:
+    android_log_reset; #vndk
+    android_log_parser_reset; #vndk
+};
diff --git a/liblog/log_event_list.c b/liblog/log_event_list.c
index a59cb87..14002ce 100644
--- a/liblog/log_event_list.c
+++ b/liblog/log_event_list.c
@@ -45,14 +45,9 @@
   uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD];
 } android_log_context_internal;
 
-LIBLOG_ABI_PUBLIC android_log_context create_android_logger(uint32_t tag) {
-  size_t needed, i;
-  android_log_context_internal* context;
+static void init_context(android_log_context_internal* context, uint32_t tag) {
+  size_t needed;
 
-  context = calloc(1, sizeof(android_log_context_internal));
-  if (!context) {
-    return NULL;
-  }
   context->tag = tag;
   context->read_write_flag = kAndroidLoggerWrite;
   needed = sizeof(uint8_t) + sizeof(uint8_t);
@@ -63,6 +58,24 @@
   context->storage[context->pos + 0] = EVENT_TYPE_LIST;
   context->list[0] = context->pos + 1;
   context->pos += needed;
+}
+
+static void init_parser_context(android_log_context_internal* context,
+                                const char* msg, size_t len) {
+  len = (len <= MAX_EVENT_PAYLOAD) ? len : MAX_EVENT_PAYLOAD;
+  context->len = len;
+  memcpy(context->storage, msg, len);
+  context->read_write_flag = kAndroidLoggerRead;
+}
+
+LIBLOG_ABI_PUBLIC android_log_context create_android_logger(uint32_t tag) {
+  android_log_context_internal* context;
+
+  context = calloc(1, sizeof(android_log_context_internal));
+  if (!context) {
+    return NULL;
+  }
+  init_context(context, tag);
 
   return (android_log_context)context;
 }
@@ -76,10 +89,7 @@
   if (!context) {
     return NULL;
   }
-  len = (len <= MAX_EVENT_PAYLOAD) ? len : MAX_EVENT_PAYLOAD;
-  context->len = len;
-  memcpy(context->storage, msg, len);
-  context->read_write_flag = kAndroidLoggerRead;
+  init_parser_context(context, msg, len);
 
   return (android_log_context)context;
 }
@@ -97,6 +107,38 @@
   return 0;
 }
 
+LIBLOG_ABI_PUBLIC int android_log_reset(android_log_context ctx) {
+  android_log_context_internal* context;
+  uint32_t tag;
+
+  context = (android_log_context_internal*)ctx;
+  if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
+    return -EBADF;
+  }
+
+  tag = context->tag;
+  memset(context, 0, sizeof(*context));
+  init_context(context, tag);
+
+  return 0;
+}
+
+LIBLOG_ABI_PUBLIC int android_log_parser_reset(android_log_context ctx,
+                                               const char* msg, size_t len) {
+  android_log_context_internal* context;
+
+  context = (android_log_context_internal*)ctx;
+  if (!context || (kAndroidLoggerRead != context->read_write_flag)) {
+    return -EBADF;
+  }
+
+  memset(context, 0, sizeof(*context));
+  init_parser_context(context, msg, len);
+
+  return 0;
+}
+
+
 LIBLOG_ABI_PUBLIC int android_log_write_list_begin(android_log_context ctx) {
   size_t needed;
   android_log_context_internal* context;