liblog: suppress pmsg on user builds

- add optimized & cached LIBLOG_HIDDEN __android_log_is_debuggable()
- check when writing, either LOG_ID_SECURITY, SafetyNet or
  debuggable when pushing content to the pmsg buffer.

Bug: 27566046
Change-Id: I85f1b55ec329b38e00f4183836b6ed53046c323d
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 59c696b..302e63c 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -83,6 +83,7 @@
         //       $(LOCAL_PATH)/event.logtags)
         // so make sure we do not regret hard-coding it as follows:
         "-DLIBLOG_LOG_TAG=1005",
+        "-DSNET_EVENT_LOG_TAG=1397638484",
     ],
     compile_multilib: "both",
     stl: "none",
diff --git a/liblog/Android.mk b/liblog/Android.mk
index 01c8e77..b24b489 100644
--- a/liblog/Android.mk
+++ b/liblog/Android.mk
@@ -23,6 +23,7 @@
 #       $(LOCAL_PATH)/event.logtags)
 # so make sure we do not regret hard-coding it as follows:
 liblog_cflags := -DLIBLOG_LOG_TAG=1005
+liblog_cflags += -DSNET_EVENT_LOG_TAG=1397638484
 
 liblog_sources := log_event_list.c log_event_write.c logger_write.c
 liblog_sources += config_write.c logger_name.c logger_lock.c
diff --git a/liblog/log_is_loggable.c b/liblog/log_is_loggable.c
index 551fa76..79a5670 100644
--- a/liblog/log_is_loggable.c
+++ b/liblog/log_is_loggable.c
@@ -259,6 +259,37 @@
     return logLevel >= 0 && prio >= logLevel;
 }
 
+LIBLOG_HIDDEN int __android_log_is_debuggable()
+{
+    static uint32_t serial;
+    static struct cache tag_cache;
+    static const char key[] = "ro.debuggable";
+    int ret;
+
+    if (tag_cache.c) { /* ro property does not change after set */
+        ret = tag_cache.c == '1';
+    } else if (lock()) {
+        struct cache temp_cache = { NULL, -1, '\0' };
+        refresh_cache(&temp_cache, key);
+        ret = temp_cache.c == '1';
+    } else {
+        int change_detected = check_cache(&tag_cache);
+        uint32_t current_serial = __system_property_area_serial();
+        if (current_serial != serial) {
+            change_detected = 1;
+        }
+        if (change_detected) {
+            refresh_cache(&tag_cache, key);
+            serial = current_serial;
+        }
+        ret = tag_cache.c == '1';
+
+        unlock();
+    }
+
+    return ret;
+}
+
 /*
  * For properties that are read often, but generally remain constant.
  * Since a change is rare, we will accept a trylock failure gracefully.
diff --git a/liblog/logger.h b/liblog/logger.h
index 5d031d7..c727f29 100644
--- a/liblog/logger.h
+++ b/liblog/logger.h
@@ -154,6 +154,7 @@
 LIBLOG_HIDDEN void __android_log_lock();
 LIBLOG_HIDDEN int __android_log_trylock();
 LIBLOG_HIDDEN void __android_log_unlock();
+LIBLOG_HIDDEN int __android_log_is_debuggable();
 
 __END_DECLS
 
diff --git a/liblog/pmsg_writer.c b/liblog/pmsg_writer.c
index 7034ceb..9cd3c48 100644
--- a/liblog/pmsg_writer.c
+++ b/liblog/pmsg_writer.c
@@ -73,6 +73,11 @@
     if (logId > LOG_ID_SECURITY) {
         return -EINVAL;
     }
+    if ((logId != LOG_ID_SECURITY) &&
+            (logId != LOG_ID_EVENTS) &&
+            !__android_log_is_debuggable()) {
+        return -EINVAL;
+    }
     if (pmsgLoggerWrite.context.fd < 0) {
         if (access("/dev/pmsg0", W_OK) == 0) {
             return 0;
@@ -82,6 +87,14 @@
     return 1;
 }
 
+/*
+ * Extract a 4-byte value from a byte stream.
+ */
+static inline uint32_t get4LE(const uint8_t* src)
+{
+    return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
+}
+
 static int pmsgWrite(log_id_t logId, struct timespec *ts,
                       struct iovec *vec, size_t nr)
 {
@@ -92,6 +105,16 @@
     size_t i, payloadSize;
     ssize_t ret;
 
+    if ((logId == LOG_ID_EVENTS) && !__android_log_is_debuggable()) {
+        if (vec[0].iov_len < 4) {
+            return -EINVAL;
+        }
+
+        if (SNET_EVENT_LOG_TAG != get4LE(vec[0].iov_base)) {
+            return -EPERM;
+        }
+    }
+
     if (pmsgLoggerWrite.context.fd < 0) {
         return -EBADF;
     }