Merge "libbase: add parsedouble.h."
diff --git a/Android.bp b/Android.bp
deleted file mode 100644
index 949a7fe..0000000
--- a/Android.bp
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-ndk_headers {
-    name: "liblog_headers",
-    from: "include/android",
-    to: "android",
-    srcs: ["include/android/log.h"],
-}
-
-optional_subdirs = ["*"]
diff --git a/adb/Android.mk b/adb/Android.mk
index 0114ca3..be04cfa 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -18,11 +18,9 @@
     -DADB_REVISION='"$(adb_version)"' \
 
 ADB_COMMON_linux_CFLAGS := \
-    -std=c++14 \
     -Wexit-time-destructors \
 
 ADB_COMMON_darwin_CFLAGS := \
-    -std=c++14 \
     -Wexit-time-destructors \
 
 # Define windows.h and tchar.h Unicode preprocessor symbols so that
@@ -45,7 +43,6 @@
 # get enough of adb in here that we no longer need minadb. https://b/17626262
 LIBADB_SRC_FILES := \
     adb.cpp \
-    adb_auth.cpp \
     adb_io.cpp \
     adb_listeners.cpp \
     adb_trace.cpp \
@@ -103,7 +100,7 @@
 LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=0
 LOCAL_SRC_FILES := \
     $(LIBADB_SRC_FILES) \
-    adb_auth_client.cpp \
+    adbd_auth.cpp \
     jdwp_service.cpp \
     usb_linux_client.cpp \
 
@@ -324,7 +321,6 @@
 LOCAL_FORCE_STATIC_EXECUTABLE := true
 LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
 LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
-LOCAL_C_INCLUDES += system/extras/ext4_utils
 
 LOCAL_SANITIZE := $(adb_target_sanitize)
 LOCAL_STRIP_MODULE := keep_symbols
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 9ae3f1c..29d6e65 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -94,6 +94,18 @@
     abort();
 }
 
+uint32_t calculate_apacket_checksum(const apacket* p) {
+    const unsigned char* x = reinterpret_cast<const unsigned char*>(p->data);
+    uint32_t sum = 0;
+    size_t count = p->msg.data_length;
+
+    while (count-- > 0) {
+        sum += *x++;
+    }
+
+    return sum;
+}
+
 apacket* get_apacket(void)
 {
     apacket* p = reinterpret_cast<apacket*>(malloc(sizeof(apacket)));
@@ -351,19 +363,31 @@
         break;
 
     case A_AUTH:
-        if (p->msg.arg0 == ADB_AUTH_TOKEN) {
-            t->connection_state = kCsUnauthorized;
-            send_auth_response(p->data, p->msg.data_length, t);
-        } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
-            if (adb_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) {
-                adb_auth_verified(t);
-                t->failed_auth_attempts = 0;
-            } else {
-                if (t->failed_auth_attempts++ > 256) adb_sleep_ms(1000);
-                send_auth_request(t);
-            }
-        } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
-            adb_auth_confirm_key(p->data, p->msg.data_length, t);
+        switch (p->msg.arg0) {
+#if ADB_HOST
+            case ADB_AUTH_TOKEN:
+                t->connection_state = kCsUnauthorized;
+                send_auth_response(p->data, p->msg.data_length, t);
+                break;
+#else
+            case ADB_AUTH_SIGNATURE:
+                if (adbd_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) {
+                    adbd_auth_verified(t);
+                    t->failed_auth_attempts = 0;
+                } else {
+                    if (t->failed_auth_attempts++ > 256) adb_sleep_ms(1000);
+                    send_auth_request(t);
+                }
+                break;
+
+            case ADB_AUTH_RSAPUBLICKEY:
+                adbd_auth_confirm_key(p->data, p->msg.data_length, t);
+                break;
+#endif
+            default:
+                t->connection_state = kCsOffline;
+                handle_offline(t);
+                break;
         }
         break;
 
diff --git a/adb/adb.h b/adb/adb.h
index 0b9fe5b..df59aaa 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -18,6 +18,7 @@
 #define __ADB_H
 
 #include <limits.h>
+#include <stdint.h>
 #include <sys/types.h>
 
 #include <string>
@@ -56,25 +57,27 @@
 struct usb_handle;
 
 struct amessage {
-    unsigned command;       /* command identifier constant      */
-    unsigned arg0;          /* first argument                   */
-    unsigned arg1;          /* second argument                  */
-    unsigned data_length;   /* length of payload (0 is allowed) */
-    unsigned data_check;    /* checksum of data payload         */
-    unsigned magic;         /* command ^ 0xffffffff             */
+    uint32_t command;     /* command identifier constant      */
+    uint32_t arg0;        /* first argument                   */
+    uint32_t arg1;        /* second argument                  */
+    uint32_t data_length; /* length of payload (0 is allowed) */
+    uint32_t data_check;  /* checksum of data payload         */
+    uint32_t magic;       /* command ^ 0xffffffff             */
 };
 
 struct apacket
 {
     apacket *next;
 
-    unsigned len;
-    unsigned char *ptr;
+    size_t len;
+    char* ptr;
 
     amessage msg;
-    unsigned char data[MAX_PAYLOAD];
+    char data[MAX_PAYLOAD];
 };
 
+uint32_t calculate_apacket_checksum(const apacket* packet);
+
 /* the adisconnect structure is used to record a callback that
 ** will be called whenever a transport is disconnected (e.g. by the user)
 ** this should be used to cleanup objects that depend on the
@@ -136,8 +139,10 @@
 int  init_socket_transport(atransport *t, int s, int port, int local);
 void init_usb_transport(atransport *t, usb_handle *usb, ConnectionState state);
 
+std::string getEmulatorSerialString(int console_port);
 #if ADB_HOST
 atransport* find_emulator_transport_by_adb_port(int adb_port);
+atransport* find_emulator_transport_by_console_port(int console_port);
 #endif
 
 int service_to_fd(const char* name, const atransport* transport);
@@ -199,7 +204,7 @@
 
 // USB device detection.
 #if ADB_HOST
-int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol);
+int is_adb_interface(int usb_class, int usb_subclass, int usb_protocol);
 #endif
 
 ConnectionState connection_state(atransport *t);
diff --git a/adb/adb_auth.cpp b/adb/adb_auth.cpp
deleted file mode 100644
index 0b07158..0000000
--- a/adb/adb_auth.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define TRACE_TAG ADB
-
-#include "adb.h"
-#include "adb_auth.h"
-#include "transport.h"
-
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-bool auth_required = true;
-
-void send_auth_request(atransport *t)
-{
-    LOG(INFO) << "Calling send_auth_request...";
-
-    if (!adb_auth_generate_token(t->token, sizeof(t->token))) {
-        PLOG(ERROR) << "Error generating token";
-        return;
-    }
-
-    apacket* p = get_apacket();
-    memcpy(p->data, t->token, sizeof(t->token));
-    p->msg.command = A_AUTH;
-    p->msg.arg0 = ADB_AUTH_TOKEN;
-    p->msg.data_length = sizeof(t->token);
-    send_packet(p, t);
-}
-
-static void send_auth_publickey(atransport* t) {
-    LOG(INFO) << "Calling send_auth_publickey";
-
-    std::string key = adb_auth_get_userkey();
-    if (key.empty()) {
-        D("Failed to get user public key");
-        return;
-    }
-
-    if (key.size() >= MAX_PAYLOAD_V1) {
-        D("User public key too large (%zu B)", key.size());
-        return;
-    }
-
-    apacket* p = get_apacket();
-    memcpy(p->data, key.c_str(), key.size() + 1);
-
-    p->msg.command = A_AUTH;
-    p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
-
-    // adbd expects a null-terminated string.
-    p->msg.data_length = key.size() + 1;
-    send_packet(p, t);
-}
-
-void send_auth_response(uint8_t* token, size_t token_size, atransport* t) {
-    std::shared_ptr<RSA> key = t->NextKey();
-    if (key == nullptr) {
-        // No more private keys to try, send the public key.
-        send_auth_publickey(t);
-        return;
-    }
-
-    LOG(INFO) << "Calling send_auth_response";
-    apacket* p = get_apacket();
-
-    int ret = adb_auth_sign(key.get(), token, token_size, p->data);
-    if (!ret) {
-        D("Error signing the token");
-        put_apacket(p);
-        return;
-    }
-
-    p->msg.command = A_AUTH;
-    p->msg.arg0 = ADB_AUTH_SIGNATURE;
-    p->msg.data_length = ret;
-    send_packet(p, t);
-}
-
-void adb_auth_verified(atransport *t)
-{
-    handle_online(t);
-    send_connect(t);
-}
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 59b80d8..a6f224f 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -24,14 +24,6 @@
 
 #include <openssl/rsa.h>
 
-extern bool auth_required;
-
-int adb_auth_keygen(const char* filename);
-void adb_auth_verified(atransport *t);
-
-void send_auth_request(atransport *t);
-void send_auth_response(uint8_t *token, size_t token_size, atransport *t);
-
 /* AUTH packets first argument */
 /* Request */
 #define ADB_AUTH_TOKEN         1
@@ -42,25 +34,25 @@
 #if ADB_HOST
 
 void adb_auth_init();
-int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig);
+
+int adb_auth_keygen(const char* filename);
 std::string adb_auth_get_userkey();
 std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys();
 
-static inline bool adb_auth_generate_token(void*, size_t) { abort(); }
-static inline bool adb_auth_verify(void*, size_t, void*, int) { abort(); }
-static inline void adb_auth_confirm_key(unsigned char*, size_t, atransport*) { abort(); }
+void send_auth_response(const char* token, size_t token_size, atransport* t);
 
 #else // !ADB_HOST
 
-static inline int adb_auth_sign(void*, const unsigned char*, size_t, unsigned char*) { abort(); }
-static inline std::string adb_auth_get_userkey() { abort(); }
-static inline std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys() { abort(); }
+extern bool auth_required;
 
 void adbd_auth_init(void);
+void adbd_auth_verified(atransport *t);
+
 void adbd_cloexec_auth_socket();
-bool adb_auth_generate_token(void* token, size_t token_size);
-bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len);
-void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t);
+bool adbd_auth_verify(const char* token, size_t token_size, const char* sig, int sig_len);
+void adbd_auth_confirm_key(const char* data, size_t len, atransport* t);
+
+void send_auth_request(atransport *t);
 
 #endif // ADB_HOST
 
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index 072c7f5..ff2d76d 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -45,6 +45,7 @@
 #include "adb_auth.h"
 #include "adb_utils.h"
 #include "sysdeps.h"
+#include "transport.h"
 
 static std::mutex& g_keys_mutex = *new std::mutex;
 static std::map<std::string, std::shared_ptr<RSA>>& g_keys =
@@ -297,14 +298,15 @@
     return result;
 }
 
-int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig) {
+static int adb_auth_sign(RSA* key, const char* token, size_t token_size, char* sig) {
     if (token_size != TOKEN_SIZE) {
         D("Unexpected token size %zd", token_size);
         return 0;
     }
 
     unsigned int len;
-    if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key)) {
+    if (!RSA_sign(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size,
+                  reinterpret_cast<uint8_t*>(sig), &len, key)) {
         return 0;
     }
 
@@ -421,3 +423,52 @@
         read_keys(path.c_str());
     }
 }
+
+static void send_auth_publickey(atransport* t) {
+    LOG(INFO) << "Calling send_auth_publickey";
+
+    std::string key = adb_auth_get_userkey();
+    if (key.empty()) {
+        D("Failed to get user public key");
+        return;
+    }
+
+    if (key.size() >= MAX_PAYLOAD_V1) {
+        D("User public key too large (%zu B)", key.size());
+        return;
+    }
+
+    apacket* p = get_apacket();
+    memcpy(p->data, key.c_str(), key.size() + 1);
+
+    p->msg.command = A_AUTH;
+    p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
+
+    // adbd expects a null-terminated string.
+    p->msg.data_length = key.size() + 1;
+    send_packet(p, t);
+}
+
+void send_auth_response(const char* token, size_t token_size, atransport* t) {
+    std::shared_ptr<RSA> key = t->NextKey();
+    if (key == nullptr) {
+        // No more private keys to try, send the public key.
+        send_auth_publickey(t);
+        return;
+    }
+
+    LOG(INFO) << "Calling send_auth_response";
+    apacket* p = get_apacket();
+
+    int ret = adb_auth_sign(key.get(), token, token_size, p->data);
+    if (!ret) {
+        D("Error signing the token");
+        put_apacket(p);
+        return;
+    }
+
+    p->msg.command = A_AUTH;
+    p->msg.arg0 = ADB_AUTH_SIGNATURE;
+    p->msg.data_length = ret;
+    send_packet(p, t);
+}
diff --git a/adb/adb_auth_client.cpp b/adb/adbd_auth.cpp
similarity index 79%
rename from adb/adb_auth_client.cpp
rename to adb/adbd_auth.cpp
index 84ad6ef..b5f87be 100644
--- a/adb/adb_auth_client.cpp
+++ b/adb/adbd_auth.cpp
@@ -44,7 +44,9 @@
 static atransport* usb_transport;
 static bool needs_retry = false;
 
-bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len) {
+bool auth_required = true;
+
+bool adbd_auth_verify(const char* token, size_t token_size, const char* sig, int sig_len) {
     static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr };
 
     for (const auto& path : key_paths) {
@@ -76,7 +78,9 @@
                     continue;
                 }
 
-                bool verified = (RSA_verify(NID_sha1, token, token_size, sig, sig_len, key) == 1);
+                bool verified =
+                    (RSA_verify(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size,
+                                reinterpret_cast<const uint8_t*>(sig), sig_len, key) == 1);
                 RSA_free(key);
                 if (verified) return true;
             }
@@ -85,7 +89,7 @@
     return false;
 }
 
-bool adb_auth_generate_token(void* token, size_t token_size) {
+static bool adbd_auth_generate_token(void* token, size_t token_size) {
     FILE* fp = fopen("/dev/urandom", "re");
     if (!fp) return false;
     bool okay = (fread(token, token_size, 1, fp) == 1);
@@ -105,7 +109,7 @@
     framework_fd = -1;
 }
 
-static void adb_auth_event(int fd, unsigned events, void*) {
+static void adbd_auth_event(int fd, unsigned events, void*) {
     if (events & FDE_READ) {
         char response[2];
         int ret = unix_read(fd, response, sizeof(response));
@@ -113,13 +117,13 @@
             framework_disconnected();
         } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
             if (usb_transport) {
-                adb_auth_verified(usb_transport);
+                adbd_auth_verified(usb_transport);
             }
         }
     }
 }
 
