Merge "Add functions in recovery/minzip to libziparchive"
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 094988a..78434a0 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -35,7 +35,8 @@
 #include <scoped_minijail.h>
 
 #include "debuggerd/client.h"
-#include "private/android_filesystem_config.h"
+#include <private/android_filesystem_config.h>
+#include <private/android_logger.h>
 #include "selinux/android.h"
 
 #include "adb.h"
@@ -48,7 +49,7 @@
 
 static void drop_capabilities_bounding_set_if_needed(struct minijail *j) {
 #if defined(ALLOW_ADBD_ROOT)
-    if (android::base::GetBoolProperty("ro.debuggable", false)) {
+    if (__android_log_is_debuggable()) {
         return;
     }
 #endif
@@ -68,7 +69,7 @@
     // ro.secure:
     //   Drop privileges by default. Set to 1 on userdebug and user builds.
     bool ro_secure = android::base::GetBoolProperty("ro.secure", true);
-    bool ro_debuggable = android::base::GetBoolProperty("ro.debuggable", false);
+    bool ro_debuggable = __android_log_is_debuggable();
 
     // Drop privileges if ro.secure is set...
     bool drop = ro_secure;
diff --git a/adb/services.cpp b/adb/services.cpp
index 0c3dd00..2fbc15a 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -38,8 +38,9 @@
 #include <cutils/sockets.h>
 
 #if !ADB_HOST
-#include "cutils/android_reboot.h"
 #include <android-base/properties.h>
+#include <cutils/android_reboot.h>
+#include <private/android_logger.h>
 #endif
 
 #include "adb.h"
@@ -73,7 +74,7 @@
         WriteFdExactly(fd, "adbd is already running as root\n");
         adb_close(fd);
     } else {
-        if (!android::base::GetBoolProperty("ro.debuggable", false)) {
+        if (!__android_log_is_debuggable()) {
             WriteFdExactly(fd, "adbd cannot run as root in production builds\n");
             adb_close(fd);
             return;
diff --git a/adb/set_verity_enable_state_service.cpp b/adb/set_verity_enable_state_service.cpp
index ae628e4..f9e028b 100644
--- a/adb/set_verity_enable_state_service.cpp
+++ b/adb/set_verity_enable_state_service.cpp
@@ -26,6 +26,7 @@
 
 #include "android-base/properties.h"
 #include "android-base/stringprintf.h"
+#include <private/android_logger.h>
 
 #include "adb.h"
 #include "adb_io.h"
@@ -102,8 +103,7 @@
         WriteFdFmt(fd, "verity not enabled - ENG build\n");
         return;
     }
-
-    if (!android::base::GetBoolProperty("ro.debuggable", false)) {
+    if (!__android_log_is_debuggable()) {
         WriteFdFmt(fd, "verity cannot be disabled/enabled - USER build\n");
         return;
     }
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index fff6049..3a57174 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -32,6 +32,7 @@
 
 #if !ADB_HOST
 #include <android-base/properties.h>
+#include <private/android_logger.h>
 #endif
 
 #include "adb.h"
@@ -416,12 +417,7 @@
     D("LS(%d): bound to '%s' via %d", s->id, name, fd);
 
 #if !ADB_HOST
-    bool debuggable = false;
-    if (!strncmp(name, "root:", 5)) {
-        debuggable = android::base::GetBoolProperty("ro.debuggable", false);
-    }
-
-    if ((!strncmp(name, "root:", 5) && getuid() != 0 && debuggable) ||
+    if ((!strncmp(name, "root:", 5) && getuid() != 0 && __android_log_is_debuggable()) ||
         (!strncmp(name, "unroot:", 7) && getuid() == 0) ||
         !strncmp(name, "usb:", 4) ||
         !strncmp(name, "tcpip:", 6)) {
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 1fc850f..155b309 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -120,6 +120,7 @@
     libbacktrace \
     libbase \
     libcutils \
+    liblog
 
 debuggerd_c_includes := \
     $(LOCAL_PATH)/test \
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index c87182e..e2461c0 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -32,13 +32,13 @@
 #include <memory>
 #include <string>
 
-#include <android/log.h>
 #include <android-base/stringprintf.h>
 #include <backtrace/Backtrace.h>
 #include <backtrace/BacktraceMap.h>
 #include <cutils/properties.h>
 #include <log/logprint.h>
 #include <private/android_filesystem_config.h>
+#include <private/android_logger.h>
 
 #include <selinux/android.h>
 
@@ -622,9 +622,7 @@
 static void dump_crash(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid,
                        const std::set<pid_t>& siblings, uintptr_t abort_msg_address) {
   // don't copy log messages to tombstone unless this is a dev device
-  char value[PROPERTY_VALUE_MAX];
-  property_get("ro.debuggable", value, "0");
-  bool want_logs = (value[0] == '1');
+  bool want_logs = __android_log_is_debuggable();
 
   _LOG(log, logtype::HEADER,
        "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 2ed6b91..d570255 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -41,6 +41,7 @@
 #include <linux/loop.h>
 #include <logwrap/logwrap.h>
 #include <private/android_filesystem_config.h>
+#include <private/android_logger.h>
 
 #include "fs_mgr_priv.h"
 #include "fs_mgr_priv_verity.h"
@@ -260,15 +261,6 @@
     return ret;
 }
 
-static int device_is_debuggable() {
-    int ret = -1;
-    char value[PROP_VALUE_MAX];
-    ret = __system_property_get("ro.debuggable", value);
-    if (ret < 0)
-        return ret;
-    return strcmp(value, "1") ? 0 : 1;
-}
-
 static int device_is_secure() {
     int ret = -1;
     char value[PROP_VALUE_MAX];
@@ -537,7 +529,7 @@
 
         if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
             int rc = fs_mgr_setup_verity(&fstab->recs[i]);
-            if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
+            if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
                 INFO("Verity disabled");
             } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
                 ERROR("Could not set up verified partition, skipping!\n");
@@ -699,7 +691,7 @@
 
         if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
             int rc = fs_mgr_setup_verity(&fstab->recs[i]);
-            if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
+            if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
                 INFO("Verity disabled");
             } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
                 ERROR("Could not set up verified partition, skipping!\n");
@@ -903,7 +895,7 @@
 {
     if ((fstab_rec->fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
         int rc = fs_mgr_setup_verity(fstab_rec);
-        if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
+        if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
             INFO("Verity disabled");
             return FS_MGR_EARLY_SETUP_VERITY_NO_VERITY;
         } else if (rc == FS_MGR_SETUP_VERITY_SUCCESS) {
diff --git a/include/private/android_logger.h b/include/private/android_logger.h
index 141001c..94095d1 100644
--- a/include/private/android_logger.h
+++ b/include/private/android_logger.h
@@ -130,6 +130,8 @@
 int __android_log_security_bswrite(int32_t tag, const char *payload);
 int __android_log_security(); /* Device Owner is present */
 
+int __android_log_is_debuggable();
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/libcutils/trace-dev.c b/libcutils/trace-dev.c
index dcd9582..113f423 100644
--- a/libcutils/trace-dev.c
+++ b/libcutils/trace-dev.c
@@ -26,10 +26,10 @@
 #include <string.h>
 #include <sys/types.h>
 
-#include <android/log.h>
 #include <cutils/compiler.h>
 #include <cutils/properties.h>
 #include <cutils/trace.h>
+#include <private/android_logger.h>
 
 /**
  * Maximum size of a message that can be logged to the trace buffer.
@@ -86,16 +86,9 @@
 // Determine whether application-level tracing is enabled for this process.
 static bool atrace_is_app_tracing_enabled()
 {
-    bool sys_debuggable = false;
-    char value[PROPERTY_VALUE_MAX];
+    bool sys_debuggable = __android_log_is_debuggable();
     bool result = false;
 
-    // Check whether the system is debuggable.
-    property_get("ro.debuggable", value, "0");
-    if (value[0] == '1') {
-        sys_debuggable = true;
-    }
-
     if (sys_debuggable || atrace_is_debuggable) {
         // Check whether tracing is enabled for this process.
         FILE * file = fopen("/proc/self/cmdline", "re");
diff --git a/liblog/fake_log_device.c b/liblog/fake_log_device.c
index 7bd1f83..5f7f05b 100644
--- a/liblog/fake_log_device.c
+++ b/liblog/fake_log_device.c
@@ -727,3 +727,8 @@
     int logLevel = def;
     return logLevel >= 0 && prio >= logLevel;
 }
+
+LIBLOG_ABI_PRIVATE int __android_log_is_debuggable()
+{
+    return 1;
+}
diff --git a/liblog/log_is_loggable.c b/liblog/log_is_loggable.c
index 4af8507..3dfc6a6 100644
--- a/liblog/log_is_loggable.c
+++ b/liblog/log_is_loggable.c
@@ -274,7 +274,7 @@
     return logLevel >= 0 && prio >= logLevel;
 }
 
-LIBLOG_HIDDEN int __android_log_is_debuggable()
+LIBLOG_ABI_PRIVATE int __android_log_is_debuggable()
 {
     static uint32_t serial;
     static struct cache tag_cache;
diff --git a/liblog/logd_reader.c b/liblog/logd_reader.c
index 563b5c7..71ff075 100644
--- a/liblog/logd_reader.c
+++ b/liblog/logd_reader.c
@@ -482,17 +482,17 @@
     struct sigaction old_sigaction;
     unsigned int old_alarm = 0;
     char buffer[256], *cp, c;
-    int e, ret, remaining;
-
-    int sock = transp->context.sock;
-    if (sock > 0) {
-        return sock;
-    }
+    int e, ret, remaining, sock;
 
     if (!logger_list) {
         return -EINVAL;
     }
 
+    sock = atomic_load(&transp->context.sock);
+    if (sock > 0) {
+        return sock;
+    }
+
     sock = socket_local_client("logdr",
                                ANDROID_SOCKET_NAMESPACE_RESERVED,
                                SOCK_SEQPACKET);
@@ -587,7 +587,11 @@
         return ret;
     }
 
-    return transp->context.sock = sock;
+    ret = atomic_exchange(&transp->context.sock, sock);
+    if ((ret > 0) && (ret != sock)) {
+        close(ret);
+    }
+    return sock;
 }
 
 /* Read from the selected logs */
@@ -662,8 +666,8 @@
 static void logdClose(struct android_log_logger_list *logger_list __unused,
                       struct android_log_transport_context *transp)
 {
-    if (transp->context.sock > 0) {
-        close (transp->context.sock);
-        transp->context.sock = -1;
+    int sock = atomic_exchange(&transp->context.sock, -1);
+    if (sock > 0) {
+        close (sock);
     }
 }
diff --git a/liblog/logd_writer.c b/liblog/logd_writer.c
index e8e392d..2913507 100644
--- a/liblog/logd_writer.c
+++ b/liblog/logd_writer.c
@@ -31,7 +31,6 @@
 #include <time.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <cutils/sockets.h>
 #include <log/logger.h>
 #include <private/android_filesystem_config.h>
@@ -65,7 +64,8 @@
 {
     int i, ret = 0;
 
-    if (logdLoggerWrite.context.sock < 0) {
+    i = atomic_load(&logdLoggerWrite.context.sock);
+    if (i < 0) {
         i = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
         if (i < 0) {
             ret = -errno;
@@ -80,7 +80,11 @@
                 ret = -errno;
                 close(i);
             } else {
-                logdLoggerWrite.context.sock = i;
+                ret = atomic_exchange(&logdLoggerWrite.context.sock, i);
+                if ((ret >= 0) && (ret != i)) {
+                    close(ret);
+                }
+                ret = 0;
             }
         }
     }
@@ -90,9 +94,9 @@
 
 static void logdClose()
 {
-    if (logdLoggerWrite.context.sock >= 0) {
-        close(logdLoggerWrite.context.sock);
-        logdLoggerWrite.context.sock = -1;
+    int sock = atomic_exchange(&logdLoggerWrite.context.sock, -1);
+    if (sock >= 0) {
+        close(sock);
     }
 }
 
@@ -101,7 +105,7 @@
     if (logId > LOG_ID_SECURITY) {
         return -EINVAL;
     }
-    if (logdLoggerWrite.context.sock < 0) {
+    if (atomic_load(&logdLoggerWrite.context.sock) < 0) {
         if (access("/dev/socket/logdw", W_OK) == 0) {
             return 0;
         }
@@ -121,7 +125,7 @@
     static atomic_int_fast32_t dropped;
     static atomic_int_fast32_t droppedSecurity;
 
-    if (logdLoggerWrite.context.sock < 0) {
+    if (atomic_load(&logdLoggerWrite.context.sock) < 0) {
         return -EBADF;
     }
 
@@ -160,7 +164,7 @@
     newVec[0].iov_base = (unsigned char *)&header;
     newVec[0].iov_len  = sizeof(header);
 
-    if (logdLoggerWrite.context.sock > 0) {
+    if (atomic_load(&logdLoggerWrite.context.sock) > 0) {
         int32_t snapshot = atomic_exchange_explicit(&droppedSecurity, 0,
                                                     memory_order_relaxed);
         if (snapshot) {
@@ -174,7 +178,8 @@
             newVec[headerLength].iov_base = &buffer;
             newVec[headerLength].iov_len  = sizeof(buffer);
 
-            ret = TEMP_FAILURE_RETRY(writev(logdLoggerWrite.context.sock, newVec, 2));
+            ret = TEMP_FAILURE_RETRY(writev(
+                    atomic_load(&logdLoggerWrite.context.sock), newVec, 2));
             if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
                 atomic_fetch_add_explicit(&droppedSecurity, snapshot,
                                           memory_order_relaxed);
@@ -194,7 +199,8 @@
             newVec[headerLength].iov_base = &buffer;
             newVec[headerLength].iov_len  = sizeof(buffer);
 
-            ret = TEMP_FAILURE_RETRY(writev(logdLoggerWrite.context.sock, newVec, 2));
+            ret = TEMP_FAILURE_RETRY(writev(
+                      atomic_load(&logdLoggerWrite.context.sock), newVec, 2));
             if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
                 atomic_fetch_add_explicit(&dropped, snapshot,
                                           memory_order_relaxed);
@@ -223,7 +229,8 @@
      * ENOTCONN occurs if logd dies.
      * EAGAIN occurs if logd is overloaded.
      */
-    ret = TEMP_FAILURE_RETRY(writev(logdLoggerWrite.context.sock, newVec, i));
+    ret = TEMP_FAILURE_RETRY(writev(
+            atomic_load(&logdLoggerWrite.context.sock), newVec, i));
     if (ret < 0) {
         ret = -errno;
         if (ret == -ENOTCONN) {
@@ -236,7 +243,8 @@
                 return ret;
             }
 
-            ret = TEMP_FAILURE_RETRY(writev(logdLoggerWrite.context.sock, newVec, i));
+            ret = TEMP_FAILURE_RETRY(writev(
+                    atomic_load(&logdLoggerWrite.context.sock), newVec, i));
             if (ret < 0) {
                 ret = -errno;
             }
diff --git a/liblog/logger.h b/liblog/logger.h
index 8fb2b4d..d2aebcb 100644
--- a/liblog/logger.h
+++ b/liblog/logger.h
@@ -17,6 +17,7 @@
 #ifndef _LIBLOG_LOGGER_H__
 #define _LIBLOG_LOGGER_H__
 
+#include <stdatomic.h>
 #include <stdbool.h>
 #include <log/uio.h>
 
@@ -31,9 +32,10 @@
 /* Union, sock or fd of zero is not allowed unless static initialized */
 union android_log_context {
   void *private;
-  int sock;
-  int fd;
+  atomic_int sock;
+  atomic_int fd;
   struct listnode *node;
+  atomic_uintptr_t atomic_pointer;
 };
 
 struct android_log_transport_write {
@@ -155,7 +157,6 @@
 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_reader.c b/liblog/pmsg_reader.c
index 679c159..a0a69c1 100644
--- a/liblog/pmsg_reader.c
+++ b/liblog/pmsg_reader.c
@@ -151,8 +151,8 @@
 
     memset(log_msg, 0, sizeof(*log_msg));
 
-    if (transp->context.fd <= 0) {
-        int fd = open("/sys/fs/pstore/pmsg-ramoops-0", O_RDONLY | O_CLOEXEC);
+    if (atomic_load(&transp->context.fd) <= 0) {
+        int i, fd = open("/sys/fs/pstore/pmsg-ramoops-0", O_RDONLY | O_CLOEXEC);
 
         if (fd < 0) {
             return -errno;
@@ -164,13 +164,22 @@
                 return -errno;
             }
         }
-        transp->context.fd = fd;
+        i = atomic_exchange(&transp->context.fd, fd);
+        if ((i > 0) && (i != fd)) {
+            close(i);
+        }
         preread_count = 0;
     }
 
     while(1) {
+        int fd;
+
         if (preread_count < sizeof(buf)) {
-            ret = TEMP_FAILURE_RETRY(read(transp->context.fd,
+            fd = atomic_load(&transp->context.fd);
+            if (fd <= 0) {
+                return -EBADF;
+            }
+            ret = TEMP_FAILURE_RETRY(read(fd,
                                           &buf.p.magic + preread_count,
                                           sizeof(buf) - preread_count));
             if (ret < 0) {
@@ -212,9 +221,13 @@
                     log_msg->entry_v4.msg :
                     log_msg->entry_v3.msg;
                 *msg = buf.prio;
-                ret = TEMP_FAILURE_RETRY(read(transp->context.fd,
-                                          msg + sizeof(buf.prio),
-                                          buf.p.len - sizeof(buf)));
+                fd = atomic_load(&transp->context.fd);
+                if (fd <= 0) {
+                    return -EBADF;
+                }
+                ret = TEMP_FAILURE_RETRY(read(fd,
+                                              msg + sizeof(buf.prio),
+                                              buf.p.len - sizeof(buf)));
                 if (ret < 0) {
                     return -errno;
                 }
@@ -239,12 +252,19 @@
             }
         }
 
-        current = TEMP_FAILURE_RETRY(lseek(transp->context.fd,
-                                           (off_t)0, SEEK_CUR));
+        fd = atomic_load(&transp->context.fd);
+        if (fd <= 0) {
+            return -EBADF;
+        }
+        current = TEMP_FAILURE_RETRY(lseek(fd, (off_t)0, SEEK_CUR));
         if (current < 0) {
             return -errno;
         }
-        next = TEMP_FAILURE_RETRY(lseek(transp->context.fd,
+        fd = atomic_load(&transp->context.fd);
+        if (fd <= 0) {
+            return -EBADF;
+        }
+        next = TEMP_FAILURE_RETRY(lseek(fd,
                                         (off_t)(buf.p.len - sizeof(buf)),
                                         SEEK_CUR));
         if (next < 0) {
@@ -258,10 +278,10 @@
 
 static void pmsgClose(struct android_log_logger_list *logger_list __unused,
                       struct android_log_transport_context *transp) {
-    if (transp->context.fd > 0) {
-        close (transp->context.fd);
+    int fd = atomic_exchange(&transp->context.fd, 0);
+    if (fd > 0) {
+        close (fd);
     }
-    transp->context.fd = 0;
 }
 
 LIBLOG_ABI_PRIVATE ssize_t __android_log_pmsg_file_read(
diff --git a/liblog/pmsg_writer.c b/liblog/pmsg_writer.c
index 06652f3..b3c4a1a 100644
--- a/liblog/pmsg_writer.c
+++ b/liblog/pmsg_writer.c
@@ -20,6 +20,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
@@ -53,18 +54,25 @@
 
 static int pmsgOpen()
 {
-    if (pmsgLoggerWrite.context.fd < 0) {
-        pmsgLoggerWrite.context.fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
+    int fd = atomic_load(&pmsgLoggerWrite.context.fd);
+    if (fd < 0) {
+        int i;
+
+        fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
+        i = atomic_exchange(&pmsgLoggerWrite.context.fd, fd);
+        if ((i >= 0) && (i != fd)) {
+            close(i);
+        }
     }
 
-    return pmsgLoggerWrite.context.fd;
+    return fd;
 }
 
 static void pmsgClose()
 {
-    if (pmsgLoggerWrite.context.fd >= 0) {
-        close(pmsgLoggerWrite.context.fd);
-        pmsgLoggerWrite.context.fd = -1;
+    int fd = atomic_exchange(&pmsgLoggerWrite.context.fd, -1);
+    if (fd >= 0) {
+        close(fd);
     }
 }
 
@@ -78,7 +86,7 @@
             !__android_log_is_debuggable()) {
         return -EINVAL;
     }
-    if (pmsgLoggerWrite.context.fd < 0) {
+    if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
         if (access("/dev/pmsg0", W_OK) == 0) {
             return 0;
         }
@@ -115,7 +123,7 @@
         }
     }
 
-    if (pmsgLoggerWrite.context.fd < 0) {
+    if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
         return -EBADF;
     }
 
@@ -169,7 +177,8 @@
     }
     pmsgHeader.len += payloadSize;
 
-    ret = TEMP_FAILURE_RETRY(writev(pmsgLoggerWrite.context.fd, newVec, i));
+    ret = TEMP_FAILURE_RETRY(writev(atomic_load(&pmsgLoggerWrite.context.fd),
+                                    newVec, i));
     if (ret < 0) {
         ret = errno ? -errno : -ENOTCONN;
     }
@@ -206,7 +215,7 @@
         char prio,
         const char *filename,
         const char *buf, size_t len) {
-    int fd;
+    bool weOpened;
     size_t length, packet_len;
     const char *tag;
     char *cp, *slash;
@@ -228,16 +237,6 @@
         return -ENOMEM;
     }
 
-    fd = pmsgLoggerWrite.context.fd;
-    if (fd < 0) {
-        __android_log_lock();
-        fd = pmsgOpen();
-        __android_log_unlock();
-        if (fd < 0) {
-            return -EBADF;
-        }
-    }
-
     tag = cp;
     slash = strrchr(cp, '/');
     if (slash) {
@@ -256,6 +255,7 @@
     vec[1].iov_base = (unsigned char *)tag;
     vec[1].iov_len  = length;
 
+    weOpened = false;
     for (ts.tv_nsec = 0, length = len;
             length;
             ts.tv_nsec += ANDROID_LOG_PMSG_FILE_SEQUENCE) {
@@ -279,15 +279,36 @@
         vec[2].iov_base = (unsigned char *)buf;
         vec[2].iov_len  = transfer;
 
+        if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
+            if (!weOpened) { /* Impossible for weOpened = true here */
+                __android_log_lock();
+            }
+            weOpened = atomic_load(&pmsgLoggerWrite.context.fd) < 0;
+            if (!weOpened) {
+                __android_log_unlock();
+            } else if (pmsgOpen() < 0) {
+                __android_log_unlock();
+                return -EBADF;
+            }
+        }
+
         ret = pmsgWrite(logId, &ts, vec, sizeof(vec) / sizeof(vec[0]));
 
         if (ret <= 0) {
+            if (weOpened) {
+                pmsgClose();
+                __android_log_unlock();
+            }
             free(cp);
-            return ret;
+            return ret ? ret : (len - length);
         }
         length -= transfer;
         buf += transfer;
     }
+    if (weOpened) {
+        pmsgClose();
+        __android_log_unlock();
+    }
     free(cp);
     return len;
 }
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index b1dae9e..7db048d 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -20,6 +20,7 @@
 #include <inttypes.h>
 #include <semaphore.h>
 #include <signal.h>
+#include <stdio.h>
 #include <string.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -129,6 +130,70 @@
     ASSERT_LT(0, ret);
 }
 
+std::string popenToString(std::string command) {
+    std::string ret;
+
+    FILE* fp = popen(command.c_str(), "r");
+    if (fp) {
+        if (!android::base::ReadFdToString(fileno(fp), &ret)) ret = "";
+        pclose(fp);
+    }
+    return ret;
+}
+
+static bool isPmsgActive() {
+    pid_t pid = getpid();
+
+    std::string myPidFds = popenToString(android::base::StringPrintf(
+                                             "ls -l /proc/%d/fd", pid));
+    if (myPidFds.length() == 0) return true; // guess it is?
+
+    return std::string::npos != myPidFds.find(" -> /dev/pmsg0");
+}
+
+static bool isLogdwActive() {
+    std::string logdwSignature = popenToString(
+        "grep /dev/socket/logdw /proc/net/unix");
+    size_t beginning = logdwSignature.find(" ");
+    if (beginning == std::string::npos) return true;
+    beginning = logdwSignature.find(" ", beginning + 1);
+    if (beginning == std::string::npos) return true;
+    size_t end = logdwSignature.find(" ", beginning + 1);
+    if (end == std::string::npos) return true;
+    end = logdwSignature.find(" ", end + 1);
+    if (end == std::string::npos) return true;
+    end = logdwSignature.find(" ", end + 1);
+    if (end == std::string::npos) return true;
+    end = logdwSignature.find(" ", end + 1);
+    if (end == std::string::npos) return true;
+    std::string allLogdwEndpoints = popenToString(
+        "grep ' 00000002" +
+        logdwSignature.substr(beginning, end - beginning) +
+        " ' /proc/net/unix | " +
+        "sed -n 's/.* \\([0-9][0-9]*\\)$/ -> socket:[\\1]/p'");
+    if (allLogdwEndpoints.length() == 0) return true;
+
+    // NB: allLogdwEndpoints has some false positives in it, but those
+    // strangers do not overlap with the simplistic activities inside this
+    // test suite.
+
+    pid_t pid = getpid();
+
+    std::string myPidFds = popenToString(android::base::StringPrintf(
+        "ls -l /proc/%d/fd", pid));
+    if (myPidFds.length() == 0) return true;
+
+    // NB: fgrep with multiple strings is broken in Android
+    for (beginning = 0;
+         (end = allLogdwEndpoints.find("\n", beginning)) != std::string::npos;
+         beginning = end + 1) {
+        if (myPidFds.find(allLogdwEndpoints.substr(beginning,
+                                                   end - beginning)) !=
+            std::string::npos) return true;
+    }
+    return false;
+}
+
 TEST(liblog, __android_log_btwrite__android_logger_list_read) {
     struct logger_list *logger_list;
 
@@ -140,10 +205,22 @@
     // Check that we can close and reopen the logger
     log_time ts(CLOCK_MONOTONIC);
     ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
+    bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
+    bool logdwActiveAfter__android_log_btwrite = isLogdwActive();
+    EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
+    EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
     __android_log_close();
+    bool pmsgActiveAfter__android_log_close = isPmsgActive();
+    bool logdwActiveAfter__android_log_close = isLogdwActive();
+    EXPECT_FALSE(pmsgActiveAfter__android_log_close);
+    EXPECT_FALSE(logdwActiveAfter__android_log_close);
 
     log_time ts1(CLOCK_MONOTONIC);
     ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
+    pmsgActiveAfter__android_log_btwrite = isPmsgActive();
+    logdwActiveAfter__android_log_btwrite = isLogdwActive();
+    EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
+    EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
     usleep(1000000);
 
     int count = 0;
@@ -2575,12 +2652,35 @@
         "/data/william-shakespeare/MuchAdoAboutNothing.txt";
 
 TEST(liblog, __android_log_pmsg_file_write) {
+    __android_log_close();
+    bool pmsgActiveAfter__android_log_close = isPmsgActive();
+    bool logdwActiveAfter__android_log_close = isLogdwActive();
+    EXPECT_FALSE(pmsgActiveAfter__android_log_close);
+    EXPECT_FALSE(logdwActiveAfter__android_log_close);
     EXPECT_LT(0, __android_log_pmsg_file_write(
             LOG_ID_CRASH, ANDROID_LOG_VERBOSE,
             __pmsg_file, max_payload_buf, sizeof(max_payload_buf)));
     fprintf(stderr, "Reboot, ensure file %s matches\n"
                     "with liblog.__android_log_msg_file_read test\n",
                     __pmsg_file);
+    bool pmsgActiveAfter__android_pmsg_file_write = isPmsgActive();
+    bool logdwActiveAfter__android_pmsg_file_write = isLogdwActive();
+    EXPECT_FALSE(pmsgActiveAfter__android_pmsg_file_write);
+    EXPECT_FALSE(logdwActiveAfter__android_pmsg_file_write);
+    EXPECT_LT(0, __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO,
+                                         "TEST__android_log_pmsg_file_write",
+                                         "main"));
+    bool pmsgActiveAfter__android_log_buf_print = isPmsgActive();
+    bool logdwActiveAfter__android_log_buf_print = isLogdwActive();
+    EXPECT_TRUE(pmsgActiveAfter__android_log_buf_print);
+    EXPECT_TRUE(logdwActiveAfter__android_log_buf_print);
+    EXPECT_LT(0, __android_log_pmsg_file_write(
+            LOG_ID_CRASH, ANDROID_LOG_VERBOSE,
+            __pmsg_file, max_payload_buf, sizeof(max_payload_buf)));
+    pmsgActiveAfter__android_pmsg_file_write = isPmsgActive();
+    logdwActiveAfter__android_pmsg_file_write = isLogdwActive();
+    EXPECT_TRUE(pmsgActiveAfter__android_pmsg_file_write);
+    EXPECT_TRUE(logdwActiveAfter__android_pmsg_file_write);
 }
 
 ssize_t __pmsg_fn(log_id_t logId, char prio, const char *filename,
@@ -2597,7 +2697,7 @@
             strcmp(max_payload_buf, buf)) {
         fprintf(stderr, "comparison fails on content \"%s\"\n", buf);
     }
-    return !arg ||
+    return arg ||
            (LOG_ID_CRASH != logId) ||
            (ANDROID_LOG_VERBOSE != prio) ||
            !strstr(__pmsg_file, filename) ||
@@ -2608,10 +2708,21 @@
 TEST(liblog, __android_log_pmsg_file_read) {
     signaled = 0;
 
+    __android_log_close();
+    bool pmsgActiveAfter__android_log_close = isPmsgActive();
+    bool logdwActiveAfter__android_log_close = isLogdwActive();
+    EXPECT_FALSE(pmsgActiveAfter__android_log_close);
+    EXPECT_FALSE(logdwActiveAfter__android_log_close);
+
     ssize_t ret = __android_log_pmsg_file_read(
             LOG_ID_CRASH, ANDROID_LOG_VERBOSE,
             __pmsg_file, __pmsg_fn, NULL);
 
+    bool pmsgActiveAfter__android_log_pmsg_file_read = isPmsgActive();
+    bool logdwActiveAfter__android_log_pmsg_file_read = isLogdwActive();
+    EXPECT_FALSE(pmsgActiveAfter__android_log_pmsg_file_read);
+    EXPECT_FALSE(logdwActiveAfter__android_log_pmsg_file_read);
+
     if (ret == -ENOENT) {
         fprintf(stderr,
             "No pre-boot results of liblog.__android_log_mesg_file_write to "
diff --git a/logd/main.cpp b/logd/main.cpp
index a0cea25..c47f396 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -44,6 +44,7 @@
 #include <log/event_tag_map.h>
 #include <packagelistparser/packagelistparser.h>
 #include <private/android_filesystem_config.h>
+#include <private/android_logger.h>
 #include <scoped_minijail.h>
 #include <utils/threads.h>
 
@@ -174,11 +175,8 @@
                                  BOOL_DEFAULT_FALSE)) {
         return false;
     }
-    if (flag & BOOL_DEFAULT_FLAG_ENG) {
-        property_get("ro.debuggable", property, "");
-        if (strcmp(property, "1")) {
-            return false;
-        }
+    if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
+        return false;
     }
 
     return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;