liblog: Add android_set_log_frontend

android_set_log_frontend allows one to select LOGGER_DEFAULT,
LOGGER_LOGD or LOGGER_NULL, the latter allows a runtime mechanism to
turn logging on or off.  LOGGER_DEFAULT is LOGGER_LOGD.

Test: gTest liblog-unit-tests notably liblog.android_set_log_frontend
      and liblog-benchmarks before and after.
Bug: 27405083
Change-Id: I365dbee9f7d83112da0ef8d1cace748d247773c8
diff --git a/liblog/logger_write.c b/liblog/logger_write.c
index 2599a53..bff77f8 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.c
@@ -25,6 +25,7 @@
 #endif
 
 #include <log/event_tag_map.h>
+#include <log/log_frontend.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 
@@ -618,3 +619,67 @@
 
     return write_to_log(LOG_ID_SECURITY, vec, 4);
 }
+
+static int __write_to_log_null(log_id_t log_id, struct iovec* vec, size_t nr)
+{
+    size_t len, i;
+
+    if ((log_id < LOG_ID_MIN) || (log_id >= LOG_ID_MAX)) {
+        return -EINVAL;
+    }
+
+    for (len = i = 0; i < nr; ++i) {
+        len += vec[i].iov_len;
+    }
+    if (!len) {
+        return -EINVAL;
+    }
+    return len;
+}
+
+/* Following functions need access to our internal write_to_log status */
+
+LIBLOG_ABI_PUBLIC int android_set_log_frontend(int frontend_flag)
+{
+    if (frontend_flag < 0) {
+        return -EINVAL;
+    }
+
+    __android_log_lock();
+
+    if (frontend_flag & LOGGER_NULL) {
+        write_to_log = __write_to_log_null;
+
+        __android_log_unlock();
+
+        return LOGGER_NULL;
+    }
+
+    /* Anything else, act as if LOGGER_DEFAULT */
+
+    /* generically we only expect these two values for write_to_log */
+    if ((write_to_log != __write_to_log_init) &&
+        (write_to_log != __write_to_log_daemon)) {
+        write_to_log = __write_to_log_init;
+    }
+
+    __android_log_unlock();
+
+    return LOGGER_DEFAULT;
+}
+
+LIBLOG_ABI_PUBLIC int android_get_log_frontend()
+{
+    int ret = LOGGER_DEFAULT;
+
+    __android_log_lock();
+    if (write_to_log == __write_to_log_null) {
+        ret = LOGGER_NULL;
+    } else if ((write_to_log != __write_to_log_init) &&
+               (write_to_log != __write_to_log_daemon)) {
+        ret = -EINVAL;
+    }
+    __android_log_unlock();
+
+    return ret;
+}