-void adb_auth_confirm_key(unsigned char* key, size_t len, atransport* t) {
+void adbd_auth_confirm_key(const char* key, size_t len, atransport* t) {
     if (!usb_transport) {
         usb_transport = t;
         t->AddDisconnect(&usb_disconnect);
@@ -150,7 +154,7 @@
     }
 }
 
-static void adb_auth_listener(int fd, unsigned events, void* data) {
+static void adbd_auth_listener(int fd, unsigned events, void* data) {
     int s = adb_socket_accept(fd, nullptr, nullptr);
     if (s < 0) {
         PLOG(ERROR) << "Failed to accept";
@@ -163,7 +167,7 @@
     }
 
     framework_fd = s;
-    fdevent_install(&framework_fde, framework_fd, adb_auth_event, nullptr);
+    fdevent_install(&framework_fde, framework_fd, adbd_auth_event, nullptr);
     fdevent_add(&framework_fde, FDE_READ);
 
     if (needs_retry) {
@@ -193,6 +197,28 @@
         return;
     }
 
-    fdevent_install(&listener_fde, fd, adb_auth_listener, NULL);
+    fdevent_install(&listener_fde, fd, adbd_auth_listener, NULL);
     fdevent_add(&listener_fde, FDE_READ);
 }
+
+void send_auth_request(atransport* t) {
+    LOG(INFO) << "Calling send_auth_request...";
+
+    if (!adbd_auth_generate_token(t->token, sizeof(t->token))) {
+        PLOG(ERROR) << "Error generating token";
+        return;
+    }
+
+    apacket* p = get_apacket();
+    memcpy(p->data, t->token, sizeof(t->token));
+    p->msg.command = A_AUTH;
+    p->msg.arg0 = ADB_AUTH_TOKEN;
+    p->msg.data_length = sizeof(t->token);
+    send_packet(p, t);
+}
+
+void adbd_auth_verified(atransport *t)
+{
+    handle_online(t);
+    send_connect(t);
+}
diff --git a/adb/bugreport.cpp b/adb/bugreport.cpp
index c348dd5..24be529 100644
--- a/adb/bugreport.cpp
+++ b/adb/bugreport.cpp
@@ -21,6 +21,7 @@
 #include <string>
 #include <vector>
 
+#include <android-base/parseint.h>
 #include <android-base/strings.h>
 
 #include "sysdeps.h"
@@ -143,9 +144,11 @@
             //
             size_t idx1 = line.rfind(BUGZ_PROGRESS_PREFIX) + strlen(BUGZ_PROGRESS_PREFIX);
             size_t idx2 = line.rfind(BUGZ_PROGRESS_SEPARATOR);
-            int progress = std::stoi(line.substr(idx1, (idx2 - idx1)));
-            int total = std::stoi(line.substr(idx2 + 1));
-            br_->UpdateProgress(line_message_, progress, total);
+            int progress, total;
+            if (android::base::ParseInt(line.substr(idx1, (idx2 - idx1)), &progress) &&
+                android::base::ParseInt(line.substr(idx2 + 1), &total)) {
+                br_->UpdateProgress(line_message_, progress, total);
+            }
         } else {
             invalid_lines_.push_back(line);
         }
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/file_sync_service.cpp b/adb/file_sync_service.cpp
index 2dfad94..837902a 100644
--- a/adb/file_sync_service.cpp
+++ b/adb/file_sync_service.cpp
@@ -31,10 +31,10 @@
 #include <unistd.h>
 #include <utime.h>
 
-#include <android/log.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <private/android_filesystem_config.h>
+#include <private/android_logger.h>
 #include <selinux/android.h>
 
 #include "adb.h"
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/shell_service.cpp b/adb/shell_service.cpp
index 7b00d9d..e2b388b 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -82,6 +82,7 @@
 #include "shell_service.h"
 
 #include <errno.h>
+#include <paths.h>
 #include <pty.h>
 #include <pwd.h>
 #include <sys/select.h>
@@ -92,10 +93,9 @@
 #include <unordered_map>
 #include <vector>
 
-#include <android/log.h>
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
-#include <paths.h>
+#include <private/android_logger.h>
 
 #include "adb.h"
 #include "adb_io.h"
diff --git a/adb/shell_service_protocol_test.cpp b/adb/shell_service_protocol_test.cpp
index a826035..b0fa3ed 100644
--- a/adb/shell_service_protocol_test.cpp
+++ b/adb/shell_service_protocol_test.cpp
@@ -86,9 +86,10 @@
 
 namespace {
 
-// Returns true if the packet contains the given values.
+// Returns true if the packet contains the given values. `data` can't be null.
 bool PacketEquals(const ShellProtocol* protocol, ShellProtocol::Id id,
                     const void* data, size_t data_length) {
+    // Note that passing memcmp null is bad, even if data_length is 0.
     return (protocol->id() == id &&
             protocol->data_length() == data_length &&
             !memcmp(data, protocol->data(), data_length));
@@ -130,7 +131,8 @@
 
     ASSERT_TRUE(write_protocol_->Write(id, 0));
     ASSERT_TRUE(read_protocol_->Read());
-    ASSERT_TRUE(PacketEquals(read_protocol_, id, nullptr, 0));
+    char buf[1];
+    ASSERT_TRUE(PacketEquals(read_protocol_, id, buf, 0));
 }
 
 // Tests exit code packets.
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index b809c4f..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"
@@ -122,7 +123,7 @@
 }
 
 static int local_socket_enqueue(asocket* s, apacket* p) {
-    D("LS(%d): enqueue %d", s->id, p->len);
+    D("LS(%d): enqueue %zu", s->id, p->len);
 
     p->ptr = p->data;
 
@@ -195,7 +196,7 @@
 
     /* dispose of any unwritten data */
     for (p = s->pkt_first; p; p = n) {
-        D("LS(%d): discarding %d bytes", s->id, p->len);
+        D("LS(%d): discarding %zu bytes", s->id, p->len);
         n = p->next;
         put_apacket(p);
     }
@@ -305,7 +306,7 @@
 
     if (ev & FDE_READ) {
         apacket* p = get_apacket();
-        unsigned char* x = p->data;
+        char* x = p->data;
         const size_t max_payload = s->get_max_payload();
         size_t avail = max_payload;
         int r = 0;
@@ -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)) {
@@ -553,7 +549,7 @@
     s->close(s);
 }
 
-static unsigned unhex(unsigned char* s, int len) {
+static unsigned unhex(char* s, int len) {
     unsigned n = 0, c;
 
     while (len-- > 0) {
@@ -665,7 +661,7 @@
     TransportType type = kTransportAny;
 #endif
 
-    D("SS(%d): enqueue %d", s->id, p->len);
+    D("SS(%d): enqueue %zu", s->id, p->len);
 
     if (s->pkt_first == 0) {
         s->pkt_first = p;
@@ -698,7 +694,7 @@
     D("SS(%d): len is %d", s->id, len);
     /* can't do anything until we have the full header */
     if ((len + 4) > p->len) {
-        D("SS(%d): waiting for %d more bytes", s->id, len + 4 - p->len);
+        D("SS(%d): waiting for %zu more bytes", s->id, len + 4 - p->len);
         return 0;
     }
 
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 3ed589c..ad9b9fd 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -594,11 +594,14 @@
 }
 
 inline int network_loopback_client(int port, int type, std::string* error) {
-  return _fd_set_error_str(socket_loopback_client(port, type), error);
+  return _fd_set_error_str(socket_network_client("localhost", port, type), error);
 }
 
 inline int network_loopback_server(int port, int type, std::string* error) {
-  return _fd_set_error_str(socket_loopback_server(port, type), error);
+  int fd = socket_loopback_server(port, type);
+  if (fd < 0 && errno == EAFNOSUPPORT)
+      return _fd_set_error_str(socket_loopback_server6(port, type), error);
+  return _fd_set_error_str(fd, error);
 }
 
 inline int network_inaddr_any_server(int port, int type, std::string* error) {
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 87712fc..7b4bb1c 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -150,32 +150,17 @@
     }
 }
 
-void send_packet(apacket *p, atransport *t)
-{
-    unsigned char *x;
-    unsigned sum;
-    unsigned count;
-
+void send_packet(apacket* p, atransport* t) {
     p->msg.magic = p->msg.command ^ 0xffffffff;
-
-    count = p->msg.data_length;
-    x = (unsigned char *) p->data;
-    sum = 0;
-    while(count-- > 0){
-        sum += *x++;
-    }
-    p->msg.data_check = sum;
+    p->msg.data_check = calculate_apacket_checksum(p);
 
     print_packet("send", p);
 
     if (t == NULL) {
-        D("Transport is null");
-        // Zap errno because print_packet() and other stuff have errno effect.
-        errno = 0;
-        fatal_errno("Transport is null");
+        fatal("Transport is null");
     }
 
-    if(write_packet(t->transport_socket, t->serial, &p)){
+    if (write_packet(t->transport_socket, t->serial, &p)) {
         fatal_errno("cannot enqueue packet on transport socket");
     }
 }
@@ -1052,25 +1037,14 @@
     return 0;
 }
 
-int check_data(apacket *p)
-{
-    unsigned count, sum;
-    unsigned char *x;
-
-    count = p->msg.data_length;
-    x = p->data;
-    sum = 0;
-    while(count-- > 0) {
-        sum += *x++;
-    }
-
-    if(sum != p->msg.data_check) {
+int check_data(apacket* p) {
+    if (calculate_apacket_checksum(p) != p->msg.data_check) {
         return -1;
-    } else {
-        return 0;
     }
+    return 0;
 }
 
+#if ADB_HOST
 std::shared_ptr<RSA> atransport::NextKey() {
     if (keys_.empty()) keys_ = adb_auth_get_private_keys();
 
@@ -1078,3 +1052,4 @@
     keys_.pop_front();
     return result;
 }
+#endif
diff --git a/adb/transport.h b/adb/transport.h
index 959681f..621516c 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -108,9 +108,11 @@
         return type == kTransportLocal && local_port_for_emulator_ == -1;
     }
 
+#if ADB_HOST
     std::shared_ptr<RSA> NextKey();
+#endif
 
-    unsigned char token[TOKEN_SIZE] = {};
+    char token[TOKEN_SIZE] = {};
     size_t failed_auth_attempts = 0;
 
     const std::string connection_state_name() const;
@@ -161,7 +163,9 @@
     // A list of adisconnect callbacks called when the transport is kicked.
     std::list<adisconnect*> disconnects_;
 
+#if ADB_HOST
     std::deque<std::shared_ptr<RSA>> keys_;
+#endif
 
     DISALLOW_COPY_AND_ASSIGN(atransport);
 };
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index a94b41e..ea2bf77 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -103,7 +103,8 @@
     int fd = -1;
 
 #if ADB_HOST
-    if (find_emulator_transport_by_adb_port(adb_port) != nullptr) {
+    if (find_emulator_transport_by_adb_port(adb_port) != nullptr ||
+        find_emulator_transport_by_console_port(console_port) != nullptr) {
         return -1;
     }
 
@@ -120,7 +121,7 @@
         D("client: connected on remote on fd %d", fd);
         close_on_exec(fd);
         disable_tcp_nagle(fd);
-        std::string serial = android::base::StringPrintf("emulator-%d", console_port);
+        std::string serial = getEmulatorSerialString(console_port);
         if (register_socket_transport(fd, serial.c_str(), adb_port, 1) == 0) {
             return 0;
         }
@@ -431,6 +432,11 @@
     return NULL;
 }
 
+std::string getEmulatorSerialString(int console_port)
+{
+    return android::base::StringPrintf("emulator-%d", console_port);
+}
+
 atransport* find_emulator_transport_by_adb_port(int adb_port)
 {
     std::lock_guard<std::mutex> lock(local_transports_lock);
@@ -438,6 +444,12 @@
     return result;
 }
 
+atransport* find_emulator_transport_by_console_port(int console_port)
+{
+    return find_transport(getEmulatorSerialString(console_port).c_str());
+}
+
+
 /* Only call this function if you already hold local_transports_lock. */
 int get_available_local_transport_index_locked()
 {
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index d05d928..d054601 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -94,7 +94,7 @@
 }
 
 #if ADB_HOST
-int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol)
+int is_adb_interface(int usb_class, int usb_subclass, int usb_protocol)
 {
     return (usb_class == ADB_CLASS && usb_subclass == ADB_SUBCLASS && usb_protocol == ADB_PROTOCOL);
 }
diff --git a/adb/usb_linux.cpp b/adb/usb_linux.cpp
index 500898a..3e5028d 100644
--- a/adb/usb_linux.cpp
+++ b/adb/usb_linux.cpp
@@ -205,9 +205,8 @@
                          interface->bInterfaceProtocol, interface->bNumEndpoints);
 
                     if (interface->bNumEndpoints == 2 &&
-                            is_adb_interface(vid, pid, interface->bInterfaceClass,
-                            interface->bInterfaceSubClass, interface->bInterfaceProtocol))  {
-
+                        is_adb_interface(interface->bInterfaceClass, interface->bInterfaceSubClass,
+                                         interface->bInterfaceProtocol)) {
                         struct stat st;
                         char pathbuf[128];
                         char link[256];
diff --git a/adb/usb_osx.cpp b/adb/usb_osx.cpp
index adcbb3e..2ee2aae 100644
--- a/adb/usb_osx.cpp
+++ b/adb/usb_osx.cpp
@@ -345,7 +345,7 @@
 
     //* check to make sure interface class, subclass and protocol match ADB
     //* avoid opening mass storage endpoints
-    if (!is_adb_interface(vendor, product, interfaceClass, interfaceSubClass, interfaceProtocol)) {
+    if (!is_adb_interface(interfaceClass, interfaceSubClass, interfaceProtocol)) {
         goto err_bad_adb_interface;
     }
 
diff --git a/adb/usb_windows.cpp b/adb/usb_windows.cpp
index 4649454..755f07e 100644
--- a/adb/usb_windows.cpp
+++ b/adb/usb_windows.cpp
@@ -553,10 +553,9 @@
     return 0;
   }
 
-  if (is_adb_interface(device_desc.idVendor, device_desc.idProduct,
-      interf_desc.bInterfaceClass, interf_desc.bInterfaceSubClass, interf_desc.bInterfaceProtocol)) {
-
-    if(interf_desc.bInterfaceProtocol == 0x01) {
+  if (is_adb_interface(interf_desc.bInterfaceClass, interf_desc.bInterfaceSubClass,
+                       interf_desc.bInterfaceProtocol)) {
+    if (interf_desc.bInterfaceProtocol == 0x01) {
       AdbEndpointInformation endpoint_info;
       // assuming zero is a valid bulk endpoint ID
       if (AdbGetEndpointInformation(handle->adb_interface, 0, &endpoint_info)) {
diff --git a/base/include/android-base/parseint.h b/base/include/android-base/parseint.h
index ed75e2d..2c8570e 100644
--- a/base/include/android-base/parseint.h
+++ b/base/include/android-base/parseint.h
@@ -21,17 +21,19 @@
 #include <stdlib.h>
 
 #include <limits>
+#include <string>
 
 namespace android {
 namespace base {
 
 // Parses the unsigned decimal integer in the string 's' and sets 'out' to
 // that value. Optionally allows the caller to define a 'max' beyond which
-// otherwise valid values will be rejected. Returns boolean success.
+// otherwise valid values will be rejected. Returns boolean success; 'out'
+// is untouched if parsing fails.
 template <typename T>
 bool ParseUint(const char* s, T* out,
                T max = std::numeric_limits<T>::max()) {
-  int base = (s[0] == '0' && s[1] == 'x') ? 16 : 10;
+  int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
   errno = 0;
   char* end;
   unsigned long long int result = strtoull(s, &end, base);
@@ -45,15 +47,22 @@
   return true;
 }
 
+// TODO: string_view
+template <typename T>
+bool ParseUint(const std::string& s, T* out,
+               T max = std::numeric_limits<T>::max()) {
+  return ParseUint(s.c_str(), out, max);
+}
+
 // Parses the signed decimal integer in the string 's' and sets 'out' to
 // that value. Optionally allows the caller to define a 'min' and 'max
 // beyond which otherwise valid values will be rejected. Returns boolean
-// success.
+// success; 'out' is untouched if parsing fails.
 template <typename T>
 bool ParseInt(const char* s, T* out,
               T min = std::numeric_limits<T>::min(),
               T max = std::numeric_limits<T>::max()) {
-  int base = (s[0] == '0' && s[1] == 'x') ? 16 : 10;
+  int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
   errno = 0;
   char* end;
   long long int result = strtoll(s, &end, base);
@@ -67,6 +76,14 @@
   return true;
 }
 
+// TODO: string_view
+template <typename T>
+bool ParseInt(const std::string& s, T* out,
+              T min = std::numeric_limits<T>::min(),
+              T max = std::numeric_limits<T>::max()) {
+  return ParseInt(s.c_str(), out, min, max);
+}
+
 }  // namespace base
 }  // namespace android
 
diff --git a/base/logging.cpp b/base/logging.cpp
index ece10ec..dab86fe 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -415,6 +415,8 @@
         msg[nl] = '\0';
         LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetId(),
                 data_->GetSeverity(), &msg[i]);
+        // Undo the zero-termination so we can give the complete message to the aborter.
+        msg[nl] = '\n';
         i = nl + 1;
       }
     }
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 9fc7736..1ee181a 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -606,3 +606,27 @@
 
   ASSERT_DEATH({SuppressAbortUI(); LOG(FATAL) << "foobar";}, "foobar");
 }
+
+struct CountLineAborter {
+  static void CountLineAborterFunction(const char* msg) {
+    while (*msg != 0) {
+      if (*msg == '\n') {
+        newline_count++;
+      }
+      msg++;
+    }
+  }
+  static size_t newline_count;
+};
+size_t CountLineAborter::newline_count = 0;
+
+TEST(logging, LOG_FATAL_ABORTER_MESSAGE) {
+  CountLineAborter::newline_count = 0;
+  android::base::SetAborter(CountLineAborter::CountLineAborterFunction);
+
+  android::base::ScopedLogSeverity sls(android::base::ERROR);
+  CapturedStderr cap;
+  LOG(FATAL) << "foo\nbar";
+
+  EXPECT_EQ(CountLineAborter::newline_count, 1U + 1U);  // +1 for final '\n'.
+}
diff --git a/base/parseint_test.cpp b/base/parseint_test.cpp
index 6a3ba31..483b1d3 100644
--- a/base/parseint_test.cpp
+++ b/base/parseint_test.cpp
@@ -19,7 +19,7 @@
 #include <gtest/gtest.h>
 
 TEST(parseint, signed_smoke) {
-  int i;
+  int i = 0;
   ASSERT_FALSE(android::base::ParseInt("x", &i));
   ASSERT_FALSE(android::base::ParseInt("123x", &i));
 
@@ -28,7 +28,7 @@
   ASSERT_TRUE(android::base::ParseInt("-123", &i));
   ASSERT_EQ(-123, i);
 
-  short s;
+  short s = 0;
   ASSERT_TRUE(android::base::ParseInt("1234", &s));
   ASSERT_EQ(1234, s);
 
@@ -39,7 +39,7 @@
 }
 
 TEST(parseint, unsigned_smoke) {
-  unsigned int i;
+  unsigned int i = 0u;
   ASSERT_FALSE(android::base::ParseUint("x", &i));
   ASSERT_FALSE(android::base::ParseUint("123x", &i));
 
@@ -47,7 +47,7 @@
   ASSERT_EQ(123u, i);
   ASSERT_FALSE(android::base::ParseUint("-123", &i));
 
-  unsigned short s;
+  unsigned short s = 0u;
   ASSERT_TRUE(android::base::ParseUint("1234", &s));
   ASSERT_EQ(1234u, s);
 
@@ -58,21 +58,41 @@
 }
 
 TEST(parseint, no_implicit_octal) {
-  int i;
+  int i = 0;
   ASSERT_TRUE(android::base::ParseInt("0123", &i));
   ASSERT_EQ(123, i);
 
-  unsigned int u;
+  unsigned int u = 0u;
   ASSERT_TRUE(android::base::ParseUint("0123", &u));
   ASSERT_EQ(123u, u);
 }
 
 TEST(parseint, explicit_hex) {
-  int i;
+  int i = 0;
   ASSERT_TRUE(android::base::ParseInt("0x123", &i));
   ASSERT_EQ(0x123, i);
 
-  unsigned int u;
+  unsigned int u = 0u;
   ASSERT_TRUE(android::base::ParseUint("0x123", &u));
   ASSERT_EQ(0x123u, u);
 }
+
+TEST(parseint, string) {
+  int i = 0;
+  ASSERT_TRUE(android::base::ParseInt(std::string("123"), &i));
+  ASSERT_EQ(123, i);
+
+  unsigned int u = 0u;
+  ASSERT_TRUE(android::base::ParseUint(std::string("123"), &u));
+  ASSERT_EQ(123u, u);
+}
+
+TEST(parseint, untouched_on_failure) {
+  int i = 123;
+  ASSERT_FALSE(android::base::ParseInt("456x", &i));
+  ASSERT_EQ(123, i);
+
+  unsigned int u = 123u;
+  ASSERT_FALSE(android::base::ParseInt("456x", &u));
+  ASSERT_EQ(123u, u);
+}
diff --git a/base/properties.cpp b/base/properties.cpp
index fab3005..37daf9a 100644
--- a/base/properties.cpp
+++ b/base/properties.cpp
@@ -52,7 +52,7 @@
 T GetIntProperty(const std::string& key, T default_value, T min, T max) {
   T result;
   std::string value = GetProperty(key, "");
-  if (!value.empty() && android::base::ParseInt(value.c_str(), &result, min, max)) return result;
+  if (!value.empty() && android::base::ParseInt(value, &result, min, max)) return result;
   return default_value;
 }
 
@@ -60,7 +60,7 @@
 T GetUintProperty(const std::string& key, T default_value, T max) {
   T result;
   std::string value = GetProperty(key, "");
-  if (!value.empty() && android::base::ParseUint(value.c_str(), &result, max)) return result;
+  if (!value.empty() && android::base::ParseUint(value, &result, max)) return result;
   return default_value;
 }
 
diff --git a/bootstat/boot_event_record_store.cpp b/bootstat/boot_event_record_store.cpp
index 346eada..78be944 100644
--- a/bootstat/boot_event_record_store.cpp
+++ b/bootstat/boot_event_record_store.cpp
@@ -59,7 +59,7 @@
   // Ignore existing bootstat records (which do not contain file content).
   if (!content.empty()) {
     int32_t value;
-    if (android::base::ParseInt(content.c_str(), &value)) {
+    if (android::base::ParseInt(content, &value)) {
       bootstat::LogHistogram("bootstat_mtime_matches_content", value == *uptime);
     }
   }
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 0ab4c98..e5ddab3 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -60,7 +60,7 @@
   BootEventRecordStore boot_event_store;
   if (!value_str.empty()) {
     int32_t value = 0;
-    if (android::base::ParseInt(value_str.c_str(), &value)) {
+    if (android::base::ParseInt(value_str, &value)) {
       boot_event_store.AddBootEventWithValue(event, value);
     }
   } else {
@@ -193,7 +193,7 @@
 
   std::string build_date_str = GetProperty("ro.build.date.utc");
   int32_t build_date;
-  if (!android::base::ParseInt(build_date_str.c_str(), &build_date)) {
+  if (!android::base::ParseInt(build_date_str, &build_date)) {
     return std::string();
   }
 
diff --git a/cpio/mkbootfs.c b/cpio/mkbootfs.c
index 0e35323..b89c395 100644
--- a/cpio/mkbootfs.c
+++ b/cpio/mkbootfs.c
@@ -51,6 +51,8 @@
 #define CANNED_LINE_LENGTH  (1024)
 #endif
 
+#define TRAILER "TRAILER!!!"
+
 static int verbose = 0;
 static int total_size = 0;
 
@@ -80,8 +82,8 @@
     } else {
         // Use the compiled-in fs_config() function.
         unsigned st_mode = s->st_mode;
-        fs_config(path, S_ISDIR(s->st_mode), target_out_path,
-                       &s->st_uid, &s->st_gid, &st_mode, &capabilities);
+        int is_dir = S_ISDIR(s->st_mode) || strcmp(path, TRAILER) == 0;
+        fs_config(path, is_dir, target_out_path, &s->st_uid, &s->st_gid, &st_mode, &capabilities);
         s->st_mode = (typeof(s->st_mode)) st_mode;
     }
 }
@@ -140,7 +142,7 @@
 {
     struct stat s;
     memset(&s, 0, sizeof(s));
-    _eject(&s, "TRAILER!!!", 10, 0, 0);
+    _eject(&s, TRAILER, 10, 0, 0);
 
     while(total_size & 0xff) {
         total_size++;
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index fdedb76..155b309 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -1,7 +1,6 @@
 LOCAL_PATH := $(call my-dir)
 
 common_cppflags := \
-    -std=gnu++11 \
     -W \
     -Wall \
     -Wextra \
@@ -121,6 +120,7 @@
     libbacktrace \
     libbase \
     libcutils \
+    liblog
 
 debuggerd_c_includes := \
     $(LOCAL_PATH)/test \
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index cf37701..c67d747 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -31,6 +31,7 @@
 #include <errno.h>
 #include <inttypes.h>
 #include <pthread.h>
+#include <sched.h>
 #include <signal.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -41,6 +42,7 @@
 #include <sys/socket.h>
 #include <sys/syscall.h>
 #include <sys/un.h>
+#include <sys/wait.h>
 #include <unistd.h>
 
 #include "private/libc_logging.h"
@@ -56,6 +58,13 @@
 
 static debuggerd_callbacks_t g_callbacks;
 
+// Don't use __libc_fatal because it exits via abort, which might put us back into a signal handler.
+#define fatal(...)                                             \
+  do {                                                         \
+    __libc_format_log(ANDROID_LOG_FATAL, "libc", __VA_ARGS__); \
+    _exit(1);                                                  \
+  } while (0)
+
 static int socket_abstract_client(const char* name, int type) {
   sockaddr_un addr;
 
@@ -188,7 +197,7 @@
   return result;
 }
 
-static void send_debuggerd_packet() {
+static void send_debuggerd_packet(pid_t crashing_tid, pid_t pseudothread_tid) {
   // Mutex to prevent multiple crashing threads from trying to talk
   // to debuggerd at the same time.
   static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -218,7 +227,8 @@
   // that's actually in our process.
   debugger_msg_t msg;
   msg.action = DEBUGGER_ACTION_CRASH;
-  msg.tid = gettid();
+  msg.tid = crashing_tid;
+  msg.ignore_tid = pseudothread_tid;
   msg.abort_msg_address = 0;
 
   if (g_callbacks.get_abort_message) {
@@ -229,11 +239,9 @@
   if (ret == sizeof(msg)) {
     char debuggerd_ack;
     ret = TEMP_FAILURE_RETRY(read(s, &debuggerd_ack, 1));
-    int saved_errno = errno;
     if (g_callbacks.post_dump) {
       g_callbacks.post_dump();
     }
-    errno = saved_errno;
   } else {
     // read or write failed -- broken connection?
     __libc_format_log(ANDROID_LOG_FATAL, "libc", "Failed while talking to debuggerd: %s",
@@ -243,6 +251,33 @@
   close(s);
 }
 
+struct debugger_thread_info {
+  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+  pid_t crashing_tid;
+  pid_t pseudothread_tid;
+  int signal_number;
+  siginfo_t* info;
+};
+
+// Logging and contacting debuggerd requires free file descriptors, which we might not have.
+// Work around this by spawning a "thread" that shares its parent's address space, but not its file
+// descriptor table, so that we can close random file descriptors without affecting the original
+// process. Note that this doesn't go through pthread_create, so TLS is shared with the spawning
+// process.
+static void* pseudothread_stack;
+static int debuggerd_dispatch_pseudothread(void* arg) {
+  debugger_thread_info* thread_info = static_cast<debugger_thread_info*>(arg);
+
+  for (int i = 3; i < 1024; ++i) {
+    close(i);
+  }
+
+  log_signal_summary(thread_info->signal_number, thread_info->info);
+  send_debuggerd_packet(thread_info->crashing_tid, thread_info->pseudothread_tid);
+  pthread_mutex_unlock(&thread_info->mutex);
+  return 0;
+}
+
 /*
  * Catches fatal signals so we can ask debuggerd to ptrace us before
  * we crash.
@@ -254,9 +289,25 @@
     info = nullptr;
   }
 
-  log_signal_summary(signal_number, info);
+  debugger_thread_info thread_info = {
+    .crashing_tid = gettid(),
+    .signal_number = signal_number,
+    .info = info
+  };
 
-  send_debuggerd_packet();
+  pthread_mutex_lock(&thread_info.mutex);
+  pid_t child_pid = clone(debuggerd_dispatch_pseudothread, pseudothread_stack,
+                          CLONE_THREAD | CLONE_SIGHAND | CLONE_VM | CLONE_CHILD_SETTID,
+                          &thread_info, nullptr, nullptr, &thread_info.pseudothread_tid);
+
+  if (child_pid == -1) {
+    fatal("failed to spawn debuggerd dispatch thread: %s", strerror(errno));
+  }
+
+  // Wait for the child to finish and unlock the mutex.
+  // This relies on bionic behavior that isn't guaranteed by the standard.
+  pthread_mutex_lock(&thread_info.mutex);
+
 
   // We need to return from the signal handler so that debuggerd can dump the
   // thread that crashed, but returning here does not guarantee that the signal
@@ -281,9 +332,7 @@
 
   int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), signal_number, info);
   if (rc != 0) {
-    __libc_format_log(ANDROID_LOG_FATAL, "libc", "failed to resend signal during crash: %s",
-                      strerror(errno));
-    _exit(0);
+    fatal("failed to resend signal during crash: %s", strerror(errno));
   }
 }
 
@@ -292,6 +341,23 @@
     g_callbacks = *callbacks;
   }
 
+  void* thread_stack_allocation =
+    mmap(nullptr, PAGE_SIZE * 3, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  if (thread_stack_allocation == MAP_FAILED) {
+    fatal("failed to allocate debuggerd thread stack");
+  }
+
+  char* stack = static_cast<char*>(thread_stack_allocation) + PAGE_SIZE;
+  if (mprotect(stack, PAGE_SIZE, PROT_READ | PROT_WRITE) != 0) {
+    fatal("failed to mprotect debuggerd thread stack");
+  }
+
+  // Stack grows negatively, set it to the last byte in the page...
+  stack = (stack + PAGE_SIZE - 1);
+  // and align it.
+  stack -= 15;
+  pseudothread_stack = stack;
+
   struct sigaction action;
   memset(&action, 0, sizeof(action));
   sigemptyset(&action.sa_mask);
diff --git a/debuggerd/crasher.cpp b/debuggerd/crasher.cpp
index 7d3509c..cfcc26e 100644
--- a/debuggerd/crasher.cpp
+++ b/debuggerd/crasher.cpp
@@ -1,5 +1,6 @@
 #include <assert.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <pthread.h>
 #include <sched.h>
 #include <signal.h>
@@ -141,7 +142,13 @@
 {
     fprintf(stderr, "%s: init pid=%d tid=%d\n", __progname, getpid(), gettid());
 
-    if (!strncmp(arg, "thread-", strlen("thread-"))) {
+    if (!strncmp(arg, "exhaustfd-", strlen("exhaustfd-"))) {
+      errno = 0;
+      while (errno != EMFILE) {
+        open("/dev/null", O_RDONLY);
+      }
+      return do_action(arg + strlen("exhaustfd-"));
+    } else if (!strncmp(arg, "thread-", strlen("thread-"))) {
         return do_action_on_thread(arg + strlen("thread-"));
     } else if (!strcmp(arg, "SIGSEGV-non-null")) {
         sigsegv_non_null();
@@ -208,6 +215,8 @@
     fprintf(stderr, "  SIGTRAP               cause a SIGTRAP\n");
     fprintf(stderr, "prefix any of the above with 'thread-' to not run\n");
     fprintf(stderr, "on the process' main thread.\n");
+    fprintf(stderr, "prefix any of the above with 'exhaustfd-' to exhaust\n");
+    fprintf(stderr, "all available file descriptors before crashing.\n");
     return EXIT_SUCCESS;
 }
 
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index a6d3d38..b8a62a5 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -69,6 +69,7 @@
   debugger_action_t action;
   pid_t pid, tid;
   uid_t uid, gid;
+  pid_t ignore_tid;
   uintptr_t abort_msg_address;
 };
 
@@ -215,6 +216,7 @@
 
   out_request->action = static_cast<debugger_action_t>(msg.action);
   out_request->tid = msg.tid;
+  out_request->ignore_tid = msg.ignore_tid;
   out_request->pid = cr.pid;
   out_request->uid = cr.uid;
   out_request->gid = cr.gid;
@@ -408,7 +410,7 @@
 }
 #endif
 
-static void ptrace_siblings(pid_t pid, pid_t main_tid, std::set<pid_t>& tids) {
+static void ptrace_siblings(pid_t pid, pid_t main_tid, pid_t ignore_tid, std::set<pid_t>& tids) {
   char task_path[64];
 
   snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
@@ -434,7 +436,7 @@
       continue;
     }
 
-    if (tid == main_tid) {
+    if (tid == main_tid || tid == ignore_tid) {
       continue;
     }
 
@@ -583,7 +585,7 @@
 
   std::set<pid_t> siblings;
   if (!attach_gdb) {
-    ptrace_siblings(request.pid, request.tid, siblings);
+    ptrace_siblings(request.pid, request.tid, request.ignore_tid, siblings);
   }
 
   // Generate the backtrace map before dropping privileges.
diff --git a/debuggerd/include/debuggerd/client.h b/debuggerd/include/debuggerd/client.h
index 8225c73..aeb723b 100644
--- a/debuggerd/include/debuggerd/client.h
+++ b/debuggerd/include/debuggerd/client.h
@@ -43,6 +43,7 @@
 typedef struct __attribute__((packed)) {
   int32_t action;
   pid_t tid;
+  pid_t ignore_tid;
   uint64_t abort_msg_address;
 } debugger_msg_t;
 
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/fastboot/Android.mk b/fastboot/Android.mk
index 7112d1d..286de5b 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -21,7 +21,6 @@
 LOCAL_C_INCLUDES := \
   $(LOCAL_PATH)/../adb \
   $(LOCAL_PATH)/../mkbootimg \
-  $(LOCAL_PATH)/../../extras/ext4_utils \
   $(LOCAL_PATH)/../../extras/f2fs_utils \
 
 LOCAL_SRC_FILES := \
@@ -38,7 +37,6 @@
 LOCAL_MODULE := fastboot
 LOCAL_MODULE_TAGS := debug
 LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_CONLYFLAGS += -std=gnu99
 LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code
 
 LOCAL_CFLAGS += -DFASTBOOT_REVISION='"$(fastboot_version)"'
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index d6b631f..4cd423a 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -755,7 +755,7 @@
     max_download_size = android::base::Trim(max_download_size);
 
     uint64_t limit;
-    if (!android::base::ParseUint(max_download_size.c_str(), &limit)) {
+    if (!android::base::ParseUint(max_download_size, &limit)) {
         fprintf(stderr, "couldn't parse max-download-size '%s'\n", max_download_size.c_str());
         return 0;
     }
@@ -903,7 +903,7 @@
     if (!fb_getvar(transport, "slot-count", &var)) {
         if (supports_AB_obsolete(transport)) return 2; // Legacy support
     }
-    if (!android::base::ParseInt(var.c_str(), &count)) return 0;
+    if (!android::base::ParseInt(var, &count)) return 0;
     return count;
 }
 
@@ -1362,7 +1362,7 @@
     }
 
     int64_t size;
-    if (!android::base::ParseInt(partition_size.c_str(), &size)) {
+    if (!android::base::ParseInt(partition_size, &size)) {
         fprintf(stderr, "Couldn't parse partition size '%s'.\n", partition_size.c_str());
         return;
     }
diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp
index 8539e23..9b73165 100644
--- a/fastboot/fs.cpp
+++ b/fastboot/fs.cpp
@@ -1,7 +1,6 @@
 #include "fs.h"
 
 #include "fastboot.h"
-#include "make_ext4fs.h"
 #include "make_f2fs.h"
 
 #include <errno.h>
@@ -12,6 +11,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <ext4_utils/make_ext4fs.h>
 #include <sparse/sparse.h>
 
 static int generate_ext4_image(int fd, long long partSize, const std::string& initial_dir)
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index b11ce75..d570255 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -30,19 +30,18 @@
 #include <time.h>
 #include <unistd.h>
 
-#include <ext4.h>
-#include <ext4_crypt_init_extensions.h>
-#include <ext4_sb.h>
-
 #include <cutils/android_reboot.h>
 #include <cutils/partition_utils.h>
 #include <cutils/properties.h>
+#include <ext4_utils/ext4.h>
+#include <ext4_utils/ext4_crypt_init_extensions.h>
+#include <ext4_utils/ext4_sb.h>
+#include <ext4_utils/ext4_utils.h>
+#include <ext4_utils/wipe.h>
 #include <linux/loop.h>
 #include <logwrap/logwrap.h>
 #include <private/android_filesystem_config.h>
-
-#include "ext4_utils.h"
-#include "wipe.h"
+#include <private/android_logger.h>
 
 #include "fs_mgr_priv.h"
 #include "fs_mgr_priv_verity.h"
@@ -262,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];
@@ -539,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");
@@ -701,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");
@@ -905,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/fs_mgr/fs_mgr_format.c b/fs_mgr/fs_mgr_format.c
index 7ee5832..7c3b1ed 100644
--- a/fs_mgr/fs_mgr_format.c
+++ b/fs_mgr/fs_mgr_format.c
@@ -24,13 +24,13 @@
 #include <cutils/partition_utils.h>
 #include <sys/mount.h>
 
+#include <ext4_utils/ext4_utils.h>
+#include <ext4_utils/ext4.h>
+#include <ext4_utils/make_ext4fs.h>
 #include <selinux/selinux.h>
 #include <selinux/label.h>
 #include <selinux/android.h>
 
-#include "ext4_utils.h"
-#include "ext4.h"
-#include "make_ext4fs.h"
 #include "fs_mgr_priv.h"
 #include "cryptfs.h"
 
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index f81e7d9..0c90a54 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -29,6 +29,7 @@
 #include <memory>
 
 #include <android-base/file.h>
+#include <android-base/parseint.h>
 #include <android-base/strings.h>
 #include <batteryservice/BatteryService.h>
 #include <cutils/klog.h>
@@ -182,7 +183,7 @@
     int value = 0;
 
     if (readFromFile(path, &buf) > 0)
-        value = std::stoi(buf.c_str(), NULL, 0);
+        android::base::ParseInt(buf, &value);
 
     return value;
 }
diff --git a/include/android/log.h b/include/android/log.h
index 5f20f8c..9b26839 100644
--- a/include/android/log.h
+++ b/include/android/log.h
@@ -178,9 +178,6 @@
                           size_t len);
 int __android_log_bswrite(int32_t tag, const char *payload);
 
-int __android_log_security_bwrite(int32_t tag, const void *payload, size_t len);
-int __android_log_security_bswrite(int32_t tag, const char *payload);
-
 // ---------------------------------------------------------------------
 
 /*
@@ -820,8 +817,6 @@
 int __android_log_is_loggable(int prio, const char *tag, int default_prio);
 int __android_log_is_loggable_len(int prio, const char *tag, size_t len, int default_prio);
 
-int __android_log_security(); /* Device Owner is present */
-
 int __android_log_error_write(int tag, const char *subTag, int32_t uid, const char *data,
                               uint32_t dataLen);
 
diff --git a/include/backtrace/BacktraceMap.h b/include/backtrace/BacktraceMap.h
index b80045f..df48dfe 100644
--- a/include/backtrace/BacktraceMap.h
+++ b/include/backtrace/BacktraceMap.h
@@ -19,7 +19,7 @@
 
 #include <stdint.h>
 #include <sys/types.h>
-#ifdef USE_MINGW
+#ifdef _WIN32
 // MINGW does not define these constants.
 #define PROT_NONE 0
 #define PROT_READ 0x1
diff --git a/include/cutils/native_handle.h b/include/cutils/native_handle.h
index 31695cb..7d6a988 100644
--- a/include/cutils/native_handle.h
+++ b/include/cutils/native_handle.h
@@ -17,10 +17,17 @@
 #ifndef NATIVE_HANDLE_H_
 #define NATIVE_HANDLE_H_
 
+#include <stdalign.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+/* Declare a char array for use with native_handle_init */
+#define NATIVE_HANDLE_DECLARE_STORAGE(name, maxFds, maxInts) \
+    alignas(native_handle_t) char name[                            \
+      sizeof(native_handle_t) + sizeof(int) * (maxFds + maxInts)]
+
 typedef struct native_handle
 {
     int version;        /* sizeof(native_handle_t) */
@@ -46,6 +53,14 @@
  */
 int native_handle_close(const native_handle_t* h);
 
+/*
+ * native_handle_init
+ *
+ * Initializes a native_handle_t from storage.  storage must be declared with
+ * NATIVE_HANDLE_DECLARE_STORAGE.  numFds and numInts must not respectively
+ * exceed maxFds and maxInts used to declare the storage.
+ */
+native_handle_t* native_handle_init(char* storage, int numFds, int numInts);
 
 /*
  * native_handle_create
@@ -57,6 +72,15 @@
 native_handle_t* native_handle_create(int numFds, int numInts);
 
 /*
+ * native_handle_clone
+ *
+ * creates a native_handle_t and initializes it from another native_handle_t.
+ * Must be destroyed with native_handle_delete().
+ *
+ */
+native_handle_t* native_handle_clone(const native_handle_t* handle);
+
+/*
  * native_handle_delete
  * 
  * frees a native_handle_t allocated with native_handle_create().
diff --git a/include/cutils/sockets.h b/include/cutils/sockets.h
index a93c8ea..4626e7a 100644
--- a/include/cutils/sockets.h
+++ b/include/cutils/sockets.h
@@ -84,11 +84,11 @@
  *
  * These functions return INVALID_SOCKET (-1) on failure for all platforms.
  */
-int socket_loopback_client(int port, int type);
 cutils_socket_t socket_network_client(const char* host, int port, int type);
 int socket_network_client_timeout(const char* host, int port, int type,
                                   int timeout, int* getaddrinfo_error);
 int socket_loopback_server(int port, int type);
+int socket_loopback_server6(int port, int type);
 int socket_local_server(const char* name, int namespaceId, int type);
 int socket_local_server_bind(int s, const char* name, int namespaceId);
 int socket_local_client_connect(int fd, const char *name, int namespaceId,
diff --git a/include/private/android_logger.h b/include/private/android_logger.h
index d477ac1..02764d3 100644
--- a/include/private/android_logger.h
+++ b/include/private/android_logger.h
@@ -21,6 +21,7 @@
 
 /* Android private interfaces */
 
+#include <stdbool.h>
 #include <stdint.h>
 #include <sys/types.h>
 
@@ -126,6 +127,26 @@
         log_id_t logId, char prio, const char *prefix,
         __android_log_pmsg_file_read_fn fn, void *arg);
 
+int __android_log_security_bwrite(int32_t tag, const void *payload, size_t len);
+int __android_log_security_bswrite(int32_t tag, const char *payload);
+int __android_log_security(); /* Device Owner is present */
+
+int __android_log_is_debuggable();
+
+#define BOOL_DEFAULT_FLAG_TRUE_FALSE 0x1
+#define BOOL_DEFAULT_FALSE       0x0     /* false if property not present   */
+#define BOOL_DEFAULT_TRUE        0x1     /* true if property not present    */
+#define BOOL_DEFAULT_FLAG_PERSIST    0x2 /* <key>, persist.<key>, ro.<key>  */
+#define BOOL_DEFAULT_FLAG_ENG        0x4 /* off for user                    */
+#define BOOL_DEFAULT_FLAG_SVELTE     0x8 /* off for low_ram                 */
+bool __android_logger_property_get_bool(const char *key, int flag);
+
+#define LOG_BUFFER_SIZE (256 * 1024) /* Tuned with ro.logd.size per-platform */
+#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
+#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
+unsigned long __android_logger_get_buffer_size(log_id_t logId);
+bool __android_logger_valid_buffer_size(unsigned long value);
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/include/ziparchive/zip_archive.h b/include/ziparchive/zip_archive.h
index 4f68c3b..fc845a4 100644
--- a/include/ziparchive/zip_archive.h
+++ b/include/ziparchive/zip_archive.h
@@ -130,6 +130,8 @@
 int32_t OpenArchiveFd(const int fd, const char* debugFileName,
                       ZipArchiveHandle *handle, bool assume_ownership = true);
 
+int32_t OpenArchiveFromMemory(void* address, size_t length, const char* debugFileName,
+                              ZipArchiveHandle *handle);
 /*
  * Close archive, releasing resources associated with it. This will
  * unmap the central directory of the zipfile and free all internal
@@ -214,6 +216,17 @@
 
 const char* ErrorCodeString(int32_t error_code);
 
+#if !defined(_WIN32)
+typedef bool (*ProcessZipEntryFunction)(const uint8_t* buf, size_t buf_size, void* cookie);
+
+/*
+ * Stream the uncompressed data through the supplied function,
+ * passing cookie to it each time it gets called.
+*/
+int32_t ProcessZipEntryContents(ZipArchiveHandle handle, ZipEntry* entry,
+        ProcessZipEntryFunction func, void* cookie);
+#endif
+
 __END_DECLS
 
 #endif  // LIBZIPARCHIVE_ZIPARCHIVE_H_
diff --git a/init/Android.mk b/init/Android.mk
index 4a8df32..1be064c 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -74,7 +74,6 @@
 
 LOCAL_MODULE:= init
 LOCAL_C_INCLUDES += \
-    system/extras/ext4_utils \
     system/core/mkbootimg
 
 LOCAL_FORCE_STATIC_EXECUTABLE := true
@@ -83,7 +82,7 @@
 
 LOCAL_STATIC_LIBRARIES := \
     libinit \
-    libbootloader_message_writer \
+    libbootloader_message \
     libfs_mgr \
     libfec \
     libfec_rs \
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 200b723..f37ccc2 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -37,8 +37,6 @@
 #include <unistd.h>
 #include <linux/loop.h>
 #include <linux/module.h>
-#include <ext4_crypt.h>
-#include <ext4_crypt_init_extensions.h>
 
 #include <selinux/selinux.h>
 #include <selinux/label.h>
@@ -48,9 +46,11 @@
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
 #include <android-base/stringprintf.h>
-#include <bootloader_message_writer.h>
+#include <bootloader_message/bootloader_message.h>
 #include <cutils/partition_utils.h>
 #include <cutils/android_reboot.h>
+#include <ext4_utils/ext4_crypt.h>
+#include <ext4_utils/ext4_crypt_init_extensions.h>
 #include <logwrap/logwrap.h>
 
 #include "action.h"
@@ -304,7 +304,7 @@
     /* mkdir <path> [mode] [owner] [group] */
 
     if (args.size() >= 3) {
-        mode = std::stoul(args[2], 0, 8);
+        mode = std::strtoul(args[2].c_str(), 0, 8);
     }
 
     ret = make_dir(args[1].c_str(), mode);
@@ -637,10 +637,13 @@
 static int do_setrlimit(const std::vector<std::string>& args) {
     struct rlimit limit;
     int resource;
-    resource = std::stoi(args[1]);
-    limit.rlim_cur = std::stoi(args[2]);
-    limit.rlim_max = std::stoi(args[3]);
-    return setrlimit(resource, &limit);
+    if (android::base::ParseInt(args[1], &resource) &&
+        android::base::ParseUint(args[2], &limit.rlim_cur) &&
+        android::base::ParseUint(args[3], &limit.rlim_max)) {
+        return setrlimit(resource, &limit);
+    }
+    LOG(WARNING) << "ignoring setrlimit " << args[1] << " " << args[2] << " " << args[3];
+    return -1;
 }
 
 static int do_start(const std::vector<std::string>& args) {
@@ -709,7 +712,7 @@
     std::string timeout = property_get("ro.build.shutdown_timeout");
     unsigned int delay = 0;
 
-    if (android::base::ParseUint(timeout.c_str(), &delay) && delay > 0) {
+    if (android::base::ParseUint(timeout, &delay) && delay > 0) {
         Timer t;
         // Ask all services to terminate.
         ServiceManager::GetInstance().ForEachService(
@@ -764,13 +767,11 @@
 }
 
 static int do_sysclktz(const std::vector<std::string>& args) {
-    struct timezone tz;
-
-    memset(&tz, 0, sizeof(tz));
-    tz.tz_minuteswest = std::stoi(args[1]);
-    if (settimeofday(NULL, &tz))
-        return -1;
-    return 0;
+    struct timezone tz = {};
+    if (android::base::ParseInt(args[1], &tz.tz_minuteswest) && settimeofday(NULL, &tz) != -1) {
+        return 0;
+    }
+    return -1;
 }
 
 static int do_verity_load_state(const std::vector<std::string>& args) {
@@ -914,7 +915,8 @@
 
 static int do_loglevel(const std::vector<std::string>& args) {
     // TODO: support names instead/as well?
-    int log_level = std::stoi(args[1]);
+    int log_level = -1;
+    android::base::ParseInt(args[1], &log_level);
     android::base::LogSeverity severity;
     switch (log_level) {
         case 7: severity = android::base::DEBUG; break;
@@ -947,9 +949,12 @@
     if (args.size() == 2) {
         return wait_for_file(args[1].c_str(), COMMAND_RETRY_TIMEOUT);
     } else if (args.size() == 3) {
-        return wait_for_file(args[1].c_str(), std::stoi(args[2]));
-    } else
-        return -1;
+        int timeout;
+        if (android::base::ParseInt(args[2], &timeout)) {
+            return wait_for_file(args[1].c_str(), timeout);
+        }
+    }
+    return -1;
 }
 
 /*
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 9ec26af..d017390 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -122,14 +122,20 @@
         return false;
     }
     dirent* current_file;
+    std::vector<std::string> files;
     while ((current_file = readdir(config_dir.get()))) {
-        std::string current_path =
-            android::base::StringPrintf("%s/%s", path.c_str(), current_file->d_name);
         // Ignore directories and only process regular files.
         if (current_file->d_type == DT_REG) {
-            if (!ParseConfigFile(current_path)) {
-                LOG(ERROR) << "could not import file '" << current_path << "'";
-            }
+            std::string current_path =
+                android::base::StringPrintf("%s/%s", path.c_str(), current_file->d_name);
+            files.emplace_back(current_path);
+        }
+    }
+    // Sort first so we load files in a consistent order (bug 31996208)
+    std::sort(files.begin(), files.end());
+    for (const auto& file : files) {
+        if (!ParseConfigFile(file)) {
+            LOG(ERROR) << "could not import file '" << file << "'";
         }
     }
     return true;
diff --git a/init/service.cpp b/init/service.cpp
index 503d84f..22fb013 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -31,6 +31,7 @@
 #include <selinux/selinux.h>
 
 #include <android-base/file.h>
+#include <android-base/parseint.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <cutils/android_reboot.h>
@@ -46,6 +47,7 @@
 #include "property_service.h"
 #include "util.h"
 
+using android::base::ParseInt;
 using android::base::StringPrintf;
 using android::base::WriteStringToFile;
 
@@ -351,22 +353,19 @@
 }
 
 bool Service::ParsePriority(const std::vector<std::string>& args, std::string* err) {
-    priority_ = std::stoi(args[1]);
-
-    if (priority_ < ANDROID_PRIORITY_HIGHEST || priority_ > ANDROID_PRIORITY_LOWEST) {
-        priority_ = 0;
+    priority_ = 0;
+    if (!ParseInt(args[1], &priority_,
+                  static_cast<int>(ANDROID_PRIORITY_LOWEST),
+                  static_cast<int>(ANDROID_PRIORITY_HIGHEST))) {
         *err = StringPrintf("process priority value must be range %d - %d",
                 ANDROID_PRIORITY_HIGHEST, ANDROID_PRIORITY_LOWEST);
         return false;
     }
-
     return true;
 }
 
 bool Service::ParseIoprio(const std::vector<std::string>& args, std::string* err) {
-    ioprio_pri_ = std::stoul(args[2], 0, 8);
-
-    if (ioprio_pri_ < 0 || ioprio_pri_ > 7) {
+    if (!ParseInt(args[2], &ioprio_pri_, 0, 7)) {
         *err = "priority value must be range 0 - 7";
         return false;
     }
@@ -387,7 +386,12 @@
 
 bool Service::ParseKeycodes(const std::vector<std::string>& args, std::string* err) {
     for (std::size_t i = 1; i < args.size(); i++) {
-        keycodes_.emplace_back(std::stoi(args[i]));
+        int code;
+        if (ParseInt(args[i], &code)) {
+            keycodes_.emplace_back(code);
+        } else {
+            LOG(WARNING) << "ignoring invalid keycode: " << args[i];
+        }
     }
     return true;
 }
@@ -420,17 +424,13 @@
 }
 
 bool Service::ParseOomScoreAdjust(const std::vector<std::string>& args, std::string* err) {
-    oom_score_adjust_ = std::stol(args[1], 0, 10);
-
-    if (oom_score_adjust_ < -1000 || oom_score_adjust_ > 1000) {
+    if (!ParseInt(args[1], &oom_score_adjust_, -1000, 1000)) {
         *err = "oom_score_adjust value must be in range -1000 - +1000";
         return false;
     }
-
     return true;
 }
 
-
 bool Service::ParseSeclabel(const std::vector<std::string>& args, std::string* err) {
     seclabel_ = args[1];
     return true;
@@ -448,7 +448,7 @@
         return false;
     }
 
-    int perm = std::stoul(args[3], 0, 8);
+    int perm = std::strtoul(args[3].c_str(), 0, 8);
     uid_t uid = args.size() > 4 ? decode_uid(args[4].c_str()) : 0;
     gid_t gid = args.size() > 5 ? decode_uid(args[5].c_str()) : 0;
     std::string socketcon = args.size() > 6 ? args[6] : "";
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index 93d997b..85b5597 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -21,8 +21,6 @@
         "-Wall",
         "-Werror",
     ],
-    conlyflags: ["-std=gnu99"],
-    cppflags: ["-std=gnu++11"],
 
     clang_cflags: ["-Wno-inline-asm"],
 
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index 56a3970..bb17325 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -20,12 +20,6 @@
 	-Wall \
 	-Werror \
 
-libbacktrace_common_conlyflags := \
-	-std=gnu99 \
-
-libbacktrace_common_cppflags := \
-	-std=gnu++11 \
-
 libbacktrace_common_c_includes := \
 	external/libunwind/include/tdep \
 
diff --git a/libbacktrace/BacktracePtrace.cpp b/libbacktrace/BacktracePtrace.cpp
index fd8b713..148c418 100644
--- a/libbacktrace/BacktracePtrace.cpp
+++ b/libbacktrace/BacktracePtrace.cpp
@@ -17,6 +17,7 @@
 #include <errno.h>
 #include <stdint.h>
 #include <string.h>
+#include <sys/uio.h>
 #include <sys/param.h>
 #include <sys/ptrace.h>
 #include <sys/types.h>
@@ -72,42 +73,20 @@
   if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
     return 0;
   }
-
   bytes = MIN(map.end - addr, bytes);
-  size_t bytes_read = 0;
-  word_t data_word;
-  size_t align_bytes = addr & (sizeof(word_t) - 1);
-  if (align_bytes != 0) {
-    if (!PtraceRead(Tid(), addr & ~(sizeof(word_t) - 1), &data_word)) {
-      return 0;
-    }
-    size_t copy_bytes = MIN(sizeof(word_t) - align_bytes, bytes);
-    memcpy(buffer, reinterpret_cast<uint8_t*>(&data_word) + align_bytes, copy_bytes);
-    addr += copy_bytes;
-    buffer += copy_bytes;
-    bytes -= copy_bytes;
-    bytes_read += copy_bytes;
-  }
 
-  size_t num_words = bytes / sizeof(word_t);
-  for (size_t i = 0; i < num_words; i++) {
-    if (!PtraceRead(Tid(), addr, &data_word)) {
-      return bytes_read;
-    }
-    memcpy(buffer, &data_word, sizeof(word_t));
-    buffer += sizeof(word_t);
-    addr += sizeof(word_t);
-    bytes_read += sizeof(word_t);
-  }
+  struct iovec local_io;
+  local_io.iov_base = buffer;
+  local_io.iov_len = bytes;
 
-  size_t left_over = bytes & (sizeof(word_t) - 1);
-  if (left_over) {
-    if (!PtraceRead(Tid(), addr, &data_word)) {
-      return bytes_read;
-    }
-    memcpy(buffer, &data_word, left_over);
-    bytes_read += left_over;
+  struct iovec remote_io;
+  remote_io.iov_base = reinterpret_cast<void*>(addr);
+  remote_io.iov_len = bytes;
+
+  ssize_t bytes_read = process_vm_readv(Tid(), &local_io, 1, &remote_io, 1, 0);
+  if (bytes_read == -1) {
+    return 0;
   }
-  return bytes_read;
+  return static_cast<size_t>(bytes_read);
 #endif
 }
diff --git a/libcrypto_utils/Android.bp b/libcrypto_utils/Android.bp
index ca7bd31..f2560e6 100644
--- a/libcrypto_utils/Android.bp
+++ b/libcrypto_utils/Android.bp
@@ -24,7 +24,6 @@
         "-Wall",
         "-Wextra",
         "-Werror",
-        "-std=c99",
     ],
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
diff --git a/libcrypto_utils/tests/Android.mk b/libcrypto_utils/tests/Android.mk
index bdaef71..ef3d0cf 100644
--- a/libcrypto_utils/tests/Android.mk
+++ b/libcrypto_utils/tests/Android.mk
@@ -19,6 +19,6 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := libcrypto_utils_test
 LOCAL_SRC_FILES := android_pubkey_test.cpp
-LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c++11
+LOCAL_CFLAGS := -Wall -Werror -Wextra
 LOCAL_SHARED_LIBRARIES := libcrypto_utils libcrypto
 include $(BUILD_HOST_NATIVE_TEST)
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 8624d13..943926b 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -23,7 +23,6 @@
     "socket_inaddr_any_server_unix.c",
     "socket_local_client_unix.c",
     "socket_local_server_unix.c",
-    "socket_loopback_client_unix.c",
     "socket_loopback_server_unix.c",
     "socket_network_client_unix.c",
     "sockets_unix.cpp",
@@ -87,18 +86,8 @@
                 "uevent.c",
             ],
 
-            // TODO: remove liblog as whole static library, once we don't have prebuilt that requires
-            // liblog symbols present in libcutils.
-            whole_static_libs: [
-                "liblog",
-            ],
-
             static_libs: ["libdebuggerd_client"],
             export_static_lib_headers: ["libdebuggerd_client"],
-
-            cflags: [
-                "-std=gnu90",
-            ],
         },
 
         android_arm: {
diff --git a/libcutils/native_handle.c b/libcutils/native_handle.c
index 7f3479d..9f4840a 100644
--- a/libcutils/native_handle.c
+++ b/libcutils/native_handle.c
@@ -28,6 +28,20 @@
 static const int kMaxNativeFds = 1024;
 static const int kMaxNativeInts = 1024;
 
+native_handle_t* native_handle_init(char* storage, int numFds, int numInts)
+{
+    if ((uintptr_t) storage % alignof(native_handle_t)) {
+        return NULL;
+    }
+
+    native_handle_t* handle = (native_handle_t*) storage;
+    handle->version = sizeof(native_handle_t);
+    handle->numFds = numFds;
+    handle->numInts = numInts;
+
+    return handle;
+}
+
 native_handle_t* native_handle_create(int numFds, int numInts)
 {
     if (numFds < 0 || numInts < 0 || numFds > kMaxNativeFds || numInts > kMaxNativeInts) {
@@ -44,6 +58,27 @@
     return h;
 }
 
+native_handle_t* native_handle_clone(const native_handle_t* handle)
+{
+    native_handle_t* clone = native_handle_create(handle->numFds, handle->numInts);
+    int i;
+
+    for (i = 0; i < handle->numFds; i++) {
+        clone->data[i] = dup(handle->data[i]);
+        if (clone->data[i] < 0) {
+            clone->numFds = i;
+            native_handle_close(clone);
+            native_handle_delete(clone);
+            return NULL;
+        }
+    }
+
+    memcpy(&clone->data[handle->numFds], &handle->data[handle->numFds],
+            sizeof(int) * handle->numInts);
+
+    return clone;
+}
+
 int native_handle_delete(native_handle_t* h)
 {
     if (h) {
diff --git a/libcutils/socket_loopback_client_unix.c b/libcutils/socket_loopback_client_unix.c
deleted file mode 100644
index e14cffb..0000000
--- a/libcutils/socket_loopback_client_unix.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#if !defined(_WIN32)
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#endif
-
-#include <cutils/sockets.h>
-
-/* Connect to port on the loopback IP interface. type is
- * SOCK_STREAM or SOCK_DGRAM. 
- * return is a file descriptor or -1 on error
- */
-int socket_loopback_client(int port, int type)
-{
-    struct sockaddr_in addr;
-    int s;
-
-    memset(&addr, 0, sizeof(addr));
-    addr.sin_family = AF_INET;
-    addr.sin_port = htons(port);
-    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
-    s = socket(AF_INET, type, 0);
-    if(s < 0) return -1;
-
-    if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-        close(s);
-        return -1;
-    }
-
-    return s;
-
-}
-
diff --git a/libcutils/socket_loopback_server_unix.c b/libcutils/socket_loopback_server_unix.c
index b600e34..7b92fd6 100644
--- a/libcutils/socket_loopback_server_unix.c
+++ b/libcutils/socket_loopback_server_unix.c
@@ -31,24 +31,18 @@
 
 #include <cutils/sockets.h>
 
-/* open listen() port on loopback interface */
-int socket_loopback_server(int port, int type)
+static int _socket_loopback_server(int family, int type, struct sockaddr * addr, size_t size)
 {
-    struct sockaddr_in addr;
     int s, n;
 
-    memset(&addr, 0, sizeof(addr));
-    addr.sin_family = AF_INET;
-    addr.sin_port = htons(port);
-    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
-    s = socket(AF_INET, type, 0);
-    if(s < 0) return -1;
+    s = socket(family, type, 0);
+    if(s < 0)
+        return -1;
 
     n = 1;
     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &n, sizeof(n));
 
-    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+    if(bind(s, addr, size) < 0) {
         close(s);
         return -1;
     }
@@ -60,10 +54,35 @@
 
         if (ret < 0) {
             close(s);
-            return -1; 
+            return -1;
         }
     }
 
     return s;
 }
 
+/* open listen() port on loopback IPv6 interface */
+int socket_loopback_server6(int port, int type)
+{
+    struct sockaddr_in6 addr;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin6_family = AF_INET6;
+    addr.sin6_port = htons(port);
+    addr.sin6_addr = in6addr_loopback;
+
+    return _socket_loopback_server(AF_INET6, type, (struct sockaddr *) &addr, sizeof(addr));
+}
+
+/* open listen() port on loopback interface */
+int socket_loopback_server(int port, int type)
+{
+    struct sockaddr_in addr;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+    return _socket_loopback_server(AF_INET, type, (struct sockaddr *) &addr, sizeof(addr));
+}
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/Android.bp b/liblog/Android.bp
index c59dde9..bbaced5 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -91,6 +91,21 @@
     compile_multilib: "both",
 }
 
+// system/core/android/log.h needs some work before it can be included in the
+// NDK. It defines a *lot* of macros that previously were usable names in NDK
+// sources that used android/log.h. As an example, the following file defines
+// LOG_TAG as a variable, but the variable name gets macro replaced if we use
+// the current android/log.h.
+// https://android.googlesource.com/platform/external/deqp/+/4adc1515f867b26c19c2f7498e9de93a230a234d/framework/platform/android/tcuTestLogParserJNI.cpp#41
+//
+// For now, we keep a copy of the old NDK android/log.h in legacy-ndk-includes.
+ndk_headers {
+    name: "liblog_headers",
+    from: "legacy-ndk-includes",
+    to: "android",
+    srcs: ["legacy-ndk-includes/log.h"],
+}
+
 ndk_library {
     name: "liblog.ndk",
     symbol_file: "liblog.map.txt",
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/legacy-ndk-includes/log.h b/liblog/legacy-ndk-includes/log.h
new file mode 100644
index 0000000..0ea4c29
--- /dev/null
+++ b/liblog/legacy-ndk-includes/log.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_LOG_H
+#define _ANDROID_LOG_H
+
+/******************************************************************
+ *
+ * IMPORTANT NOTICE:
+ *
+ *   This file is part of Android's set of stable system headers
+ *   exposed by the Android NDK (Native Development Kit) since
+ *   platform release 1.5
+ *
+ *   Third-party source AND binary code relies on the definitions
+ *   here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
+ *
+ *   - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
+ *   - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
+ *   - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
+ *   - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
+ */
+
+/*
+ * Support routines to send messages to the Android in-kernel log buffer,
+ * which can later be accessed through the 'logcat' utility.
+ *
+ * Each log message must have
+ *   - a priority
+ *   - a log tag
+ *   - some text
+ *
+ * The tag normally corresponds to the component that emits the log message,
+ * and should be reasonably small.
+ *
+ * Log message text may be truncated to less than an implementation-specific
+ * limit (e.g. 1023 characters max).
+ *
+ * Note that a newline character ("\n") will be appended automatically to your
+ * log message, if not already there. It is not possible to send several messages
+ * and have them appear on a single line in logcat.
+ *
+ * PLEASE USE LOGS WITH MODERATION:
+ *
+ *  - Sending log messages eats CPU and slow down your application and the
+ *    system.
+ *
+ *  - The circular log buffer is pretty small (<64KB), sending many messages
+ *    might push off other important log messages from the rest of the system.
+ *
+ *  - In release builds, only send log messages to account for exceptional
+ *    conditions.
+ *
+ * NOTE: These functions MUST be implemented by /system/lib/liblog.so
+ */
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Android log priority values, in ascending priority order.
+ */
+typedef enum android_LogPriority {
+    ANDROID_LOG_UNKNOWN = 0,
+    ANDROID_LOG_DEFAULT,    /* only for SetMinPriority() */
+    ANDROID_LOG_VERBOSE,
+    ANDROID_LOG_DEBUG,
+    ANDROID_LOG_INFO,
+    ANDROID_LOG_WARN,
+    ANDROID_LOG_ERROR,
+    ANDROID_LOG_FATAL,
+    ANDROID_LOG_SILENT,     /* only for SetMinPriority(); must be last */
+} android_LogPriority;
+
+/*
+ * Send a simple string to the log.
+ */
+int __android_log_write(int prio, const char *tag, const char *text);
+
+/*
+ * Send a formatted string to the log, used like printf(fmt,...)
+ */
+int __android_log_print(int prio, const char *tag,  const char *fmt, ...)
+#if defined(__GNUC__)
+    __attribute__ ((format(printf, 3, 4)))
+#endif
+    ;
+
+/*
+ * A variant of __android_log_print() that takes a va_list to list
+ * additional parameters.
+ */
+int __android_log_vprint(int prio, const char *tag,
+                         const char *fmt, va_list ap);
+
+/*
+ * Log an assertion failure and SIGTRAP the process to have a chance
+ * to inspect it, if a debugger is attached. This uses the FATAL priority.
+ */
+void __android_log_assert(const char *cond, const char *tag,
+			  const char *fmt, ...)    
+#if defined(__GNUC__)
+    __attribute__ ((noreturn))
+    __attribute__ ((format(printf, 3, 4)))
+#endif
+    ;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ANDROID_LOG_H */
diff --git a/liblog/log_event_list.c b/liblog/log_event_list.c
index a4244cd..11d8afb 100644
--- a/liblog/log_event_list.c
+++ b/liblog/log_event_list.c
@@ -22,8 +22,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <android/log.h>
-#include <log/logger.h>
+#include <private/android_logger.h>
 
 #include "log_portability.h"
 
diff --git a/liblog/log_is_loggable.c b/liblog/log_is_loggable.c
index 4af8507..132d96f 100644
--- a/liblog/log_is_loggable.c
+++ b/liblog/log_is_loggable.c
@@ -16,12 +16,16 @@
 
 #include <ctype.h>
 #include <pthread.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <sys/_system_properties.h>
+#include <unistd.h>
 
 #include <android/log.h>
+#include <log/logger.h>
+#include <private/android_logger.h>
 
 #include "log_portability.h"
 
@@ -47,12 +51,16 @@
 }
 
 struct cache {
-    const prop_info *pinfo;
+    const prop_info* pinfo;
     uint32_t serial;
+};
+
+struct cache_char {
+    struct cache cache;
     unsigned char c;
 };
 
-static int check_cache(struct cache *cache)
+static int check_cache(struct cache* cache)
 {
     return cache->pinfo
         && __system_property_serial(cache->pinfo) != cache->serial;
@@ -61,18 +69,18 @@
 #define BOOLEAN_TRUE 0xFF
 #define BOOLEAN_FALSE 0xFE
 
-static void refresh_cache(struct cache *cache, const char *key)
+static void refresh_cache(struct cache_char* cache, const char* key)
 {
     char buf[PROP_VALUE_MAX];
 
-    if (!cache->pinfo) {
-        cache->pinfo = __system_property_find(key);
-        if (!cache->pinfo) {
+    if (!cache->cache.pinfo) {
+        cache->cache.pinfo = __system_property_find(key);
+        if (!cache->cache.pinfo) {
             return;
         }
     }
-    cache->serial = __system_property_serial(cache->pinfo);
-    __system_property_read(cache->pinfo, 0, buf);
+    cache->cache.serial = __system_property_serial(cache->cache.pinfo);
+    __system_property_read(cache->cache.pinfo, 0, buf);
     switch(buf[0]) {
     case 't': case 'T':
         cache->c = strcasecmp(buf + 1, "rue") ? buf[0] : BOOLEAN_TRUE;
@@ -85,7 +93,7 @@
     }
 }
 
-static int __android_log_level(const char *tag, size_t len, int default_prio)
+static int __android_log_level(const char* tag, size_t len, int default_prio)
 {
     /* sizeof() is used on this array below */
     static const char log_namespace[] = "persist.log.tag.";
@@ -93,8 +101,8 @@
     /* calculate the size of our key temporary buffer */
     const size_t taglen = tag ? len : 0;
     /* sizeof(log_namespace) = strlen(log_namespace) + 1 */
-    char key[sizeof(log_namespace) + taglen]; /* may be > PROPERTY_KEY_MAX */
-    char *kp;
+    char key[sizeof(log_namespace) + taglen]; /* may be > PROP_NAME_MAX */
+    char* kp;
     size_t i;
     char c = 0;
     /*
@@ -110,8 +118,8 @@
     static uint32_t global_serial;
     /* some compilers erroneously see uninitialized use. !not_locked */
     uint32_t current_global_serial = 0;
-    static struct cache tag_cache[2];
-    static struct cache global_cache[2];
+    static struct cache_char tag_cache[2];
+    static struct cache_char global_cache[2];
     int change_detected;
     int global_change_detected;
     int not_locked;
@@ -125,12 +133,12 @@
          *  check all known serial numbers to changes.
          */
         for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
-            if (check_cache(&tag_cache[i])) {
+            if (check_cache(&tag_cache[i].cache)) {
                 change_detected = 1;
             }
         }
         for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
-            if (check_cache(&global_cache[i])) {
+            if (check_cache(&global_cache[i].cache)) {
                 global_change_detected = 1;
             }
         }
@@ -154,7 +162,7 @@
                     || ((len < sizeof(last_tag)) && last_tag[len])) {
                 /* invalidate log.tag.<tag> cache */
                 for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
-                    tag_cache[i].pinfo = NULL;
+                    tag_cache[i].cache.pinfo = NULL;
                     tag_cache[i].c = '\0';
                 }
                 last_tag[0] = '\0';
@@ -174,11 +182,11 @@
 
         kp = key;
         for (i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) {
-            struct cache *cache = &tag_cache[i];
-            struct cache temp_cache;
+            struct cache_char* cache = &tag_cache[i];
+            struct cache_char temp_cache;
 
             if (not_locked) {
-                temp_cache.pinfo = NULL;
+                temp_cache.cache.pinfo = NULL;
                 temp_cache.c = '\0';
                 cache = &temp_cache;
             }
@@ -212,13 +220,13 @@
 
         kp = key;
         for (i = 0; i < (sizeof(global_cache) / sizeof(global_cache[0])); ++i) {
-            struct cache *cache = &global_cache[i];
-            struct cache temp_cache;
+            struct cache_char* cache = &global_cache[i];
+            struct cache_char temp_cache;
 
             if (not_locked) {
                 temp_cache = *cache;
-                if (temp_cache.pinfo != cache->pinfo) { /* check atomic */
-                    temp_cache.pinfo = NULL;
+                if (temp_cache.cache.pinfo != cache->cache.pinfo) { /* check atomic */
+                    temp_cache.cache.pinfo = NULL;
                     temp_cache.c = '\0';
                 }
                 cache = &temp_cache;
@@ -257,7 +265,7 @@
 }
 
 LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio,
-                                                    const char *tag, size_t len,
+                                                    const char* tag, size_t len,
                                                     int default_prio)
 {
     int logLevel = __android_log_level(tag, len, default_prio);
@@ -265,7 +273,7 @@
 }
 
 LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio,
-                                                const char *tag,
+                                                const char* tag,
                                                 int default_prio)
 {
     int logLevel = __android_log_level(tag,
@@ -274,21 +282,21 @@
     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;
+    static struct cache_char 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' };
+        struct cache_char temp_cache = { { NULL, -1 }, '\0' };
         refresh_cache(&temp_cache, key);
         ret = temp_cache.c == '1';
     } else {
-        int change_detected = check_cache(&tag_cache);
+        int change_detected = check_cache(&tag_cache.cache);
         uint32_t current_serial = __system_property_area_serial();
         if (current_serial != serial) {
             change_detected = 1;
@@ -310,17 +318,17 @@
  * Since a change is rare, we will accept a trylock failure gracefully.
  * Use a separate lock from is_loggable to keep contention down b/25563384.
  */
-struct cache2 {
+struct cache2_char {
     pthread_mutex_t lock;
     uint32_t serial;
-    const char *key_persist;
-    struct cache cache_persist;
-    const char *key_ro;
-    struct cache cache_ro;
-    unsigned char (*const evaluate)(const struct cache2 *self);
+    const char* key_persist;
+    struct cache_char cache_persist;
+    const char* key_ro;
+    struct cache_char cache_ro;
+    unsigned char (*const evaluate)(const struct cache2_char *self);
 };
 
-static inline unsigned char do_cache2(struct cache2 *self)
+static inline unsigned char do_cache2_char(struct cache2_char *self)
 {
     uint32_t current_serial;
     int change_detected;
@@ -331,8 +339,8 @@
         return self->evaluate(self);
     }
 
-    change_detected = check_cache(&self->cache_persist)
-                   || check_cache(&self->cache_ro);
+    change_detected = check_cache(&self->cache_persist.cache)
+                   || check_cache(&self->cache_ro.cache);
     current_serial = __system_property_area_serial();
     if (current_serial != self->serial) {
         change_detected = 1;
@@ -349,7 +357,7 @@
     return c;
 }
 
-static unsigned char evaluate_persist_ro(const struct cache2 *self)
+static unsigned char evaluate_persist_ro(const struct cache2_char *self)
 {
     unsigned char c = self->cache_persist.c;
 
@@ -366,17 +374,17 @@
  */
 LIBLOG_ABI_PUBLIC clockid_t android_log_clockid()
 {
-    static struct cache2 clockid = {
+    static struct cache2_char clockid = {
         PTHREAD_MUTEX_INITIALIZER,
         0,
         "persist.logd.timestamp",
-        { NULL, -1, '\0' },
+        { { NULL, -1 }, '\0' },
         "ro.logd.timestamp",
-        { NULL, -1, '\0' },
+        { { NULL, -1 }, '\0' },
         evaluate_persist_ro
     };
 
-    return (tolower(do_cache2(&clockid)) == 'm')
+    return (tolower(do_cache2_char(&clockid)) == 'm')
         ? CLOCK_MONOTONIC
         : CLOCK_REALTIME;
 }
@@ -385,7 +393,7 @@
  * Security state generally remains constant, but the DO must be able
  * to turn off logging should it become spammy after an attack is detected.
  */
-static unsigned char evaluate_security(const struct cache2 *self)
+static unsigned char evaluate_security(const struct cache2_char *self)
 {
     unsigned char c = self->cache_ro.c;
 
@@ -394,15 +402,265 @@
 
 LIBLOG_ABI_PUBLIC int __android_log_security()
 {
-    static struct cache2 security = {
+    static struct cache2_char security = {
         PTHREAD_MUTEX_INITIALIZER,
         0,
         "persist.logd.security",
-        { NULL, -1, BOOLEAN_FALSE },
+        { { NULL, -1 }, BOOLEAN_FALSE },
         "ro.device_owner",
-        { NULL, -1, BOOLEAN_FALSE },
+        { { NULL, -1 }, BOOLEAN_FALSE },
         evaluate_security
     };
 
-    return do_cache2(&security);
+    return do_cache2_char(&security);
+}
+
+/*
+ * Interface that represents the logd buffer size determination so that others
+ * need not guess our intentions.
+ */
+
+/* Property helper */
+static bool check_flag(const char* prop, const char* flag) {
+    const char* cp = strcasestr(prop, flag);
+    if (!cp) {
+        return false;
+    }
+    /* We only will document comma (,) */
+    static const char sep[] = ",:;|+ \t\f";
+    if ((cp != prop) && !strchr(sep, cp[-1])) {
+        return false;
+    }
+    cp += strlen(flag);
+    return !*cp || !!strchr(sep, *cp);
+}
+
+/* cache structure */
+struct cache_property {
+    struct cache cache;
+    char property[PROP_VALUE_MAX];
+};
+
+static void refresh_cache_property(struct cache_property* cache, const char* key)
+{
+    if (!cache->cache.pinfo) {
+        cache->cache.pinfo = __system_property_find(key);
+        if (!cache->cache.pinfo) {
+            return;
+        }
+    }
+    cache->cache.serial = __system_property_serial(cache->cache.pinfo);
+    __system_property_read(cache->cache.pinfo, 0, cache->property);
+}
+
+/* get boolean with the logger twist that supports eng adjustments */
+LIBLOG_ABI_PRIVATE bool __android_logger_property_get_bool(const char* key,
+                                                           int flag)
+{
+    struct cache_property property = { { NULL, -1 }, { 0 } };
+    if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
+        char newkey[PROP_NAME_MAX];
+        snprintf(newkey, sizeof(newkey), "ro.%s", key);
+        refresh_cache_property(&property, newkey);
+        property.cache.pinfo = NULL;
+        property.cache.serial = -1;
+        snprintf(newkey, sizeof(newkey), "persist.%s", key);
+        refresh_cache_property(&property, newkey);
+        property.cache.pinfo = NULL;
+        property.cache.serial = -1;
+    }
+
+    refresh_cache_property(&property, key);
+
+    if (check_flag(property.property, "true")) {
+        return true;
+    }
+    if (check_flag(property.property, "false")) {
+        return false;
+    }
+    if (check_flag(property.property, "eng")) {
+       flag |= BOOL_DEFAULT_FLAG_ENG;
+    }
+    /* this is really a "not" flag */
+    if (check_flag(property.property, "svelte")) {
+       flag |= BOOL_DEFAULT_FLAG_SVELTE;
+    }
+
+    /* Sanity Check */
+    if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
+        flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
+        flag |= BOOL_DEFAULT_TRUE;
+    }
+
+    if ((flag & BOOL_DEFAULT_FLAG_SVELTE)
+            && __android_logger_property_get_bool("ro.config.low_ram",
+                                 BOOL_DEFAULT_FALSE)) {
+        return false;
+    }
+    if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
+        return false;
+    }
+
+    return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
+}
+
+LIBLOG_ABI_PRIVATE bool __android_logger_valid_buffer_size(unsigned long value)
+{
+    static long pages, pagesize;
+    unsigned long maximum;
+
+    if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
+        return false;
+    }
+
+    if (!pages) {
+        pages = sysconf(_SC_PHYS_PAGES);
+    }
+    if (pages < 1) {
+        return true;
+    }
+
+    if (!pagesize) {
+        pagesize = sysconf(_SC_PAGESIZE);
+        if (pagesize <= 1) {
+            pagesize = PAGE_SIZE;
+        }
+    }
+
+    /* maximum memory impact a somewhat arbitrary ~3% */
+    pages = (pages + 31) / 32;
+    maximum = pages * pagesize;
+
+    if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
+        return true;
+    }
+
+    return value <= maximum;
+}
+
+struct cache2_property_size {
+    pthread_mutex_t lock;
+    uint32_t serial;
+    const char* key_persist;
+    struct cache_property cache_persist;
+    const char* key_ro;
+    struct cache_property cache_ro;
+    unsigned long (*const evaluate)(const struct cache2_property_size* self);
+};
+
+static inline unsigned long do_cache2_property_size(struct cache2_property_size* self)
+{
+    uint32_t current_serial;
+    int change_detected;
+    unsigned long v;
+
+    if (pthread_mutex_trylock(&self->lock)) {
+        /* We are willing to accept some race in this context */
+        return self->evaluate(self);
+    }
+
+    change_detected = check_cache(&self->cache_persist.cache)
+                   || check_cache(&self->cache_ro.cache);
+    current_serial = __system_property_area_serial();
+    if (current_serial != self->serial) {
+        change_detected = 1;
+    }
+    if (change_detected) {
+        refresh_cache_property(&self->cache_persist, self->key_persist);
+        refresh_cache_property(&self->cache_ro, self->key_ro);
+        self->serial = current_serial;
+    }
+    v = self->evaluate(self);
+
+    pthread_mutex_unlock(&self->lock);
+
+    return v;
+}
+
+static unsigned long property_get_size_from_cache(const struct cache_property* cache)
+{
+    char* cp;
+    unsigned long value = strtoul(cache->property, &cp, 10);
+
+    switch(*cp) {
+    case 'm':
+    case 'M':
+        value *= 1024;
+    /* FALLTHRU */
+    case 'k':
+    case 'K':
+        value *= 1024;
+    /* FALLTHRU */
+    case '\0':
+        break;
+
+    default:
+        value = 0;
+    }
+
+    if (!__android_logger_valid_buffer_size(value)) {
+        value = 0;
+    }
+
+    return value;
+}
+
+static unsigned long evaluate_property_get_size(const struct cache2_property_size* self)
+{
+    unsigned long size = property_get_size_from_cache(&self->cache_persist);
+    if (size) {
+        return size;
+    }
+    return property_get_size_from_cache(&self->cache_ro);
+}
+
+LIBLOG_ABI_PRIVATE unsigned long __android_logger_get_buffer_size(log_id_t logId)
+{
+    static const char global_tunable[] = "persist.logd.size"; /* Settings App */
+    static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
+    static struct cache2_property_size global = {
+        PTHREAD_MUTEX_INITIALIZER,
+        0,
+        global_tunable,
+        { { NULL, -1 }, {} },
+        global_default,
+        { { NULL, -1 }, {} },
+        evaluate_property_get_size
+    };
+    char key_persist[PROP_NAME_MAX];
+    char key_ro[PROP_NAME_MAX];
+    struct cache2_property_size local = {
+        PTHREAD_MUTEX_INITIALIZER,
+        0,
+        key_persist,
+        { { NULL, -1 }, {} },
+        key_ro,
+        { { NULL, -1 }, {} },
+        evaluate_property_get_size
+    };
+    unsigned long property_size, default_size;
+
+    default_size =  do_cache2_property_size(&global);
+    if (!default_size) {
+        default_size = __android_logger_property_get_bool("ro.config.low_ram",
+                                                          BOOL_DEFAULT_FALSE)
+            ? LOG_BUFFER_MIN_SIZE /* 64K  */
+            : LOG_BUFFER_SIZE;    /* 256K */
+    }
+
+    snprintf(key_persist, sizeof(key_persist), "%s.%s",
+             global_tunable, android_log_id_to_name(logId));
+    snprintf(key_ro, sizeof(key_ro), "%s.%s",
+             global_default, android_log_id_to_name(logId));
+    property_size = do_cache2_property_size(&local);
+
+    if (!property_size) {
+        property_size = default_size;
+    }
+
+    if (!property_size) {
+        property_size = LOG_BUFFER_SIZE;
+    }
+
+    return property_size;
 }
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/Android.mk b/liblog/tests/Android.mk
index a755b98..158987a 100644
--- a/liblog/tests/Android.mk
+++ b/liblog/tests/Android.mk
@@ -28,7 +28,6 @@
     -Wall -Wextra \
     -Werror \
     -fno-builtin \
-    -std=gnu++11
 
 benchmark_src_files := \
     benchmark_main.cpp \
@@ -54,7 +53,6 @@
     -Wall -Wextra \
     -Werror \
     -fno-builtin \
-    -std=gnu++11
 
 test_src_files := \
     liblog_test.cpp
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/libmemunreachable/Android.bp b/libmemunreachable/Android.bp
index 85bc421..4662368 100644
--- a/libmemunreachable/Android.bp
+++ b/libmemunreachable/Android.bp
@@ -2,7 +2,6 @@
     name: "libmemunreachable_defaults",
 
     cflags: [
-        "-std=c++14",
         "-Wall",
         "-Wextra",
         "-Werror",
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
index 598dfcd..5fb56f2 100644
--- a/libnativebridge/Android.bp
+++ b/libnativebridge/Android.bp
@@ -12,7 +12,6 @@
         "-Wall",
     ],
     cppflags: [
-        "-std=gnu++11",
         "-fvisibility=protected",
     ],
 
diff --git a/libnativebridge/tests/Android.mk b/libnativebridge/tests/Android.mk
index 7265939..5ad1569 100644
--- a/libnativebridge/tests/Android.mk
+++ b/libnativebridge/tests/Android.mk
@@ -31,7 +31,6 @@
 $(foreach file,$(test_src_files), \
     $(eval include $(CLEAR_VARS)) \
     $(eval LOCAL_CLANG := true) \
-    $(eval LOCAL_CPPFLAGS := -std=gnu++11) \
     $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
     $(eval LOCAL_SRC_FILES := $(file)) \
     $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
@@ -41,7 +40,6 @@
 $(foreach file,$(test_src_files), \
     $(eval include $(CLEAR_VARS)) \
     $(eval LOCAL_CLANG := true) \
-    $(eval LOCAL_CPPFLAGS := -std=gnu++11) \
     $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
     $(eval LOCAL_SRC_FILES := $(file)) \
     $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
diff --git a/libnativebridge/tests/Android.nativebridge-dummy.mk b/libnativebridge/tests/Android.nativebridge-dummy.mk
index 551765a..e556f80 100644
--- a/libnativebridge/tests/Android.nativebridge-dummy.mk
+++ b/libnativebridge/tests/Android.nativebridge-dummy.mk
@@ -12,7 +12,7 @@
 LOCAL_SRC_FILES:= $(NATIVE_BRIDGE_COMMON_SRC_FILES)
 LOCAL_CLANG := true
 LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CPPFLAGS := -std=gnu++11 -fvisibility=protected
+LOCAL_CPPFLAGS := -fvisibility=protected
 LOCAL_SHARED_LIBRARIES := libdl
 LOCAL_MULTILIB := both
 
@@ -27,7 +27,7 @@
 LOCAL_SRC_FILES:= $(NATIVE_BRIDGE_COMMON_SRC_FILES)
 LOCAL_CLANG := true
 LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CPPFLAGS := -std=gnu++11 -fvisibility=protected
+LOCAL_CPPFLAGS := -fvisibility=protected
 LOCAL_LDFLAGS := -ldl
 LOCAL_MULTILIB := both
 
@@ -48,7 +48,7 @@
 LOCAL_SRC_FILES:= $(NATIVE_BRIDGE2_COMMON_SRC_FILES)
 LOCAL_CLANG := true
 LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CPPFLAGS := -std=gnu++11 -fvisibility=protected
+LOCAL_CPPFLAGS := -fvisibility=protected
 LOCAL_SHARED_LIBRARIES := libdl
 LOCAL_MULTILIB := both
 
@@ -63,7 +63,7 @@
 LOCAL_SRC_FILES:= $(NATIVE_BRIDGE2_COMMON_SRC_FILES)
 LOCAL_CLANG := true
 LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CPPFLAGS := -std=gnu++11 -fvisibility=protected
+LOCAL_CPPFLAGS := -fvisibility=protected
 LOCAL_LDFLAGS := -ldl
 LOCAL_MULTILIB := both
 
diff --git a/libnativeloader/Android.bp b/libnativeloader/Android.bp
index b4a69bc..30531bc 100644
--- a/libnativeloader/Android.bp
+++ b/libnativeloader/Android.bp
@@ -24,7 +24,6 @@
         "-Wall",
     ],
     cppflags: [
-        "-std=gnu++14",
         "-fvisibility=hidden",
     ],
     export_include_dirs: ["include"],
diff --git a/libsparse/output_file.c b/libsparse/output_file.c
index d284736..2115998 100644
--- a/libsparse/output_file.c
+++ b/libsparse/output_file.c
@@ -34,7 +34,7 @@
 #include "sparse_crc32.h"
 #include "sparse_format.h"
 
-#ifndef USE_MINGW
+#ifndef _WIN32
 #include <sys/mman.h>
 #define O_BINARY 0
 #else
@@ -63,7 +63,7 @@
 	int (*open)(struct output_file *, int fd);
 	int (*skip)(struct output_file *, int64_t);
 	int (*pad)(struct output_file *, int64_t);
-	int (*write)(struct output_file *, void *, int);
+	int (*write)(struct output_file *, void *, size_t);
 	void (*close)(struct output_file *);
 };
 
@@ -149,18 +149,23 @@
 	return 0;
 }
 
-static int file_write(struct output_file *out, void *data, int len)
+static int file_write(struct output_file *out, void *data, size_t len)
 {
-	int ret;
+	ssize_t ret;
 	struct output_file_normal *outn = to_output_file_normal(out);
 
-	ret = write(outn->fd, data, len);
-	if (ret < 0) {
-		error_errno("write");
-		return -1;
-	} else if (ret < len) {
-		error("incomplete write");
-		return -1;
+	while (len > 0) {
+		ret = write(outn->fd, data, len);
+		if (ret < 0) {
+			if (errno == EINTR) {
+				continue;
+			}
+			error_errno("write");
+			return -1;
+		}
+
+		data = (char *)data + ret;
+		len -= ret;
 	}
 
 	return 0;
@@ -232,18 +237,20 @@
 	return 0;
 }
 
-static int gz_file_write(struct output_file *out, void *data, int len)
+static int gz_file_write(struct output_file *out, void *data, size_t len)
 {
 	int ret;
 	struct output_file_gz *outgz = to_output_file_gz(out);
 
-	ret = gzwrite(outgz->gz_fd, data, len);
-	if (ret < 0) {
-		error_errno("gzwrite");
-		return -1;
-	} else if (ret < len) {
-		error("incomplete gzwrite");
-		return -1;
+	while (len > 0) {
+		ret = gzwrite(outgz->gz_fd, data,
+			      min(len, (unsigned int)INT_MAX));
+		if (ret == 0) {
+			error("gzwrite %s", gzerror(outgz->gz_fd, NULL));
+			return -1;
+		}
+		len -= ret;
+		data = (char *)data + ret;
 	}
 
 	return 0;
@@ -293,7 +300,7 @@
 	return -1;
 }
 
-static int callback_file_write(struct output_file *out, void *data, int len)
+static int callback_file_write(struct output_file *out, void *data, size_t len)
 {
 	struct output_file_callback *outc = to_output_file_callback(out);
 
@@ -698,14 +705,16 @@
 	int ret;
 	int64_t aligned_offset;
 	int aligned_diff;
-	int buffer_size;
+	uint64_t buffer_size;
 	char *ptr;
 
 	aligned_offset = offset & ~(4096 - 1);
 	aligned_diff = offset - aligned_offset;
-	buffer_size = len + aligned_diff;
+	buffer_size = (uint64_t)len + (uint64_t)aligned_diff;
 
-#ifndef USE_MINGW
+#ifndef _WIN32
+	if (buffer_size > SIZE_MAX)
+		return -E2BIG;
 	char *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, fd,
 			aligned_offset);
 	if (data == MAP_FAILED) {
@@ -733,7 +742,7 @@
 
 	ret = out->sparse_ops->write_data_chunk(out, len, ptr);
 
-#ifndef USE_MINGW
+#ifndef _WIN32
 	munmap(data, buffer_size);
 #else
 	free(data);
diff --git a/libsparse/sparse_read.c b/libsparse/sparse_read.c
index dbb4dab..a188202 100644
--- a/libsparse/sparse_read.c
+++ b/libsparse/sparse_read.c
@@ -79,7 +79,7 @@
 		s = " at ";
 	}
 	if (verbose) {
-#ifndef USE_MINGW
+#ifndef _WIN32
 		if (err == -EOVERFLOW) {
 			sparse_print_verbose("EOF while reading file%s%s\n", s, at);
 		} else
diff --git a/libsync/Android.bp b/libsync/Android.bp
index 4948aa5..a4e5599 100644
--- a/libsync/Android.bp
+++ b/libsync/Android.bp
@@ -34,7 +34,6 @@
         "-g",
         "-Wall",
         "-Werror",
-        "-std=gnu++11",
         "-Wno-missing-field-initializers",
         "-Wno-sign-compare",
     ],
diff --git a/libutils/Printer.cpp b/libutils/Printer.cpp
index 1dc8632..98cd2c6 100644
--- a/libutils/Printer.cpp
+++ b/libutils/Printer.cpp
@@ -44,7 +44,7 @@
 
     char* formattedString;
 
-#ifndef USE_MINGW
+#ifndef _WIN32
     if (vasprintf(&formattedString, format, arglist) < 0) { // returns -1 on error
         ALOGE("%s: Failed to format string", __FUNCTION__);
         return;
@@ -115,7 +115,7 @@
         return;
     }
 
-#ifndef USE_MINGW
+#ifndef _WIN32
     dprintf(mFd, mFormatString, mPrefix, string);
 #endif
 }
diff --git a/libziparchive/testdata/dummy-update.zip b/libziparchive/testdata/dummy-update.zip
new file mode 100644
index 0000000..6976bf1
--- /dev/null
+++ b/libziparchive/testdata/dummy-update.zip
Binary files differ
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index cc3f0e4..b00557c 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -215,19 +215,14 @@
   return 0;
 }
 
-static int32_t MapCentralDirectory0(int fd, const char* debug_file_name,
-                                    ZipArchive* archive, off64_t file_length,
-                                    off64_t read_amount, uint8_t* scan_buffer) {
+static int32_t MapCentralDirectory0(const char* debug_file_name, ZipArchive* archive,
+                                    off64_t file_length, off64_t read_amount,
+                                    uint8_t* scan_buffer) {
   const off64_t search_start = file_length - read_amount;
 
-  if (lseek64(fd, search_start, SEEK_SET) != search_start) {
-    ALOGW("Zip: seek %" PRId64 " failed: %s", static_cast<int64_t>(search_start),
-          strerror(errno));
-    return kIoError;
-  }
-  if (!android::base::ReadFully(fd, scan_buffer, static_cast<size_t>(read_amount))) {
-    ALOGW("Zip: read %" PRId64 " failed: %s", static_cast<int64_t>(read_amount),
-          strerror(errno));
+  if(!archive->mapped_zip.ReadAtOffset(scan_buffer, read_amount, search_start)) {
+    ALOGE("Zip: read %" PRId64 " from offset %" PRId64 " failed",
+          static_cast<int64_t>(read_amount), static_cast<int64_t>(search_start));
     return kIoError;
   }
 
@@ -287,9 +282,11 @@
    * It all looks good.  Create a mapping for the CD, and set the fields
    * in archive.
    */
-  if (!archive->directory_map.create(debug_file_name, fd,
-          static_cast<off64_t>(eocd->cd_start_offset),
-          static_cast<size_t>(eocd->cd_size), true /* read only */) ) {
+
+  if (!archive->InitializeCentralDirectory(debug_file_name,
+                                           static_cast<off64_t>(eocd->cd_start_offset),
+                                           static_cast<size_t>(eocd->cd_size))) {
+    ALOGE("Zip: failed to intialize central directory.\n");
     return kMmapFailed;
   }
 
@@ -304,18 +301,16 @@
  *
  * On success, returns 0 after populating fields from the EOCD area:
  *   directory_offset
- *   directory_map
+ *   directory_ptr
  *   num_entries
  */
-static int32_t MapCentralDirectory(int fd, const char* debug_file_name,
-                                   ZipArchive* archive) {
+static int32_t MapCentralDirectory(const char* debug_file_name, ZipArchive* archive) {
 
   // Test file length. We use lseek64 to make sure the file
   // is small enough to be a zip file (Its size must be less than
   // 0xffffffff bytes).
-  off64_t file_length = lseek64(fd, 0, SEEK_END);
+  off64_t file_length = archive->mapped_zip.GetFileLength();
   if (file_length == -1) {
-    ALOGV("Zip: lseek on fd %d failed", fd);
     return kInvalidFile;
   }
 
@@ -346,11 +341,9 @@
     read_amount = file_length;
   }
 
-  uint8_t* scan_buffer = reinterpret_cast<uint8_t*>(malloc(read_amount));
-  int32_t result = MapCentralDirectory0(fd, debug_file_name, archive,
-                                        file_length, read_amount, scan_buffer);
-
-  free(scan_buffer);
+  std::vector<uint8_t> scan_buffer(read_amount);
+  int32_t result = MapCentralDirectory0(debug_file_name, archive, file_length, read_amount,
+                                        scan_buffer.data());
   return result;
 }
 
@@ -361,9 +354,8 @@
  * Returns 0 on success.
  */
 static int32_t ParseZipArchive(ZipArchive* archive) {
-  const uint8_t* const cd_ptr =
-      reinterpret_cast<const uint8_t*>(archive->directory_map.getDataPtr());
-  const size_t cd_length = archive->directory_map.getDataLength();
+  const uint8_t* const cd_ptr = archive->central_directory.GetBasePtr();
+  const size_t cd_length = archive->central_directory.GetMapLength();
   const uint16_t num_entries = archive->num_entries;
 
   /*
@@ -437,7 +429,7 @@
 static int32_t OpenArchiveInternal(ZipArchive* archive,
                                    const char* debug_file_name) {
   int32_t result = -1;
-  if ((result = MapCentralDirectory(archive->fd, debug_file_name, archive))) {
+  if ((result = MapCentralDirectory(debug_file_name, archive)) != 0) {
     return result;
   }
 
@@ -468,6 +460,13 @@
   return OpenArchiveInternal(archive, fileName);
 }
 
+int32_t OpenArchiveFromMemory(void* address, size_t length, const char* debug_file_name,
+                              ZipArchiveHandle *handle) {
+  ZipArchive* archive = new ZipArchive(address, length);
+  *handle = archive;
+  return OpenArchiveInternal(archive, debug_file_name);
+}
+
 /*
  * Close a ZipArchive, closing the file and freeing the contents.
  */
@@ -477,10 +476,10 @@
   delete archive;
 }
 
-static int32_t UpdateEntryFromDataDescriptor(int fd,
+static int32_t UpdateEntryFromDataDescriptor(MappedZipFile& mapped_zip,
                                              ZipEntry *entry) {
   uint8_t ddBuf[sizeof(DataDescriptor) + sizeof(DataDescriptor::kOptSignature)];
-  if (!android::base::ReadFully(fd, ddBuf, sizeof(ddBuf))) {
+  if (!mapped_zip.ReadData(ddBuf, sizeof(ddBuf))) {
     return kIoError;
   }
 
@@ -495,23 +494,6 @@
   return 0;
 }
 
-// Attempts to read |len| bytes into |buf| at offset |off|.
-// On non-Windows platforms, callers are guaranteed that the |fd|
-// offset is unchanged and there is no side effect to this call.
-//
-// On Windows platforms this is not thread-safe.
-static inline bool ReadAtOffset(int fd, uint8_t* buf, size_t len, off64_t off) {
-#if !defined(_WIN32)
-  return TEMP_FAILURE_RETRY(pread64(fd, buf, len, off));
-#else
-  if (lseek64(fd, off, SEEK_SET) != off) {
-    ALOGW("Zip: failed seek to offset %" PRId64, off);
-    return false;
-  }
-  return android::base::ReadFully(fd, buf, len);
-#endif
-}
-
 static int32_t FindEntry(const ZipArchive* archive, const int ent,
                          ZipEntry* data) {
   const uint16_t nameLen = archive->hash_table[ent].name_length;
@@ -525,9 +507,8 @@
   // This is the base of our mmapped region, we have to sanity check that
   // the name that's in the hash table is a pointer to a location within
   // this mapped region.
-  const uint8_t* base_ptr = reinterpret_cast<const uint8_t*>(
-    archive->directory_map.getDataPtr());
-  if (ptr < base_ptr || ptr > base_ptr + archive->directory_map.getDataLength()) {
+  const uint8_t* base_ptr = archive->central_directory.GetBasePtr();
+  if (ptr < base_ptr || ptr > base_ptr + archive->central_directory.GetMapLength()) {
     ALOGW("Zip: Invalid entry pointer");
     return kInvalidOffset;
   }
@@ -559,7 +540,7 @@
   }
 
   uint8_t lfh_buf[sizeof(LocalFileHeader)];
-  if (!ReadAtOffset(archive->fd, lfh_buf, sizeof(lfh_buf), local_header_offset)) {
+  if (!archive->mapped_zip.ReadAtOffset(lfh_buf, sizeof(lfh_buf), local_header_offset)) {
     ALOGW("Zip: failed reading lfh name from offset %" PRId64,
         static_cast<int64_t>(local_header_offset));
     return kIoError;
@@ -599,19 +580,16 @@
       return kInvalidOffset;
     }
 
-    uint8_t* name_buf = reinterpret_cast<uint8_t*>(malloc(nameLen));
-    if (!ReadAtOffset(archive->fd, name_buf, nameLen, name_offset)) {
+    std::vector<uint8_t> name_buf(nameLen);
+    if (!archive->mapped_zip.ReadAtOffset(name_buf.data(), nameLen, name_offset)) {
       ALOGW("Zip: failed reading lfh name from offset %" PRId64, static_cast<int64_t>(name_offset));
-      free(name_buf);
       return kIoError;
     }
 
-    if (memcmp(archive->hash_table[ent].name, name_buf, nameLen)) {
-      free(name_buf);
+    if (memcmp(archive->hash_table[ent].name, name_buf.data(), nameLen)) {
       return kInconsistentInformation;
     }
 
-    free(name_buf);
   } else {
     ALOGW("Zip: lfh name did not match central directory.");
     return kInconsistentInformation;
@@ -881,7 +859,7 @@
 }
 #pragma GCC diagnostic pop
 
-static int32_t InflateEntryToWriter(int fd, const ZipEntry* entry,
+static int32_t InflateEntryToWriter(MappedZipFile& mapped_zip, const ZipEntry* entry,
                                     Writer* writer, uint64_t* crc_out) {
   const size_t kBufSize = 32768;
   std::vector<uint8_t> read_buf(kBufSize);
@@ -931,7 +909,7 @@
     /* read as much as we can */
     if (zstream.avail_in == 0) {
       const size_t getSize = (compressed_length > kBufSize) ? kBufSize : compressed_length;
-      if (!android::base::ReadFully(fd, read_buf.data(), getSize)) {
+      if (!mapped_zip.ReadData(read_buf.data(), getSize)) {
         ALOGW("Zip: inflate read failed, getSize = %zu: %s", getSize, strerror(errno));
         return kIoError;
       }
@@ -979,7 +957,7 @@
   return 0;
 }
 
-static int32_t CopyEntryToWriter(int fd, const ZipEntry* entry, Writer* writer,
+static int32_t CopyEntryToWriter(MappedZipFile& mapped_zip, const ZipEntry* entry, Writer* writer,
                                  uint64_t *crc_out) {
   static const uint32_t kBufSize = 32768;
   std::vector<uint8_t> buf(kBufSize);
@@ -993,7 +971,7 @@
     // Safe conversion because kBufSize is narrow enough for a 32 bit signed
     // value.
     const size_t block_size = (remaining > kBufSize) ? kBufSize : remaining;
-    if (!android::base::ReadFully(fd, buf.data(), block_size)) {
+    if (!mapped_zip.ReadData(buf.data(), block_size)) {
       ALOGW("CopyFileToFile: copy read failed, block_size = %zu: %s", block_size, strerror(errno));
       return kIoError;
     }
@@ -1016,7 +994,7 @@
   const uint16_t method = entry->method;
   off64_t data_offset = entry->offset;
 
-  if (lseek64(archive->fd, data_offset, SEEK_SET) != data_offset) {
+  if (!archive->mapped_zip.SeekToOffset(data_offset)) {
     ALOGW("Zip: lseek to data at %" PRId64 " failed", static_cast<int64_t>(data_offset));
     return kIoError;
   }
@@ -1025,13 +1003,13 @@
   int32_t return_value = -1;
   uint64_t crc = 0;
   if (method == kCompressStored) {
-    return_value = CopyEntryToWriter(archive->fd, entry, writer, &crc);
+    return_value = CopyEntryToWriter(archive->mapped_zip, entry, writer, &crc);
   } else if (method == kCompressDeflated) {
-    return_value = InflateEntryToWriter(archive->fd, entry, writer, &crc);
+    return_value = InflateEntryToWriter(archive->mapped_zip, entry, writer, &crc);
   }
 
   if (!return_value && entry->has_data_descriptor) {
-    return_value = UpdateEntryFromDataDescriptor(archive->fd, entry);
+    return_value = UpdateEntryFromDataDescriptor(archive->mapped_zip, entry);
     if (return_value) {
       return return_value;
     }
@@ -1072,7 +1050,7 @@
 }
 
 int GetFileDescriptor(const ZipArchiveHandle handle) {
-  return reinterpret_cast<ZipArchive*>(handle)->fd;
+  return reinterpret_cast<ZipArchive*>(handle)->mapped_zip.GetFileDescriptor();
 }
 
 ZipString::ZipString(const char* entry_name)
@@ -1081,3 +1059,143 @@
   CHECK_LE(len, static_cast<size_t>(UINT16_MAX));
   name_length = static_cast<uint16_t>(len);
 }
+
+#if !defined(_WIN32)
+class ProcessWriter : public Writer {
+ public:
+  ProcessWriter(ProcessZipEntryFunction func, void* cookie) : Writer(),
+    proc_function_(func),
+    cookie_(cookie) {
+  }
+
+  virtual bool Append(uint8_t* buf, size_t buf_size) override {
+    return proc_function_(buf, buf_size, cookie_);
+  }
+
+ private:
+  ProcessZipEntryFunction proc_function_;
+  void* cookie_;
+};
+
+int32_t ProcessZipEntryContents(ZipArchiveHandle handle, ZipEntry* entry,
+                                ProcessZipEntryFunction func, void* cookie) {
+  ProcessWriter writer(func, cookie);
+  return ExtractToWriter(handle, entry, &writer);
+}
+
+#endif //!defined(_WIN32)
+
+int MappedZipFile::GetFileDescriptor() const {
+  if (!has_fd_) {
+    ALOGW("Zip: MappedZipFile doesn't have a file descriptor.");
+    return -1;
+  }
+  return fd_;
+}
+
+void* MappedZipFile::GetBasePtr() const {
+  if (has_fd_) {
+    ALOGW("Zip: MappedZipFile doesn't have a base pointer.");
+    return nullptr;
+  }
+  return base_ptr_;
+}
+
+off64_t MappedZipFile::GetFileLength() const {
+  if (has_fd_) {
+    off64_t result = lseek64(fd_, 0, SEEK_END);
+    if (result == -1) {
+      ALOGE("Zip: lseek on fd %d failed: %s", fd_, strerror(errno));
+    }
+    return result;
+  } else {
+    if (base_ptr_ == nullptr) {
+      ALOGE("Zip: invalid file map\n");
+      return -1;
+    }
+    return static_cast<off64_t>(data_length_);
+  }
+}
+
+bool MappedZipFile::SeekToOffset(off64_t offset) {
+  if (has_fd_) {
+    if (lseek64(fd_, offset, SEEK_SET) != offset) {
+      ALOGE("Zip: lseek to %" PRId64 " failed: %s\n", offset, strerror(errno));
+      return false;
+    }
+    return true;
+  } else {
+    if (offset < 0 || offset > static_cast<off64_t>(data_length_)) {
+      ALOGE("Zip: invalid offset: %" PRId64 ", data length: %" PRId64 "\n" , offset,
+            data_length_);
+      return false;
+    }
+
+    read_pos_ = offset;
+    return true;
+  }
+}
+
+bool MappedZipFile::ReadData(uint8_t* buffer, size_t read_amount) {
+  if (has_fd_) {
+    if(!android::base::ReadFully(fd_, buffer, read_amount)) {
+      ALOGE("Zip: read from %d failed\n", fd_);
+      return false;
+    }
+  } else {
+    memcpy(buffer, static_cast<uint8_t*>(base_ptr_) + read_pos_, read_amount);
+    read_pos_ += read_amount;
+  }
+  return true;
+}
+
+// Attempts to read |len| bytes into |buf| at offset |off|.
+bool MappedZipFile::ReadAtOffset(uint8_t* buf, size_t len, off64_t off) {
+#if !defined(_WIN32)
+  if (has_fd_) {
+    if (static_cast<size_t>(TEMP_FAILURE_RETRY(pread64(fd_, buf, len, off))) != len) {
+      ALOGE("Zip: failed to read at offset %" PRId64 "\n", off);
+      return false;
+    }
+    return true;
+  }
+#endif
+  if (!SeekToOffset(off)) {
+    return false;
+  }
+  return ReadData(buf, len);
+
+}
+
+void CentralDirectory::Initialize(void* map_base_ptr, off64_t cd_start_offset, size_t cd_size) {
+  base_ptr_ = static_cast<uint8_t*>(map_base_ptr) + cd_start_offset;
+  length_ = cd_size;
+}
+
+bool ZipArchive::InitializeCentralDirectory(const char* debug_file_name, off64_t cd_start_offset,
+                                            size_t cd_size) {
+  if (mapped_zip.HasFd()) {
+    if (!directory_map->create(debug_file_name, mapped_zip.GetFileDescriptor(),
+                               cd_start_offset, cd_size, true /* read only */)) {
+      return false;
+    }
+
+    CHECK_EQ(directory_map->getDataLength(), cd_size);
+    central_directory.Initialize(directory_map->getDataPtr(), 0/*offset*/, cd_size);
+  } else {
+    if (mapped_zip.GetBasePtr() == nullptr) {
+      ALOGE("Zip: Failed to map central directory, bad mapped_zip base pointer\n");
+      return false;
+    }
+    if (static_cast<off64_t>(cd_start_offset) + static_cast<off64_t>(cd_size) >
+        mapped_zip.GetFileLength()) {
+      ALOGE("Zip: Failed to map central directory, offset exceeds mapped memory region ("
+            "start_offset %"  PRId64 ", cd_size %zu, mapped_region_size %" PRId64 ")",
+            static_cast<int64_t>(cd_start_offset), cd_size, mapped_zip.GetFileLength());
+      return false;
+    }
+
+    central_directory.Initialize(mapped_zip.GetBasePtr(), cd_start_offset, cd_size);
+  }
+  return true;
+}
diff --git a/libziparchive/zip_archive_private.h b/libziparchive/zip_archive_private.h
index ab52368..971db4f 100644
--- a/libziparchive/zip_archive_private.h
+++ b/libziparchive/zip_archive_private.h
@@ -21,17 +21,83 @@
 #include <stdlib.h>
 #include <unistd.h>
 
+#include <memory>
+#include <vector>
+
 #include <utils/FileMap.h>
 #include <ziparchive/zip_archive.h>
 
+class MappedZipFile {
+ public:
+  explicit MappedZipFile(const int fd) :
+    has_fd_(true),
+    fd_(fd),
+    base_ptr_(nullptr),
+    data_length_(0),
+    read_pos_(0) {}
+
+  explicit MappedZipFile(void* address, size_t length) :
+    has_fd_(false),
+    fd_(-1),
+    base_ptr_(address),
+    data_length_(static_cast<off64_t>(length)),
+    read_pos_(0) {}
+
+  bool HasFd() const {return has_fd_;}
+
+  int GetFileDescriptor() const;
+
+  void* GetBasePtr() const;
+
+  off64_t GetFileLength() const;
+
+  bool SeekToOffset(off64_t offset);
+
+  bool ReadData(uint8_t* buffer, size_t read_amount);
+
+  bool ReadAtOffset(uint8_t* buf, size_t len, off64_t off);
+
+ private:
+  // If has_fd_ is true, fd is valid and we'll read contents of a zip archive
+  // from the file. Otherwise, we're opening the archive from a memory mapped
+  // file. In that case, base_ptr_ points to the start of the memory region and
+  // data_length_ defines the file length.
+  const bool has_fd_;
+
+  const int fd_;
+
+  void* const base_ptr_;
+  const off64_t data_length_;
+  // read_pos_ is the offset to the base_ptr_ where we read data from.
+  size_t read_pos_;
+};
+
+class CentralDirectory {
+ public:
+  CentralDirectory(void) :
+    base_ptr_(nullptr),
+    length_(0) {}
+
+  const uint8_t* GetBasePtr() const {return base_ptr_;}
+
+  size_t GetMapLength() const {return length_;}
+
+  void Initialize(void* map_base_ptr, off64_t cd_start_offset, size_t cd_size);
+
+ private:
+  const uint8_t* base_ptr_;
+  size_t length_;
+};
+
 struct ZipArchive {
   // open Zip archive
-  const int fd;
+  mutable MappedZipFile mapped_zip;
   const bool close_file;
 
   // mapped central directory area
   off64_t directory_offset;
-  android::FileMap directory_map;
+  CentralDirectory central_directory;
+  std::unique_ptr<android::FileMap> directory_map;
 
   // number of entries in the Zip archive
   uint16_t num_entries;
@@ -44,20 +110,36 @@
   ZipString* hash_table;
 
   ZipArchive(const int fd, bool assume_ownership) :
-      fd(fd),
-      close_file(assume_ownership),
-      directory_offset(0),
-      num_entries(0),
-      hash_table_size(0),
-      hash_table(NULL) {}
+    mapped_zip(fd),
+    close_file(assume_ownership),
+    directory_offset(0),
+    central_directory(),
+    directory_map(new android::FileMap()),
+    num_entries(0),
+    hash_table_size(0),
+    hash_table(nullptr) {}
+
+  ZipArchive(void* address, size_t length) :
+    mapped_zip(address, length),
+    close_file(false),
+    directory_offset(0),
+    central_directory(),
+    directory_map(new android::FileMap()),
+    num_entries(0),
+    hash_table_size(0),
+    hash_table(nullptr) {}
 
   ~ZipArchive() {
-    if (close_file && fd >= 0) {
-      close(fd);
+    if (close_file && mapped_zip.GetFileDescriptor() >= 0) {
+      close(mapped_zip.GetFileDescriptor());
     }
 
     free(hash_table);
   }
+
+  bool InitializeCentralDirectory(const char* debug_file_name, off64_t cd_start_offset,
+                                  size_t cd_size);
+
 };
 
 #endif  // LIBZIPARCHIVE_ZIPARCHIVE_PRIVATE_H_
diff --git a/libziparchive/zip_archive_stream_entry.cc b/libziparchive/zip_archive_stream_entry.cc
index 41988bc..64b24c3 100644
--- a/libziparchive/zip_archive_stream_entry.cc
+++ b/libziparchive/zip_archive_stream_entry.cc
@@ -39,7 +39,7 @@
 bool ZipArchiveStreamEntry::Init(const ZipEntry& entry) {
   ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle_);
   off64_t data_offset = entry.offset;
-  if (lseek64(archive->fd, data_offset, SEEK_SET) != data_offset) {
+  if (!archive->mapped_zip.SeekToOffset(data_offset)) {
     ALOGW("lseek to data at %" PRId64 " failed: %s", data_offset, strerror(errno));
     return false;
   }
@@ -88,7 +88,7 @@
   size_t bytes = (length_ > data_.size()) ? data_.size() : length_;
   ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle_);
   errno = 0;
-  if (!android::base::ReadFully(archive->fd, data_.data(), bytes)) {
+  if (!archive->mapped_zip.ReadData(data_.data(), bytes)) {
     if (errno != 0) {
       ALOGE("Error reading from archive fd: %s", strerror(errno));
     } else {
@@ -209,7 +209,7 @@
       size_t bytes = (compressed_length_ > in_.size()) ? in_.size() : compressed_length_;
       ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle_);
       errno = 0;
-      if (!android::base::ReadFully(archive->fd, in_.data(), bytes)) {
+      if (!archive->mapped_zip.ReadData(in_.data(), bytes)) {
         if (errno != 0) {
           ALOGE("Error reading from archive fd: %s", strerror(errno));
         } else {
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 6aee1bb..9dd6cc0 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -26,7 +26,9 @@
 
 #include <android-base/file.h>
 #include <android-base/test_utils.h>
+#include <android-base/unique_fd.h>
 #include <gtest/gtest.h>
+#include <utils/FileMap.h>
 #include <ziparchive/zip_archive.h>
 #include <ziparchive/zip_archive_stream_entry.h>
 
@@ -36,6 +38,7 @@
 static const std::string kValidZip = "valid.zip";
 static const std::string kLargeZip = "large.zip";
 static const std::string kBadCrcZip = "bad_crc.zip";
+static const std::string kUpdateZip = "dummy-update.zip";
 
 static const std::vector<uint8_t> kATxtContents {
   'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
@@ -494,6 +497,32 @@
             lseek64(tmp_file.fd, 0, SEEK_END));
 }
 
+#if !defined(_WIN32)
+TEST(ziparchive, OpenFromMemory) {
+  const std::string zip_path = test_data_dir + "/" + kUpdateZip;
+  android::base::unique_fd fd(open(zip_path.c_str(), O_RDONLY | O_BINARY));
+  ASSERT_NE(-1, fd);
+  struct stat sb;
+  ASSERT_EQ(0, fstat(fd, &sb));
+
+  // Memory map the file first and open the archive from the memory region.
+  android::FileMap file_map;
+  file_map.create(zip_path.c_str(), fd, 0/*offset*/, sb.st_size, true);
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveFromMemory(file_map.getDataPtr(), file_map.getDataLength(),
+                                     zip_path.c_str(), &handle));
+
+  // Assert one entry can be found and extracted correctly.
+  std::string BINARY_PATH("META-INF/com/google/android/update-binary");
+  ZipString binary_path(BINARY_PATH.c_str());
+  ZipEntry binary_entry;
+  ASSERT_EQ(0, FindEntry(handle, binary_path, &binary_entry));
+  TemporaryFile tmp_binary;
+  ASSERT_NE(-1, tmp_binary.fd);
+  ASSERT_EQ(0, ExtractEntryToFile(handle, &binary_entry, tmp_binary.fd));
+}
+#endif
+
 static void ZipArchiveStreamTest(
     ZipArchiveHandle& handle, const std::string& entry_name, bool raw,
     bool verified, ZipEntry* entry, std::vector<uint8_t>* read_data) {
diff --git a/logcat/tests/Android.mk b/logcat/tests/Android.mk
index a28664e..99c2e0a 100644
--- a/logcat/tests/Android.mk
+++ b/logcat/tests/Android.mk
@@ -25,7 +25,6 @@
     -Wall -Wextra \
     -Werror \
     -fno-builtin \
-    -std=gnu++11
 
 # -----------------------------------------------------------------------------
 # Benchmarks (actually a gTest where the result code does not matter)
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 9c9043e..66800b1 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -570,6 +570,14 @@
     EXPECT_EQ(1, signals);
 }
 
+// meant to be handed to ASSERT_FALSE / EXPECT_FALSE to expand the message
+static testing::AssertionResult IsFalse(int ret, const char* command) {
+    return ret ?
+        (testing::AssertionSuccess() <<
+            "ret=" << ret << " command=\"" << command << "\"") :
+        testing::AssertionFailure();
+}
+
 TEST(logcat, logrotate) {
     static const char form[] = "/data/local/tmp/logcat.logrotate.XXXXXX";
     char buf[sizeof(form)];
@@ -581,7 +589,7 @@
     snprintf(command, sizeof(command), comm, buf);
 
     int ret;
-    EXPECT_FALSE((ret = system(command)));
+    EXPECT_FALSE(IsFalse(ret = system(command), command));
     if (!ret) {
         snprintf(command, sizeof(command), "ls -s %s 2>/dev/null", buf);
 
@@ -611,7 +619,7 @@
         }
     }
     snprintf(command, sizeof(command), "rm -rf %s", buf);
-    EXPECT_FALSE(system(command));
+    EXPECT_FALSE(IsFalse(system(command), command));
 }
 
 TEST(logcat, logrotate_suffix) {
@@ -625,7 +633,7 @@
     snprintf(command, sizeof(command), logcat_cmd, tmp_out_dir);
 
     int ret;
-    EXPECT_FALSE((ret = system(command)));
+    EXPECT_FALSE(IsFalse(ret = system(command), command));
     if (!ret) {
         snprintf(command, sizeof(command), "ls %s 2>/dev/null", tmp_out_dir);
 
@@ -664,7 +672,7 @@
         EXPECT_EQ(11, log_file_count);
     }
     snprintf(command, sizeof(command), "rm -rf %s", tmp_out_dir);
-    EXPECT_FALSE(system(command));
+    EXPECT_FALSE(IsFalse(system(command), command));
 }
 
 TEST(logcat, logrotate_continue) {
@@ -679,10 +687,10 @@
     snprintf(command, sizeof(command), logcat_cmd, tmp_out_dir, log_filename);
 
     int ret;
-    EXPECT_FALSE((ret = system(command)));
+    EXPECT_FALSE(IsFalse(ret = system(command), command));
     if (ret) {
         snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
-        EXPECT_FALSE(system(command));
+        EXPECT_FALSE(IsFalse(system(command), command));
         return;
     }
     FILE *fp;
@@ -690,7 +698,7 @@
     EXPECT_TRUE(NULL != ((fp = fopen(command, "r"))));
     if (!fp) {
         snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
-        EXPECT_FALSE(system(command));
+        EXPECT_FALSE(IsFalse(system(command), command));
         return;
     }
     char *line = NULL;
@@ -714,23 +722,23 @@
     EXPECT_TRUE(NULL != second_last_line);
     if (!second_last_line) {
         snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
-        EXPECT_FALSE(system(command));
+        EXPECT_FALSE(IsFalse(system(command), command));
         return;
     }
     // re-run the command, it should only add a few lines more content if it
     // continues where it left off.
     snprintf(command, sizeof(command), logcat_cmd, tmp_out_dir, log_filename);
-    EXPECT_FALSE((ret = system(command)));
+    EXPECT_FALSE(IsFalse(ret = system(command), command));
     if (ret) {
         snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
-        EXPECT_FALSE(system(command));
+        EXPECT_FALSE(IsFalse(system(command), command));
         return;
     }
     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir), closedir);
     EXPECT_NE(nullptr, dir);
     if (!dir) {
         snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
-        EXPECT_FALSE(system(command));
+        EXPECT_FALSE(IsFalse(system(command), command));
         return;
     }
     struct dirent *entry;
@@ -769,7 +777,7 @@
     free(second_last_line);
 
     snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
-    EXPECT_FALSE(system(command));
+    EXPECT_FALSE(IsFalse(system(command), command));
 }
 
 TEST(logcat, logrotate_clear) {
@@ -790,17 +798,17 @@
                  logcat_cmd, tmp_out_dir, log_filename, num_val);
 
         int ret;
-        EXPECT_FALSE((ret = system(command)));
+        EXPECT_FALSE(IsFalse(ret = system(command), command));
         if (ret) {
             snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
-            EXPECT_FALSE(system(command));
+            EXPECT_FALSE(IsFalse(system(command), command));
             return;
         }
         std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir), closedir);
         EXPECT_NE(nullptr, dir);
         if (!dir) {
             snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
-            EXPECT_FALSE(system(command));
+            EXPECT_FALSE(IsFalse(system(command), command));
             return;
         }
         struct dirent *entry;
@@ -819,17 +827,18 @@
         strcat(command, clear_cmd);
 
         int ret;
-        EXPECT_FALSE((ret = system(command)));
+        EXPECT_FALSE(IsFalse(ret = system(command), command));
         if (ret) {
             snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
             EXPECT_FALSE(system(command));
+            EXPECT_FALSE(IsFalse(system(command), command));
             return;
         }
         std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir), closedir);
         EXPECT_NE(nullptr, dir);
         if (!dir) {
             snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
-            EXPECT_FALSE(system(command));
+            EXPECT_FALSE(IsFalse(system(command), command));
             return;
         }
         struct dirent *entry;
@@ -845,7 +854,7 @@
     }
 
     snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
-    EXPECT_FALSE(system(command));
+    EXPECT_FALSE(IsFalse(system(command), command));
 }
 
 static int logrotate_count_id(const char *logcat_cmd, const char *tmp_out_dir) {
@@ -856,7 +865,7 @@
     snprintf(command, sizeof(command), logcat_cmd, tmp_out_dir, log_filename);
 
     int ret;
-    EXPECT_FALSE((ret = system(command)));
+    EXPECT_FALSE(IsFalse(ret = system(command), command));
     if (ret) {
         return -1;
     }
@@ -914,7 +923,7 @@
     static const char cleanup_cmd[] = "rm -rf %s";
     char command[strlen(cleanup_cmd) + strlen(tmp_out_dir_form)];
     snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
-    EXPECT_FALSE(system(command));
+    EXPECT_FALSE(IsFalse(system(command), command));
 }
 
 TEST(logcat, logrotate_nodir) {
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 7f5fe4f..5554d53 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -25,114 +25,21 @@
 #include <unordered_map>
 
 #include <cutils/properties.h>
-#include <log/logger.h>
+#include <private/android_logger.h>
 
 #include "LogBuffer.h"
 #include "LogKlog.h"
 #include "LogReader.h"
 
 // Default
-#define LOG_BUFFER_SIZE (256 * 1024) // Tuned with ro.logd.size per-platform
 #define log_buffer_size(id) mMaxSize[id]
-#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
-#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
-
-static bool valid_size(unsigned long value) {
-    if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
-        return false;
-    }
-
-    long pages = sysconf(_SC_PHYS_PAGES);
-    if (pages < 1) {
-        return true;
-    }
-
-    long pagesize = sysconf(_SC_PAGESIZE);
-    if (pagesize <= 1) {
-        pagesize = PAGE_SIZE;
-    }
-
-    // maximum memory impact a somewhat arbitrary ~3%
-    pages = (pages + 31) / 32;
-    unsigned long maximum = pages * pagesize;
-
-    if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
-        return true;
-    }
-
-    return value <= maximum;
-}
-
-static unsigned long property_get_size(const char *key) {
-    char property[PROPERTY_VALUE_MAX];
-    property_get(key, property, "");
-
-    char *cp;
-    unsigned long value = strtoul(property, &cp, 10);
-
-    switch(*cp) {
-    case 'm':
-    case 'M':
-        value *= 1024;
-    /* FALLTHRU */
-    case 'k':
-    case 'K':
-        value *= 1024;
-    /* FALLTHRU */
-    case '\0':
-        break;
-
-    default:
-        value = 0;
-    }
-
-    if (!valid_size(value)) {
-        value = 0;
-    }
-
-    return value;
-}
 
 void LogBuffer::init() {
-    static const char global_tuneable[] = "persist.logd.size"; // Settings App
-    static const char global_default[] = "ro.logd.size";       // BoardConfig.mk
-
-    unsigned long default_size = property_get_size(global_tuneable);
-    if (!default_size) {
-        default_size = property_get_size(global_default);
-        if (!default_size) {
-            default_size = property_get_bool("ro.config.low_ram",
-                                             BOOL_DEFAULT_FALSE)
-                ? LOG_BUFFER_MIN_SIZE // 64K
-                : LOG_BUFFER_SIZE;    // 256K
-        }
-    }
-
     log_id_for_each(i) {
         mLastSet[i] = false;
         mLast[i] = mLogElements.begin();
 
-        char key[PROP_NAME_MAX];
-
-        snprintf(key, sizeof(key), "%s.%s",
-                 global_tuneable, android_log_id_to_name(i));
-        unsigned long property_size = property_get_size(key);
-
-        if (!property_size) {
-            snprintf(key, sizeof(key), "%s.%s",
-                     global_default, android_log_id_to_name(i));
-            property_size = property_get_size(key);
-        }
-
-        if (!property_size) {
-            property_size = default_size;
-        }
-
-        if (!property_size) {
-            property_size = LOG_BUFFER_SIZE;
-        }
-
-        if (setSize(i, property_size)) {
+        if (setSize(i, __android_logger_get_buffer_size(i))) {
             setSize(i, LOG_BUFFER_MIN_SIZE);
         }
     }
@@ -880,7 +787,7 @@
 // set the total space allocated to "id"
 int LogBuffer::setSize(log_id_t id, unsigned long size) {
     // Reasonable limits ...
-    if (!valid_size(size)) {
+    if (!__android_logger_valid_buffer_size(size)) {
         return -1;
     }
     pthread_mutex_lock(&mLogElementsLock);
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index c6ebd52..f69bc50 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -21,6 +21,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <list>
+
 #include <log/logger.h>
 
 #include "LogStatistics.h"
@@ -467,55 +469,86 @@
     short spaces = 1;
 
     log_id_for_each(id) {
-        if (!(logMask & (1 << id))) {
-            continue;
-        }
+        if (!(logMask & (1 << id))) continue;
         oldLength = output.length();
-        if (spaces < 0) {
-            spaces = 0;
-        }
+        if (spaces < 0) spaces = 0;
         output += android::base::StringPrintf("%*s%s", spaces, "",
                                               android_log_id_to_name(id));
         spaces += spaces_total + oldLength - output.length();
     }
+    if (spaces < 0) spaces = 0;
+    output += android::base::StringPrintf("%*sTotal", spaces, "");
 
-    spaces = 4;
-    output += "\nTotal";
+    static const char TotalStr[] = "\nTotal";
+    spaces = 10 - strlen(TotalStr);
+    output += TotalStr;
 
+    size_t totalSize = 0;
+    size_t totalEls = 0;
     log_id_for_each(id) {
-        if (!(logMask & (1 << id))) {
-            continue;
-        }
+        if (!(logMask & (1 << id))) continue;
         oldLength = output.length();
-        if (spaces < 0) {
-            spaces = 0;
-        }
-        output += android::base::StringPrintf("%*s%zu/%zu", spaces, "",
-                                              sizesTotal(id),
-                                              elementsTotal(id));
+        if (spaces < 0) spaces = 0;
+        size_t szs = sizesTotal(id);
+        totalSize += szs;
+        size_t els = elementsTotal(id);
+        totalEls += els;
+        output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
         spaces += spaces_total + oldLength - output.length();
     }
+    if (spaces < 0) spaces = 0;
+    output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize, totalEls);
 
-    spaces = 6;
-    output += "\nNow";
+    static const char NowStr[] = "\nNow";
+    spaces = 10 - strlen(NowStr);
+    output += NowStr;
 
+    totalSize = 0;
+    totalEls = 0;
     log_id_for_each(id) {
-        if (!(logMask & (1 << id))) {
-            continue;
-        }
+        if (!(logMask & (1 << id))) continue;
 
         size_t els = elements(id);
         if (els) {
             oldLength = output.length();
-            if (spaces < 0) {
-                spaces = 0;
-            }
-            output += android::base::StringPrintf("%*s%zu/%zu", spaces, "",
-                                                  sizes(id), els);
+            if (spaces < 0) spaces = 0;
+            size_t szs = sizes(id);
+            totalSize += szs;
+            totalEls += els;
+            output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
             spaces -= output.length() - oldLength;
         }
         spaces += spaces_total;
     }
+    if (spaces < 0) spaces = 0;
+    output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize, totalEls);
+
+    static const char OverheadStr[] = "\nOverhead";
+    spaces = 10 - strlen(OverheadStr);
+    output += OverheadStr;
+
+    totalSize = 0;
+    log_id_for_each(id) {
+        if (!(logMask & (1 << id))) continue;
+
+        size_t els = elements(id);
+        if (els) {
+            oldLength = output.length();
+            if (spaces < 0) spaces = 0;
+            // estimate the std::list overhead.
+            static const size_t overhead =
+                ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
+                    -sizeof(uint64_t)) +
+                sizeof(std::list<LogBufferElement*>);
+            size_t szs = sizes(id) + els * overhead;
+            totalSize += szs;
+            output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
+            spaces -= output.length() - oldLength;
+        }
+        spaces += spaces_total;
+    }
+    if (spaces < 0) spaces = 0;
+    output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
 
     // Report on Chattiest
 
@@ -523,9 +556,7 @@
 
     // Chattiest by application (UID)
     log_id_for_each(id) {
-        if (!(logMask & (1 << id))) {
-            continue;
-        }
+        if (!(logMask & (1 << id))) continue;
 
         name = (uid == AID_ROOT)
             ? "Chattiest UIDs in %s log buffer:"
@@ -539,27 +570,21 @@
             : "Logging for this PID:";
         output += pidTable.format(*this, uid, pid, name);
         name = "Chattiest TIDs";
-        if (pid) {
-            name += android::base::StringPrintf(" for PID %d", pid);
-        }
+        if (pid) name += android::base::StringPrintf(" for PID %d", pid);
         name += ":";
         output += tidTable.format(*this, uid, pid, name);
     }
 
     if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
         name = "Chattiest events log buffer TAGs";
-        if (pid) {
-            name += android::base::StringPrintf(" for PID %d", pid);
-        }
+        if (pid) name += android::base::StringPrintf(" for PID %d", pid);
         name += ":";
         output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
     }
 
     if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
         name = "Chattiest security log buffer TAGs";
-        if (pid) {
-            name += android::base::StringPrintf(" for PID %d", pid);
-        }
+        if (pid) name += android::base::StringPrintf(" for PID %d", pid);
         name += ":";
         output += securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
     }
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
index 6db4c51..881f097 100644
--- a/logd/LogUtils.h
+++ b/logd/LogUtils.h
@@ -45,16 +45,6 @@
 bool clientHasLogCredentials(uid_t uid, gid_t gid, pid_t pid);
 bool clientHasLogCredentials(SocketClient *cli);
 
-// Furnished in main.cpp
-#define BOOL_DEFAULT_FLAG_TRUE_FALSE 0x1
-#define BOOL_DEFAULT_FALSE       0x0     // false if property not present
-#define BOOL_DEFAULT_TRUE        0x1     // true if property not present
-#define BOOL_DEFAULT_FLAG_PERSIST    0x2 // <key>, persist.<key>, ro.<key>
-#define BOOL_DEFAULT_FLAG_ENG        0x4 // off for user
-#define BOOL_DEFAULT_FLAG_SVELTE     0x8 // off for low_ram
-
-bool property_get_bool(const char *key, int def);
-
 static inline bool worstUidEnabledForLogid(log_id_t id) {
     return (id == LOG_ID_MAIN) || (id == LOG_ID_SYSTEM) ||
             (id == LOG_ID_RADIO) || (id == LOG_ID_EVENTS);
diff --git a/logd/main.cpp b/logd/main.cpp
index a0cea25..0cb26dc 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>
 
@@ -130,60 +131,6 @@
     return !*cp || !!strchr(sep, *cp);
 }
 
-bool property_get_bool(const char *key, int flag) {
-    char def[PROPERTY_VALUE_MAX];
-    char property[PROPERTY_VALUE_MAX];
-    def[0] = '\0';
-    if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
-        char newkey[PROPERTY_KEY_MAX];
-        snprintf(newkey, sizeof(newkey), "ro.%s", key);
-        property_get(newkey, property, "");
-        // persist properties set by /data require inoculation with
-        // logd-reinit. They may be set in init.rc early and function, but
-        // otherwise are defunct unless reset. Do not rely on persist
-        // properties for startup-only keys unless you are willing to restart
-        // logd daemon (not advised).
-        snprintf(newkey, sizeof(newkey), "persist.%s", key);
-        property_get(newkey, def, property);
-    }
-
-    property_get(key, property, def);
-
-    if (check_flag(property, "true")) {
-        return true;
-    }
-    if (check_flag(property, "false")) {
-        return false;
-    }
-    if (check_flag(property, "eng")) {
-       flag |= BOOL_DEFAULT_FLAG_ENG;
-    }
-    // this is really a "not" flag
-    if (check_flag(property, "svelte")) {
-       flag |= BOOL_DEFAULT_FLAG_SVELTE;
-    }
-
-    // Sanity Check
-    if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
-        flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
-        flag |= BOOL_DEFAULT_TRUE;
-    }
-
-    if ((flag & BOOL_DEFAULT_FLAG_SVELTE)
-            && property_get_bool("ro.config.low_ram",
-                                 BOOL_DEFAULT_FALSE)) {
-        return false;
-    }
-    if (flag & BOOL_DEFAULT_FLAG_ENG) {
-        property_get("ro.debuggable", property, "");
-        if (strcmp(property, "1")) {
-            return false;
-        }
-    }
-
-    return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
-}
-
 static int fdDmesg = -1;
 void android::prdebug(const char *fmt, ...) {
     if (fdDmesg < 0) {
@@ -367,11 +314,11 @@
 // transitory per-client threads are created for each reader.
 int main(int argc, char *argv[]) {
     int fdPmesg = -1;
-    bool klogd = property_get_bool("logd.kernel",
-                                   BOOL_DEFAULT_TRUE |
-                                   BOOL_DEFAULT_FLAG_PERSIST |
-                                   BOOL_DEFAULT_FLAG_ENG |
-                                   BOOL_DEFAULT_FLAG_SVELTE);
+    bool klogd = __android_logger_property_get_bool("logd.kernel",
+                                                    BOOL_DEFAULT_TRUE |
+                                                    BOOL_DEFAULT_FLAG_PERSIST |
+                                                    BOOL_DEFAULT_FLAG_ENG |
+                                                    BOOL_DEFAULT_FLAG_SVELTE);
     if (klogd) {
         fdPmesg = open("/proc/kmsg", O_RDONLY | O_NDELAY);
     }
@@ -451,11 +398,11 @@
 
     signal(SIGHUP, reinit_signal_handler);
 
-    if (property_get_bool("logd.statistics",
-                          BOOL_DEFAULT_TRUE |
-                          BOOL_DEFAULT_FLAG_PERSIST |
-                          BOOL_DEFAULT_FLAG_ENG |
-                          BOOL_DEFAULT_FLAG_SVELTE)) {
+    if (__android_logger_property_get_bool("logd.statistics",
+                                           BOOL_DEFAULT_TRUE |
+                                           BOOL_DEFAULT_FLAG_PERSIST |
+                                           BOOL_DEFAULT_FLAG_ENG |
+                                           BOOL_DEFAULT_FLAG_SVELTE)) {
         logBuf->enableStatistics();
     }
 
@@ -489,17 +436,17 @@
     // initiated log messages. New log entries are added to LogBuffer
     // and LogReader is notified to send updates to connected clients.
 
-    bool auditd = property_get_bool("logd.auditd",
-                                    BOOL_DEFAULT_TRUE |
-                                    BOOL_DEFAULT_FLAG_PERSIST);
+    bool auditd = __android_logger_property_get_bool("logd.auditd",
+                                                     BOOL_DEFAULT_TRUE |
+                                                     BOOL_DEFAULT_FLAG_PERSIST);
     LogAudit *al = NULL;
     if (auditd) {
         al = new LogAudit(logBuf, reader,
-                          property_get_bool("logd.auditd.dmesg",
-                                            BOOL_DEFAULT_TRUE |
-                                            BOOL_DEFAULT_FLAG_PERSIST)
-                              ? fdDmesg
-                              : -1);
+                          __android_logger_property_get_bool(
+                              "logd.auditd.dmesg",
+                              BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_PERSIST)
+                                  ? fdDmesg
+                                  : -1);
     }
 
     LogKlog *kl = NULL;
diff --git a/logwrapper/Android.bp b/logwrapper/Android.bp
index 41f0726..7ee0464 100644
--- a/logwrapper/Android.bp
+++ b/logwrapper/Android.bp
@@ -14,7 +14,6 @@
     local_include_dirs: ["include"],
     cflags: [
         "-Werror",
-        "-std=gnu99",
     ],
 }
 
@@ -31,6 +30,5 @@
     ],
     cflags: [
         "-Werror",
-        "-std=gnu99",
     ],
 }
diff --git a/sdcard/fuse.cpp b/sdcard/fuse.cpp
index f549606..d4c51fd 100644
--- a/sdcard/fuse.cpp
+++ b/sdcard/fuse.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
 #define LOG_TAG "sdcard"
 
 #include "fuse.h"
@@ -223,7 +227,8 @@
 }
 
 static int touch(char* path, mode_t mode) {
-    int fd = open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, mode);
+    int fd = TEMP_FAILURE_RETRY(open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC,
+                                     mode));
     if (fd == -1) {
         if (errno == EEXIST) {
             return 0;
@@ -469,27 +474,34 @@
     hdr.len = sizeof(hdr);
     hdr.error = err;
     hdr.unique = unique;
-    write(fuse->fd, &hdr, sizeof(hdr));
+    ssize_t ret = TEMP_FAILURE_RETRY(write(fuse->fd, &hdr, sizeof(hdr)));
+    if (ret == -1) {
+        PLOG(ERROR) << "*** STATUS FAILED ***";
+    } else if (static_cast<size_t>(ret) != sizeof(hdr)) {
+        LOG(ERROR) << "*** STATUS FAILED: written " << ret << " expected "
+                   << sizeof(hdr) << " ***";
+    }
 }
 
 static void fuse_reply(struct fuse *fuse, __u64 unique, void *data, int len)
 {
     struct fuse_out_header hdr;
-    struct iovec vec[2];
-    int res;
-
     hdr.len = len + sizeof(hdr);
     hdr.error = 0;
     hdr.unique = unique;
 
+    struct iovec vec[2];
     vec[0].iov_base = &hdr;
     vec[0].iov_len = sizeof(hdr);
     vec[1].iov_base = data;
     vec[1].iov_len = len;
 
-    res = writev(fuse->fd, vec, 2);
-    if (res < 0) {
+    ssize_t ret = TEMP_FAILURE_RETRY(writev(fuse->fd, vec, 2));
+    if (ret == -1) {
         PLOG(ERROR) << "*** REPLY FAILED ***";
+    } else if (static_cast<size_t>(ret) != sizeof(hdr) + len) {
+        LOG(ERROR) << "*** REPLY FAILED: written " << ret << " expected "
+                   << sizeof(hdr) + len << " ***";
     }
 }
 
@@ -501,7 +513,7 @@
     struct fuse_entry_out out;
     struct stat s;
 
-    if (lstat(path, &s) < 0) {
+    if (lstat(path, &s) == -1) {
         return -errno;
     }
 
@@ -528,7 +540,7 @@
     struct fuse_attr_out out;
     struct stat s;
 
-    if (lstat(path, &s) < 0) {
+    if (lstat(path, &s) == -1) {
         return -errno;
     }
     memset(&out, 0, sizeof(out));
@@ -542,10 +554,7 @@
         const __u64 child, const char* name) {
     struct fuse_out_header hdr;
     struct fuse_notify_delete_out data;
-    struct iovec vec[3];
     size_t namelen = strlen(name);
-    int res;
-
     hdr.len = sizeof(hdr) + sizeof(data) + namelen + 1;
     hdr.error = FUSE_NOTIFY_DELETE;
     hdr.unique = 0;
@@ -555,6 +564,7 @@
     data.namelen = namelen;
     data.padding = 0;
 
+    struct iovec vec[3];
     vec[0].iov_base = &hdr;
     vec[0].iov_len = sizeof(hdr);
     vec[1].iov_base = &data;
@@ -562,10 +572,15 @@
     vec[2].iov_base = (void*) name;
     vec[2].iov_len = namelen + 1;
 
-    res = writev(fuse->fd, vec, 3);
+    ssize_t ret = TEMP_FAILURE_RETRY(writev(fuse->fd, vec, 3));
     /* Ignore ENOENT, since other views may not have seen the entry */
-    if (res < 0 && errno != ENOENT) {
-        PLOG(ERROR) << "*** NOTIFY FAILED ***";
+    if (ret == -1) {
+        if (errno != ENOENT) {
+            PLOG(ERROR) << "*** NOTIFY FAILED ***";
+        }
+    } else if (static_cast<size_t>(ret) != sizeof(hdr) + sizeof(data) + namelen + 1) {
+        LOG(ERROR) << "*** NOTIFY FAILED: written " << ret << " expected "
+                   << sizeof(hdr) + sizeof(data) + namelen + 1 << " ***";
     }
 }
 
@@ -665,7 +680,7 @@
     /* XXX: incomplete implementation on purpose.
      * chmod/chown should NEVER be implemented.*/
 
-    if ((req->valid & FATTR_SIZE) && truncate64(path, req->size) < 0) {
+    if ((req->valid & FATTR_SIZE) && TEMP_FAILURE_RETRY(truncate64(path, req->size)) == -1) {
         return -errno;
     }
 
@@ -727,7 +742,7 @@
         return -EACCES;
     }
     __u32 mode = (req->mode & (~0777)) | 0664;
-    if (mknod(child_path, mode, req->rdev) < 0) {
+    if (mknod(child_path, mode, req->rdev) == -1) {
         return -errno;
     }
     return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path);
@@ -757,7 +772,7 @@
         return -EACCES;
     }
     __u32 mode = (req->mode & (~0777)) | 0775;
-    if (mkdir(child_path, mode) < 0) {
+    if (mkdir(child_path, mode) == -1) {
         return -errno;
     }
 
@@ -804,7 +819,7 @@
     if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK)) {
         return -EACCES;
     }
-    if (unlink(child_path) < 0) {
+    if (unlink(child_path) == -1) {
         return -errno;
     }
     pthread_mutex_lock(&fuse->global->lock);
@@ -854,7 +869,7 @@
     if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK)) {
         return -EACCES;
     }
-    if (rmdir(child_path) < 0) {
+    if (rmdir(child_path) == -1) {
         return -errno;
     }
     pthread_mutex_lock(&fuse->global->lock);
@@ -942,7 +957,7 @@
 
     DLOG(INFO) << "[" << handler->token << "] RENAME " << old_child_path << "->" << new_child_path;
     res = rename(old_child_path, new_child_path);
-    if (res < 0) {
+    if (res == -1) {
         res = -errno;
         goto io_error;
     }
@@ -1004,8 +1019,8 @@
         return -ENOMEM;
     }
     DLOG(INFO) << "[" << handler->token << "] OPEN " << path;
-    h->fd = open(path, req->flags);
-    if (h->fd < 0) {
+    h->fd = TEMP_FAILURE_RETRY(open(path, req->flags));
+    if (h->fd == -1) {
         free(h);
         return -errno;
     }
@@ -1035,8 +1050,8 @@
     if (size > MAX_READ) {
         return -EINVAL;
     }
-    res = pread64(h->fd, read_buffer, size, offset);
-    if (res < 0) {
+    res = TEMP_FAILURE_RETRY(pread64(h->fd, read_buffer, size, offset));
+    if (res == -1) {
         return -errno;
     }
     fuse_reply(fuse, unique, read_buffer, res);
@@ -1059,8 +1074,8 @@
 
     DLOG(INFO) << "[" << handler->token << "] WRITE " << std::hex << h << std::dec
                << "(" << h->fd << ") " << req->size << "@" << req->offset;
-    res = pwrite64(h->fd, buffer, req->size, req->offset);
-    if (res < 0) {
+    res = TEMP_FAILURE_RETRY(pwrite64(h->fd, buffer, req->size, req->offset));
+    if (res == -1) {
         return -errno;
     }
     out.size = res;
@@ -1084,7 +1099,7 @@
     if (res < 0) {
         return -ENOENT;
     }
-    if (statfs(fuse->global->root.name, &stat) < 0) {
+    if (TEMP_FAILURE_RETRY(statfs(fuse->global->root.name, &stat)) == -1) {
         return -errno;
     }
     memset(&out, 0, sizeof(out));
@@ -1293,7 +1308,6 @@
     return NO_STATUS;
 }
 
-
 static int handle_fuse_request(struct fuse *fuse, struct fuse_handler* handler,
         const struct fuse_in_header *hdr, const void *data, size_t data_len)
 {
@@ -1427,7 +1441,7 @@
     for (;;) {
         ssize_t len = TEMP_FAILURE_RETRY(read(fuse->fd,
                 handler->request_buffer, sizeof(handler->request_buffer)));
-        if (len < 0) {
+        if (len == -1) {
             if (errno == ENODEV) {
                 LOG(ERROR) << "[" << handler->token << "] someone stole our marbles!";
                 exit(2);
@@ -1436,14 +1450,14 @@
             continue;
         }
 
-        if ((size_t)len < sizeof(struct fuse_in_header)) {
+        if (static_cast<size_t>(len) < sizeof(struct fuse_in_header)) {
             LOG(ERROR) << "[" << handler->token << "] request too short: len=" << len;
             continue;
         }
 
         const struct fuse_in_header* hdr =
             reinterpret_cast<const struct fuse_in_header*>(handler->request_buffer);
-        if (hdr->len != (size_t)len) {
+        if (hdr->len != static_cast<size_t>(len)) {
             LOG(ERROR) << "[" << handler->token << "] malformed header: len=" << len
                        << ", hdr->len=" << hdr->len;
             continue;
diff --git a/sdcard/sdcard.cpp b/sdcard/sdcard.cpp
index 70bbf26..bc502a0 100644
--- a/sdcard/sdcard.cpp
+++ b/sdcard/sdcard.cpp
@@ -111,7 +111,7 @@
     char event_buf[512];
 
     int nfd = inotify_init();
-    if (nfd < 0) {
+    if (nfd == -1) {
         PLOG(ERROR) << "inotify_init failed";
         return;
     }
@@ -142,17 +142,19 @@
         }
 
         int event_pos = 0;
-        int res = read(nfd, event_buf, sizeof(event_buf));
-        if (res < (int) sizeof(*event)) {
-            if (errno == EINTR)
-                continue;
+        ssize_t res = TEMP_FAILURE_RETRY(read(nfd, event_buf, sizeof(event_buf)));
+        if (res == -1) {
             PLOG(ERROR) << "failed to read inotify event";
             return;
+        } else if (static_cast<size_t>(res) < sizeof(*event)) {
+            LOG(ERROR) << "failed to read inotify event: read " << res << " expected "
+                       << sizeof(event_buf);
+            return;
         }
 
-        while (res >= (int) sizeof(*event)) {
+        while (res >= static_cast<ssize_t>(sizeof(*event))) {
             int event_size;
-            event = (struct inotify_event *) (event_buf + event_pos);
+            event = reinterpret_cast<struct inotify_event*>(event_buf + event_pos);
 
             DLOG(INFO) << "inotify event: " << std::hex << event->mask << std::dec;
             if ((event->mask & IN_IGNORED) == IN_IGNORED) {
@@ -171,7 +173,7 @@
 static int fuse_setup(struct fuse* fuse, gid_t gid, mode_t mask) {
     char opts[256];
 
-    fuse->fd = open("/dev/fuse", O_RDWR);
+    fuse->fd = TEMP_FAILURE_RETRY(open("/dev/fuse", O_RDWR | O_CLOEXEC));
     if (fuse->fd == -1) {
         PLOG(ERROR) << "failed to open fuse device";
         return -1;
@@ -182,8 +184,8 @@
     snprintf(opts, sizeof(opts),
             "fd=%i,rootmode=40000,default_permissions,allow_other,user_id=%d,group_id=%d",
             fuse->fd, fuse->global->uid, fuse->global->gid);
-    if (mount("/dev/fuse", fuse->dest_path, "fuse", MS_NOSUID | MS_NODEV | MS_NOEXEC |
-            MS_NOATIME, opts) != 0) {
+    if (mount("/dev/fuse", fuse->dest_path, "fuse", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME,
+              opts) == -1) {
         PLOG(ERROR) << "failed to mount fuse filesystem";
         return -1;
     }
@@ -321,7 +323,7 @@
             fsuid, fsgid, multi_user?"multiuser,":"", mask, userid, gid);
 
     if (mount(source_path.c_str(), dest_path.c_str(), "sdcardfs",
-                        MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) != 0) {
+              MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) == -1) {
         PLOG(ERROR) << "failed to mount sdcardfs filesystem";
         return false;
     }
@@ -480,7 +482,7 @@
 
     rlim.rlim_cur = 8192;
     rlim.rlim_max = 8192;
-    if (setrlimit(RLIMIT_NOFILE, &rlim)) {
+    if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
         PLOG(ERROR) << "setting RLIMIT_NOFILE failed";
     }
 
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 4852fa4..5319ff4 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -42,7 +42,6 @@
 
 LOCAL_CFLAGS += $(common_cflags)
 LOCAL_C_INCLUDES += $(LOCAL_PATH)/upstream-netbsd/include/
-LOCAL_CONLYFLAGS += -std=gnu99
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \