Merge changes Ic15a87f4,I8a53ad3a,I6a03d405

* changes:
  liblog: __android_log_error_write use event list library
  liblog: test: __android_log_error_write accuracy
  liblog: add android_log_write_string8_len
diff --git a/include/log/log.h b/include/log/log.h
index 6ad6f0a..e606a84 100644
--- a/include/log/log.h
+++ b/include/log/log.h
@@ -589,6 +589,8 @@
 int android_log_write_int32(android_log_context ctx, int32_t value);
 int android_log_write_int64(android_log_context ctx, int64_t value);
 int android_log_write_string8(android_log_context ctx, const char *value);
+int android_log_write_string8_len(android_log_context ctx,
+                                  const char *value, size_t maxlen);
 int android_log_write_float32(android_log_context ctx, float value);
 
 /* Submit the composed list context to the specified logger id */
diff --git a/liblog/Android.mk b/liblog/Android.mk
index c7b76d8..dd5b518 100644
--- a/liblog/Android.mk
+++ b/liblog/Android.mk
@@ -24,11 +24,10 @@
 # so make sure we do not regret hard-coding it as follows:
 liblog_cflags := -DLIBLOG_LOG_TAG=1005
 
-liblog_host_sources := logd_write.c log_event_write.c fake_log_device.c event.logtags
-liblog_target_sources := logd_write.c log_event_write.c event_tag_map.c log_time.cpp log_is_loggable.c
-liblog_target_sources += logprint.c
-liblog_target_sources += log_read.c
-liblog_target_sources += log_event_list.c
+liblog_sources := logd_write.c log_event_list.c log_event_write.c
+liblog_host_sources := $(liblog_sources) fake_log_device.c event.logtags
+liblog_target_sources := $(liblog_sources) event_tag_map.c
+liblog_target_sources += log_time.cpp log_is_loggable.c logprint.c log_read.c
 
 # Shared and static library for host
 # ========================================================
diff --git a/liblog/log_event_list.c b/liblog/log_event_list.c
index 50a27c0..2213f21 100644
--- a/liblog/log_event_list.c
+++ b/liblog/log_event_list.c
@@ -195,9 +195,10 @@
     return 0;
 }
 
-int android_log_write_string8(android_log_context ctx, const char *value) {
+int android_log_write_string8_len(android_log_context ctx,
+                                  const char *value, size_t maxlen) {
     size_t needed;
-    int32_t len;
+    ssize_t len;
     android_log_context_internal *context;
 
     context = (android_log_context_internal *)ctx;
@@ -208,13 +209,13 @@
         return -EIO;
     }
     if (!value) {
-        return -EINVAL;
+        value = "";
     }
-    len = strlen(value);
-    needed = sizeof(uint8_t) + sizeof(len) + len;
+    len = strnlen(value, maxlen);
+    needed = sizeof(uint8_t) + sizeof(int32_t) + len;
     if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
         /* Truncate string for delivery */
-        len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(len);
+        len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(int32_t);
         if (len <= 0) {
             context->overflow = true;
             return -EIO;
@@ -223,9 +224,15 @@
     context->count[context->list_nest_depth]++;
     context->storage[context->pos + 0] = EVENT_TYPE_STRING;
     copy4LE(&context->storage[context->pos + 1], len);
-    memcpy(&context->storage[context->pos + 5], value, len);
+    if (len) {
+        memcpy(&context->storage[context->pos + 5], value, len);
+    }
     context->pos += needed;
-    return 0;
+    return len;
+}
+
+int android_log_write_string8(android_log_context ctx, const char *value) {
+    return android_log_write_string8_len(ctx, value, MAX_EVENT_PAYLOAD);
 }
 
 int android_log_write_float32(android_log_context ctx, float value) {
diff --git a/liblog/log_event_write.c b/liblog/log_event_write.c
index 0bc42d5..ad42edd 100644
--- a/liblog/log_event_write.c
+++ b/liblog/log_event_write.c
@@ -15,74 +15,33 @@
  */
 
 #include <errno.h>
-#include <string.h>
 
 #include <log/log.h>
-#include <log/logger.h>
 
-#define MAX_EVENT_PAYLOAD 512
 #define MAX_SUBTAG_LEN 32
 
-static inline void copy4LE(uint8_t *buf, size_t pos, int val)
+int __android_log_error_write(int tag, const char *subTag, int32_t uid,
+                              const char *data, uint32_t dataLen)
 {
-    buf[pos] = val & 0xFF;
-    buf[pos+1] = (val >> 8) & 0xFF;
-    buf[pos+2] = (val >> 16) & 0xFF;
-    buf[pos+3] = (val >> 24) & 0xFF;
-}
+    int ret = -EINVAL;
 
-int __android_log_error_write(int tag, const char *subTag, int32_t uid, const char *data,
-                              uint32_t dataLen)
-{
-    uint8_t buf[MAX_EVENT_PAYLOAD];
-    size_t pos = 0;
-    uint32_t subTagLen = 0;
-    uint32_t roomLeftForData = 0;
+    if (subTag && (data || !dataLen)) {
+        android_log_context ctx = create_android_logger(tag);
 
-    if ((subTag == NULL) || ((data == NULL) && (dataLen != 0))) return -EINVAL;
-
-    subTagLen = strlen(subTag);
-
-    // Truncate subtags that are too long.
-    subTagLen = subTagLen > MAX_SUBTAG_LEN ? MAX_SUBTAG_LEN : subTagLen;
-
-    // Truncate dataLen if it is too long.
-    roomLeftForData = MAX_EVENT_PAYLOAD -
-            (1 + // EVENT_TYPE_LIST
-             1 + // Number of elements in list
-             1 + // EVENT_TYPE_STRING
-             sizeof(subTagLen) +
-             subTagLen +
-             1 + // EVENT_TYPE_INT
-             sizeof(uid) +
-             1 + // EVENT_TYPE_STRING
-             sizeof(dataLen));
-    dataLen = dataLen > roomLeftForData ? roomLeftForData : dataLen;
-
-    buf[pos++] = EVENT_TYPE_LIST;
-    buf[pos++] = 3; // Number of elements in the list (subTag, uid, data)
-
-    // Write sub tag.
-    buf[pos++] = EVENT_TYPE_STRING;
-    copy4LE(buf, pos, subTagLen);
-    pos += 4;
-    memcpy(&buf[pos], subTag, subTagLen);
-    pos += subTagLen;
-
-    // Write UID.
-    buf[pos++] = EVENT_TYPE_INT;
-    copy4LE(buf, pos, uid);
-    pos += 4;
-
-    // Write data.
-    buf[pos++] = EVENT_TYPE_STRING;
-    copy4LE(buf, pos, dataLen);
-    pos += 4;
-    if (dataLen != 0)
-    {
-        memcpy(&buf[pos], data, dataLen);
-        pos += dataLen;
+        ret = -ENOMEM;
+        if (ctx) {
+            ret = android_log_write_string8_len(ctx, subTag, MAX_SUBTAG_LEN);
+            if (ret >= 0) {
+                ret = android_log_write_int32(ctx, uid);
+                if (ret >= 0) {
+                    ret = android_log_write_string8_len(ctx, data, dataLen);
+                    if (ret >= 0) {
+                        ret = android_log_write_list(ctx, LOG_ID_EVENTS);
+                    }
+                }
+            }
+            android_log_destroy(&ctx);
+        }
     }
-
-    return __android_log_bwrite(tag, buf, pos);
+    return ret;
 }
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 1317853..50ecd2d 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -1429,7 +1429,7 @@
     const int TAG = 123456782;
     const char SUBTAG[] = "test-subtag";
     const int UID = -1;
-    const int DATA_LEN = SIZEOF_MAX_PAYLOAD_BUF;
+    const int DATA_LEN = sizeof(max_payload_buf);
     struct logger_list *logger_list;
 
     pid_t pid = getpid();
@@ -1500,9 +1500,9 @@
         }
         eventData += dataLen;
 
-        // 4 bytes for the tag, and 512 bytes for the log since the
-        // max_payload_buf should be truncated.
-        ASSERT_EQ(4 + 512, eventData - original);
+        // 4 bytes for the tag, and max_payload_buf should be truncated.
+        ASSERT_LE(4 + 512, eventData - original);      // worst expectations
+        ASSERT_GT(4 + DATA_LEN, eventData - original); // must be truncated
 
         ++count;
     }
@@ -2123,6 +2123,30 @@
     return "[1,[2,[3,[4,[5,[6]]]]]]";
 }
 
+static const char *event_test_android_log_error_write(uint32_t tag, size_t &expected_len) {
+    EXPECT_LE(0, __android_log_error_write(tag, "Hello World", 42, "dlroW olleH", 11));
+
+    expected_len = sizeof(uint32_t) +
+      sizeof(uint8_t) + sizeof(uint8_t) +
+          sizeof(uint8_t) + sizeof(uint32_t) + sizeof("Hello World") - 1 +
+          sizeof(uint8_t) + sizeof(uint32_t) +
+          sizeof(uint8_t) + sizeof(uint32_t) + sizeof("dlroW olleH") - 1;
+
+    return "[Hello World,42,dlroW olleH]";
+}
+
+static const char *event_test_android_log_error_write_null(uint32_t tag, size_t &expected_len) {
+    EXPECT_LE(0, __android_log_error_write(tag, "Hello World", 42, NULL, 0));
+
+    expected_len = sizeof(uint32_t) +
+      sizeof(uint8_t) + sizeof(uint8_t) +
+          sizeof(uint8_t) + sizeof(uint32_t) + sizeof("Hello World") - 1 +
+          sizeof(uint8_t) + sizeof(uint32_t) +
+          sizeof(uint8_t) + sizeof(uint32_t) + sizeof("") - 1;
+
+    return "[Hello World,42,]";
+}
+
 // make sure all user buffers are flushed
 static void print_barrier() {
     std::cout.flush();
@@ -2241,6 +2265,14 @@
     create_android_logger(event_test_7_level_suffix);
 }
 
+TEST(liblog, create_android_logger_android_log_error_write) {
+    create_android_logger(event_test_android_log_error_write);
+}
+
+TEST(liblog, create_android_logger_android_log_error_write_null) {
+    create_android_logger(event_test_android_log_error_write_null);
+}
+
 TEST(liblog, create_android_logger_overflow) {
     android_log_context ctx;