liblog: add LOGGER_STDERR frontend

Standalone, this logger provides no end-to-end capability.  Only
provides a writer, no reader transport.  All output goes, logcat-like,
into the stderr stream.  Output can be adjusted with environment
variables ANDROID_PRINTF_LOG and ANDROID_LOG_TAGS.

liblog_*.__android_log_bswrite_and_print___max print fails if a string
member is truncated with "Binary log entry conversion failed" and -1.
We expose the truncated content in the tests and in LOGGER_STDERR.

The purpose of this transport selection is for command-line tools,
providing a means to shunt the logs to be mixed in with the tool's
error stream.

Test: gTest liblog-unit-tests
Bug: 27405083
Change-Id: If344b6e3e67df2dc86ce317cfad8af8e857727b7
diff --git a/liblog/config_write.c b/liblog/config_write.c
index 583dcff..6a6c220 100644
--- a/liblog/config_write.c
+++ b/liblog/config_write.c
@@ -78,6 +78,29 @@
                                     &fakeLoggerWrite);
 #endif
     }
+
+    if (__android_log_frontend & LOGGER_STDERR) {
+        extern struct android_log_transport_write stderrLoggerWrite;
+
+        /*
+         * stderr logger should be primary if we can be the only one, or if
+         * already in the primary list.  Otherwise land in the persist list.
+         * Remember we can be called here if we are already initialized.
+         */
+        if (list_empty(&__android_log_transport_write)) {
+            __android_log_add_transport(&__android_log_transport_write,
+                                        &stderrLoggerWrite);
+        } else {
+            struct android_log_transport_write *transp;
+            write_transport_for_each(transp, &__android_log_transport_write) {
+                if (transp == &stderrLoggerWrite) {
+                    return;
+                }
+            }
+            __android_log_add_transport(&__android_log_persist_write,
+                                        &stderrLoggerWrite);
+        }
+    }
 }
 
 LIBLOG_HIDDEN void __android_log_config_write_close() {