Merge "Fix memory order and race bugs in Refbase.h & RefBase.cpp"
diff --git a/adb/Android.mk b/adb/Android.mk
index 6693619..6188184 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -58,6 +58,7 @@
 
 LIBADB_TEST_SRCS := \
     adb_io_test.cpp \
+    adb_listeners_test.cpp \
     adb_utils_test.cpp \
     fdevent_test.cpp \
     socket_test.cpp \
@@ -207,24 +208,6 @@
 
 include $(BUILD_HOST_NATIVE_TEST)
 
-# adb device tracker (used by ddms) test tool
-# =========================================================
-
-ifeq ($(HOST_OS),linux)
-include $(CLEAR_VARS)
-LOCAL_MODULE := adb_device_tracker_test
-LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS)
-LOCAL_CFLAGS_windows := $(LIBADB_windows_CFLAGS)
-LOCAL_CFLAGS_linux := $(LIBADB_linux_CFLAGS)
-LOCAL_CFLAGS_darwin := $(LIBADB_darwin_CFLAGS)
-LOCAL_SRC_FILES := test_track_devices.cpp
-LOCAL_SANITIZE := $(adb_host_sanitize)
-LOCAL_SHARED_LIBRARIES := libbase
-LOCAL_STATIC_LIBRARIES := libadb libcrypto_utils_static libcrypto_static libcutils
-LOCAL_LDLIBS += -lrt -ldl -lpthread
-include $(BUILD_HOST_EXECUTABLE)
-endif
-
 # adb host tool
 # =========================================================
 include $(CLEAR_VARS)
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 49d2936..3f14f1a 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -65,21 +65,34 @@
 void fatal(const char *fmt, ...) {
     va_list ap;
     va_start(ap, fmt);
-    fprintf(stderr, "error: ");
-    vfprintf(stderr, fmt, ap);
-    fprintf(stderr, "\n");
+    char buf[1024];
+    vsnprintf(buf, sizeof(buf), fmt, ap);
+
+#if ADB_HOST
+    fprintf(stderr, "error: %s\n", buf);
+#else
+    LOG(ERROR) << "error: " << buf;
+#endif
+
     va_end(ap);
-    exit(-1);
+    abort();
 }
 
 void fatal_errno(const char* fmt, ...) {
+    int err = errno;
     va_list ap;
     va_start(ap, fmt);
-    fprintf(stderr, "error: %s: ", strerror(errno));
-    vfprintf(stderr, fmt, ap);
-    fprintf(stderr, "\n");
+    char buf[1024];
+    vsnprintf(buf, sizeof(buf), fmt, ap);
+
+#if ADB_HOST
+    fprintf(stderr, "error: %s: %s\n", buf, strerror(err));
+#else
+    LOG(ERROR) << "error: " << buf << ": " << strerror(err);
+#endif
+
     va_end(ap);
-    exit(-1);
+    abort();
 }
 
 apacket* get_apacket(void)
@@ -955,18 +968,25 @@
 
         std::string error;
         InstallStatus r;
+        int resolved_tcp_port = 0;
         if (kill_forward) {
             r = remove_listener(pieces[0].c_str(), transport);
         } else {
-            r = install_listener(pieces[0], pieces[1].c_str(), transport,
-                                 no_rebind, &error);
+            r = install_listener(pieces[0], pieces[1].c_str(), transport, no_rebind,
+                                 &resolved_tcp_port, &error);
         }
         if (r == INSTALL_STATUS_OK) {
 #if ADB_HOST
-            /* On the host: 1st OKAY is connect, 2nd OKAY is status */
+            // On the host: 1st OKAY is connect, 2nd OKAY is status.
             SendOkay(reply_fd);
 #endif
             SendOkay(reply_fd);
+
+            // If a TCP port was resolved, send the actual port number back.
+            if (resolved_tcp_port != 0) {
+                SendProtocolString(reply_fd, android::base::StringPrintf("%d", resolved_tcp_port));
+            }
+
             return 1;
         }
 
diff --git a/adb/adb.h b/adb/adb.h
index ea20800..cb38e61 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -50,7 +50,7 @@
 std::string adb_version();
 
 // Increment this when we want to force users to start a new adb server.
-#define ADB_SERVER_VERSION 36
+#define ADB_SERVER_VERSION 37
 
 class atransport;
 struct usb_handle;
@@ -116,29 +116,6 @@
     kCsUnauthorized,
 };
 
-/* A listener is an entity which binds to a local port
-** and, upon receiving a connection on that port, creates
-** an asocket to connect the new local connection to a
-** specific remote service.
-**
-** TODO: some listeners read from the new connection to
-** determine what exact service to connect to on the far
-** side.
-*/
-struct alistener
-{
-    alistener *next;
-    alistener *prev;
-
-    fdevent fde;
-    int fd;
-
-    char *local_name;
-    char *connect_to;
-    atransport *transport;
-    adisconnect  disconnect;
-};
-
 
 void print_packet(const char *label, apacket *p);
 
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index e8c2338..f54603c 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -20,18 +20,55 @@
 #include <stdlib.h>
 
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 #include <cutils/sockets.h>
 
 #include "sysdeps.h"
 #include "transport.h"
 
-int gListenAll = 0; /* Not static because it is used in commandline.c. */
+// Not static because it is used in commandline.c.
+int gListenAll = 0;
 
-static alistener listener_list = {
-    .next = &listener_list,
-    .prev = &listener_list,
+// A listener is an entity which binds to a local port and, upon receiving a connection on that
+// port, creates an asocket to connect the new local connection to a specific remote service.
+//
+// TODO: some listeners read from the new connection to determine what exact service to connect to
+// on the far side.
+class alistener {
+  public:
+    alistener(const std::string& _local_name, const std::string& _connect_to);
+    ~alistener();
+
+    fdevent fde;
+    int fd = -1;
+
+    std::string local_name;
+    std::string connect_to;
+    atransport* transport = nullptr;
+    adisconnect disconnect;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(alistener);
 };
 
+alistener::alistener(const std::string& _local_name, const std::string& _connect_to)
+    : local_name(_local_name), connect_to(_connect_to) {
+}
+
+alistener::~alistener() {
+    // Closes the corresponding fd.
+    fdevent_remove(&fde);
+
+    if (transport) {
+        transport->RemoveDisconnect(&disconnect);
+    }
+}
+
+// listener_list retains ownership of all created alistener objects. Removing an alistener from
+// this list will cause it to be deleted.
+typedef std::list<std::unique_ptr<alistener>> ListenerList;
+static ListenerList& listener_list = *new ListenerList();
+
 static void ss_listener_event_func(int _fd, unsigned ev, void *_l) {
     if (ev & FDE_READ) {
         sockaddr_storage ss;
@@ -73,7 +110,7 @@
         s = create_local_socket(fd);
         if (s) {
             s->transport = listener->transport;
-            connect_to_remote(s, listener->connect_to);
+            connect_to_remote(s, listener->connect_to.c_str());
             return;
         }
 
@@ -81,66 +118,63 @@
     }
 }
 
-static void free_listener(alistener*  l)
-{
-    if (l->next) {
-        l->next->prev = l->prev;
-        l->prev->next = l->next;
-        l->next = l->prev = l;
-    }
-
-    // closes the corresponding fd
-    fdevent_remove(&l->fde);
-
-    if (l->local_name)
-        free((char*)l->local_name);
-
-    if (l->connect_to)
-        free((char*)l->connect_to);
-
-    if (l->transport) {
-        l->transport->RemoveDisconnect(&l->disconnect);
-    }
-    free(l);
-}
-
+// Called as a transport disconnect function. |arg| is the raw alistener*.
 static void listener_disconnect(void* arg, atransport*) {
-    alistener* listener = reinterpret_cast<alistener*>(arg);
-    listener->transport = nullptr;
-    free_listener(listener);
-}
-
-static int local_name_to_fd(const char* name, std::string* error) {
-    if (!strncmp("tcp:", name, 4)) {
-        int port = atoi(name + 4);
-        if (gListenAll > 0) {
-            return network_inaddr_any_server(port, SOCK_STREAM, error);
-        } else {
-            return network_loopback_server(port, SOCK_STREAM, error);
+    for (auto iter = listener_list.begin(); iter != listener_list.end(); ++iter) {
+        if (iter->get() == arg) {
+            (*iter)->transport = nullptr;
+            listener_list.erase(iter);
+            return;
         }
     }
+}
+
+int local_name_to_fd(alistener* listener, int* resolved_tcp_port, std::string* error) {
+    if (android::base::StartsWith(listener->local_name, "tcp:")) {
+        int requested_port = atoi(&listener->local_name[4]);
+        int sock = -1;
+        if (gListenAll > 0) {
+            sock = network_inaddr_any_server(requested_port, SOCK_STREAM, error);
+        } else {
+            sock = network_loopback_server(requested_port, SOCK_STREAM, error);
+        }
+
+        // If the caller requested port 0, update the listener name with the resolved port.
+        if (sock >= 0 && requested_port == 0) {
+            int local_port = adb_socket_get_local_port(sock);
+            if (local_port > 0) {
+                listener->local_name = android::base::StringPrintf("tcp:%d", local_port);
+                if (resolved_tcp_port != nullptr) {
+                    *resolved_tcp_port = local_port;
+                }
+            }
+        }
+
+        return sock;
+    }
 #if !defined(_WIN32)  // No Unix-domain sockets on Windows.
-    // It's nonsensical to support the "reserved" space on the adb host side
-    if (!strncmp(name, "local:", 6)) {
-        return network_local_server(name + 6,
-                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM, error);
-    } else if (!strncmp(name, "localabstract:", 14)) {
-        return network_local_server(name + 14,
-                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM, error);
-    } else if (!strncmp(name, "localfilesystem:", 16)) {
-        return network_local_server(name + 16,
-                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM, error);
+    // It's nonsensical to support the "reserved" space on the adb host side.
+    if (android::base::StartsWith(listener->local_name, "local:")) {
+        return network_local_server(&listener->local_name[6], ANDROID_SOCKET_NAMESPACE_ABSTRACT,
+                                    SOCK_STREAM, error);
+    } else if (android::base::StartsWith(listener->local_name, "localabstract:")) {
+        return network_local_server(&listener->local_name[14], ANDROID_SOCKET_NAMESPACE_ABSTRACT,
+                                    SOCK_STREAM, error);
+    } else if (android::base::StartsWith(listener->local_name, "localfilesystem:")) {
+        return network_local_server(&listener->local_name[16], ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
+                                    SOCK_STREAM, error);
     }
 
 #endif
-    *error = android::base::StringPrintf("unknown local portname '%s'", name);
+    *error = android::base::StringPrintf("unknown local portname '%s'",
+                                         listener->local_name.c_str());
     return -1;
 }
 
 // Write the list of current listeners (network redirections) into a string.
 std::string format_listeners() {
     std::string result;
-    for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
+    for (auto& l : listener_list) {
         // Ignore special listeners like those for *smartsocket*
         if (l->connect_to[0] == '*') {
             continue;
@@ -149,65 +183,51 @@
         // Entries from "adb reverse" have no serial.
         android::base::StringAppendF(&result, "%s %s %s\n",
                                      l->transport->serial ? l->transport->serial : "(reverse)",
-                                     l->local_name, l->connect_to);
+                                     l->local_name.c_str(), l->connect_to.c_str());
     }
     return result;
 }
 
-InstallStatus remove_listener(const char *local_name, atransport* transport) {
-    alistener *l;
-
-    for (l = listener_list.next; l != &listener_list; l = l->next) {
-        if (!strcmp(local_name, l->local_name)) {
-            free_listener(l);
+InstallStatus remove_listener(const char* local_name, atransport* transport) {
+    for (auto iter = listener_list.begin(); iter != listener_list.end(); ++iter) {
+        if (local_name == (*iter)->local_name) {
+            listener_list.erase(iter);
             return INSTALL_STATUS_OK;
         }
     }
     return INSTALL_STATUS_LISTENER_NOT_FOUND;
 }
 
-void remove_all_listeners(void)
-{
-    alistener *l, *l_next;
-    for (l = listener_list.next; l != &listener_list; l = l_next) {
-        l_next = l->next;
+void remove_all_listeners() {
+    auto iter = listener_list.begin();
+    while (iter != listener_list.end()) {
         // Never remove smart sockets.
-        if (l->connect_to[0] == '*')
-            continue;
-        free_listener(l);
+        if ((*iter)->connect_to[0] == '*') {
+            ++iter;
+        } else {
+            iter = listener_list.erase(iter);
+        }
     }
 }
 
-InstallStatus install_listener(const std::string& local_name,
-                                  const char *connect_to,
-                                  atransport* transport,
-                                  int no_rebind,
-                                  std::string* error)
-{
-    for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
+InstallStatus install_listener(const std::string& local_name, const char* connect_to,
+                               atransport* transport, int no_rebind, int* resolved_tcp_port,
+                               std::string* error) {
+    for (auto& l : listener_list) {
         if (local_name == l->local_name) {
-            char* cto;
-
-            /* can't repurpose a smartsocket */
+            // Can't repurpose a smartsocket.
             if(l->connect_to[0] == '*') {
                 *error = "cannot repurpose smartsocket";
                 return INSTALL_STATUS_INTERNAL_ERROR;
             }
 
-            /* can't repurpose a listener if 'no_rebind' is true */
+            // Can't repurpose a listener if 'no_rebind' is true.
             if (no_rebind) {
                 *error = "cannot rebind";
                 return INSTALL_STATUS_CANNOT_REBIND;
             }
 
-            cto = strdup(connect_to);
-            if(cto == 0) {
-                *error = "cannot duplicate string";
-                return INSTALL_STATUS_INTERNAL_ERROR;
-            }
-
-            free((void*) l->connect_to);
-            l->connect_to = cto;
+            l->connect_to = connect_to;
             if (l->transport != transport) {
                 l->transport->RemoveDisconnect(&l->disconnect);
                 l->transport = transport;
@@ -217,54 +237,29 @@
         }
     }
 
-    alistener* listener = reinterpret_cast<alistener*>(
-        calloc(1, sizeof(alistener)));
-    if (listener == nullptr) {
-        goto nomem;
-    }
+    std::unique_ptr<alistener> listener(new alistener(local_name, connect_to));
 
-    listener->local_name = strdup(local_name.c_str());
-    if (listener->local_name == nullptr) {
-        goto nomem;
-    }
-
-    listener->connect_to = strdup(connect_to);
-    if (listener->connect_to == nullptr) {
-        goto nomem;
-    }
-
-    listener->fd = local_name_to_fd(listener->local_name, error);
+    listener->fd = local_name_to_fd(listener.get(), resolved_tcp_port, error);
     if (listener->fd < 0) {
-        free(listener->local_name);
-        free(listener->connect_to);
-        free(listener);
         return INSTALL_STATUS_CANNOT_BIND;
     }
 
     close_on_exec(listener->fd);
-    if (!strcmp(listener->connect_to, "*smartsocket*")) {
-        fdevent_install(&listener->fde, listener->fd, ss_listener_event_func,
-                        listener);
+    if (listener->connect_to == "*smartsocket*") {
+        fdevent_install(&listener->fde, listener->fd, ss_listener_event_func, listener.get());
     } else {
-        fdevent_install(&listener->fde, listener->fd, listener_event_func,
-                        listener);
+        fdevent_install(&listener->fde, listener->fd, listener_event_func, listener.get());
     }
     fdevent_set(&listener->fde, FDE_READ);
 
-    listener->next = &listener_list;
-    listener->prev = listener_list.prev;
-    listener->next->prev = listener;
-    listener->prev->next = listener;
     listener->transport = transport;
 
     if (transport) {
-        listener->disconnect.opaque = listener;
+        listener->disconnect.opaque = listener.get();
         listener->disconnect.func   = listener_disconnect;
         transport->AddDisconnect(&listener->disconnect);
     }
-    return INSTALL_STATUS_OK;
 
-nomem:
-    fatal("cannot allocate listener");
-    return INSTALL_STATUS_INTERNAL_ERROR;
+    listener_list.push_back(std::move(listener));
+    return INSTALL_STATUS_OK;
 }
diff --git a/adb/adb_listeners.h b/adb/adb_listeners.h
index fa98eed..8eba00a 100644
--- a/adb/adb_listeners.h
+++ b/adb/adb_listeners.h
@@ -21,6 +21,8 @@
 
 #include <string>
 
+#include <android-base/macros.h>
+
 // error/status codes for install_listener.
 enum InstallStatus {
   INSTALL_STATUS_OK = 0,
@@ -30,10 +32,8 @@
   INSTALL_STATUS_LISTENER_NOT_FOUND = -4,
 };
 
-InstallStatus install_listener(const std::string& local_name,
-                               const char* connect_to,
-                               atransport* transport,
-                               int no_rebind,
+InstallStatus install_listener(const std::string& local_name, const char* connect_to,
+                               atransport* transport, int no_rebind, int* resolved_tcp_port,
                                std::string* error);
 
 std::string format_listeners();
diff --git a/adb/adb_listeners_test.cpp b/adb/adb_listeners_test.cpp
new file mode 100644
index 0000000..b697769
--- /dev/null
+++ b/adb/adb_listeners_test.cpp
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+
+#include "adb_listeners.h"
+
+#include <gtest/gtest.h>
+
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+
+#include "fdevent.h"
+#include "sysdeps.h"
+#include "transport.h"
+
+// Returns true if the given listener is present in format_listeners(). Empty parameters will
+// be ignored.
+static bool listener_is_installed(const std::string& serial, const std::string& source,
+                                  const std::string& dest) {
+    // format_listeners() gives lines of "<serial> <source> <dest>\n".
+    for (const std::string& line : android::base::Split(format_listeners(), "\n")) {
+        std::vector<std::string> info = android::base::Split(line, " ");
+        if (info.size() == 3 &&
+                (serial.empty() || info[0] == serial) &&
+                (source.empty() || info[1] == source) &&
+                (dest.empty() || info[2] == dest)) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+class AdbListenersTest : public ::testing::Test {
+  public:
+    void SetUp() override {
+        // We don't need an fdevent loop, but adding/removing listeners must be done from the
+        // fdevent thread if one exists. Since previously run tests may have created an fdevent
+        // thread, we need to reset to prevent the thread check.
+        fdevent_reset();
+    }
+
+    void TearDown() override {
+        // Clean up any listeners that may have been installed.
+        remove_all_listeners();
+
+        // Make sure we didn't leave any dangling events.
+        ASSERT_EQ(0u, fdevent_installed_count());
+    }
+
+  protected:
+    atransport transport_;
+};
+
+TEST_F(AdbListenersTest, test_install_listener) {
+    std::string error;
+
+    ASSERT_EQ(INSTALL_STATUS_OK,
+              install_listener("tcp:9000", "tcp:9000", &transport_, false, nullptr, &error));
+    ASSERT_TRUE(error.empty());
+
+    ASSERT_TRUE(listener_is_installed("", "tcp:9000", "tcp:9000"));
+}
+
+TEST_F(AdbListenersTest, test_install_listener_rebind) {
+    std::string error;
+
+    ASSERT_EQ(INSTALL_STATUS_OK,
+              install_listener("tcp:9000", "tcp:9000", &transport_, false, nullptr, &error));
+    ASSERT_TRUE(error.empty());
+
+    ASSERT_EQ(INSTALL_STATUS_OK,
+              install_listener("tcp:9000", "tcp:9001", &transport_, false, nullptr, &error));
+    ASSERT_TRUE(error.empty());
+
+    ASSERT_TRUE(listener_is_installed("", "tcp:9000", "tcp:9001"));
+}
+
+TEST_F(AdbListenersTest, test_install_listener_no_rebind) {
+    std::string error;
+
+    ASSERT_EQ(INSTALL_STATUS_OK,
+              install_listener("tcp:9000", "tcp:9000", &transport_, true, nullptr, &error));
+    ASSERT_TRUE(error.empty());
+
+    ASSERT_EQ(INSTALL_STATUS_CANNOT_REBIND,
+              install_listener("tcp:9000", "tcp:9001", &transport_, true, nullptr, &error));
+    ASSERT_FALSE(error.empty());
+
+    ASSERT_TRUE(listener_is_installed("", "tcp:9000", "tcp:9000"));
+}
+
+TEST_F(AdbListenersTest, test_install_listener_tcp_port_0) {
+    int port = 0;
+    std::string error;
+
+    ASSERT_EQ(INSTALL_STATUS_OK,
+              install_listener("tcp:0", "tcp:9000", &transport_, true, &port, &error));
+    ASSERT_TRUE(error.empty());
+
+    ASSERT_TRUE(listener_is_installed("", android::base::StringPrintf("tcp:%d", port), "tcp:9000"));
+}
+
+TEST_F(AdbListenersTest, test_remove_listener) {
+    std::string error;
+
+    ASSERT_EQ(INSTALL_STATUS_OK,
+              install_listener("tcp:9000", "tcp:9000", &transport_, false, nullptr, &error));
+    ASSERT_TRUE(error.empty());
+
+    ASSERT_EQ(INSTALL_STATUS_OK, remove_listener("tcp:9000", &transport_));
+    ASSERT_TRUE(format_listeners().empty());
+}
+
+TEST_F(AdbListenersTest, test_remove_nonexistent_listener) {
+    std::string error;
+
+    ASSERT_EQ(INSTALL_STATUS_OK,
+              install_listener("tcp:9000", "tcp:9000", &transport_, false, nullptr, &error));
+    ASSERT_TRUE(error.empty());
+
+    ASSERT_EQ(INSTALL_STATUS_LISTENER_NOT_FOUND, remove_listener("tcp:1", &transport_));
+    ASSERT_TRUE(listener_is_installed("", "tcp:9000", "tcp:9000"));
+}
+
+TEST_F(AdbListenersTest, test_remove_all_listeners) {
+    std::string error;
+
+    ASSERT_EQ(INSTALL_STATUS_OK,
+              install_listener("tcp:9000", "tcp:9000", &transport_, false, nullptr, &error));
+    ASSERT_TRUE(error.empty());
+
+    ASSERT_EQ(INSTALL_STATUS_OK,
+              install_listener("tcp:9001", "tcp:9001", &transport_, false, nullptr, &error));
+    ASSERT_TRUE(error.empty());
+
+    remove_all_listeners();
+    ASSERT_TRUE(format_listeners().empty());
+}
+
+TEST_F(AdbListenersTest, test_transport_disconnect) {
+    std::string error;
+
+    ASSERT_EQ(INSTALL_STATUS_OK,
+              install_listener("tcp:9000", "tcp:9000", &transport_, false, nullptr, &error));
+    ASSERT_TRUE(error.empty());
+
+    ASSERT_EQ(INSTALL_STATUS_OK,
+              install_listener("tcp:9001", "tcp:9001", &transport_, false, nullptr, &error));
+    ASSERT_TRUE(error.empty());
+
+    transport_.RunDisconnects();
+    ASSERT_TRUE(format_listeners().empty());
+}
diff --git a/adb/adb_trace.h b/adb/adb_trace.h
index d50f947..5206a99 100644
--- a/adb/adb_trace.h
+++ b/adb/adb_trace.h
@@ -41,7 +41,7 @@
 };
 
 #define VLOG_IS_ON(TAG) \
-    ((adb_trace_mask & (1 << TAG)) != 0)
+    ((adb_trace_mask & (1 << (TAG))) != 0)
 
 #define VLOG(TAG)         \
     if (LIKELY(!VLOG_IS_ON(TAG))) \
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 3333fc6..5d4755f 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -27,6 +27,7 @@
 #include <algorithm>
 
 #include <android-base/logging.h>
+#include <android-base/parseint.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 
@@ -230,3 +231,26 @@
     return true;
 }
 #endif
+
+bool forward_targets_are_valid(const std::string& source, const std::string& dest,
+                               std::string* error) {
+    if (android::base::StartsWith(source, "tcp:")) {
+        // The source port may be 0 to allow the system to select an open port.
+        int port;
+        if (!android::base::ParseInt(&source[4], &port) || port < 0) {
+            *error = android::base::StringPrintf("Invalid source port: '%s'", &source[4]);
+            return false;
+        }
+    }
+
+    if (android::base::StartsWith(dest, "tcp:")) {
+        // The destination port must be > 0.
+        int port;
+        if (!android::base::ParseInt(&dest[4], &port) || port <= 0) {
+            *error = android::base::StringPrintf("Invalid destination port: '%s'", &dest[4]);
+            return false;
+        }
+    }
+
+    return true;
+}
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index 89fcd66..22eb4d2 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -20,6 +20,7 @@
 #include <string>
 
 #include <android-base/macros.h>
+#include <android-base/unique_fd.h>
 
 void close_stdin();
 
@@ -43,7 +44,22 @@
 
 extern int adb_close(int fd);
 
+// Given forward/reverse targets, returns true if they look sane. If an error is found, fills
+// |error| and returns false.
+// Currently this only checks "tcp:" targets. Additional checking could be added for other targets
+// if needed.
+bool forward_targets_are_valid(const std::string& source, const std::string& dest,
+                               std::string* error);
+
 // Helper to automatically close an FD when it goes out of scope.
+struct AdbCloser {
+    static void Close(int fd) {
+        adb_close(fd);
+    }
+};
+
+using unique_fd = android::base::unique_fd_impl<AdbCloser>;
+
 class ScopedFd {
   public:
     ScopedFd() {
diff --git a/adb/adb_utils_test.cpp b/adb/adb_utils_test.cpp
index f1ebaa1..aabc5d7 100644
--- a/adb/adb_utils_test.cpp
+++ b/adb/adb_utils_test.cpp
@@ -149,3 +149,24 @@
   ASSERT_EQ(0, adb_close(fd));
 }
 #endif
+
+TEST(adb_utils, test_forward_targets_are_valid) {
+    std::string error;
+
+    // Source port can be >= 0.
+    EXPECT_FALSE(forward_targets_are_valid("tcp:-1", "tcp:9000", &error));
+    EXPECT_TRUE(forward_targets_are_valid("tcp:0", "tcp:9000", &error));
+    EXPECT_TRUE(forward_targets_are_valid("tcp:8000", "tcp:9000", &error));
+
+    // Destination port must be >0.
+    EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:-1", &error));
+    EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:0", &error));
+
+    // Port must be a number.
+    EXPECT_FALSE(forward_targets_are_valid("tcp:", "tcp:9000", &error));
+    EXPECT_FALSE(forward_targets_are_valid("tcp:a", "tcp:9000", &error));
+    EXPECT_FALSE(forward_targets_are_valid("tcp:22x", "tcp:9000", &error));
+    EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:", &error));
+    EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:a", &error));
+    EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:22x", &error));
+}
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 27b7109..65640ad 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -117,7 +117,7 @@
 
     std::string error;
     std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
-    if (install_listener(local_name, "*smartsocket*", nullptr, 0, &error)) {
+    if (install_listener(local_name, "*smartsocket*", nullptr, 0, nullptr, &error)) {
         fatal("could not install *smartsocket* listener: %s", error.c_str());
     }
 
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 45c6142..868470c 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -126,7 +126,7 @@
         "                                    <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
         "  adb forward <local> <remote> - forward socket connections\n"
         "                                 forward specs are one of: \n"
-        "                                   tcp:<port>\n"
+        "                                   tcp:<port> (<local> may be \"tcp:0\" to pick any open port)\n"
         "                                   localabstract:<unix domain socket name>\n"
         "                                   localreserved:<unix domain socket name>\n"
         "                                   localfilesystem:<unix domain socket name>\n"
@@ -140,7 +140,7 @@
         "  adb reverse --list           - list all reverse socket connections from device\n"
         "  adb reverse <remote> <local> - reverse socket connections\n"
         "                                 reverse specs are one of:\n"
-        "                                   tcp:<port>\n"
+        "                                   tcp:<port> (<remote> may be \"tcp:0\" to pick any open port)\n"
         "                                   localabstract:<unix domain socket name>\n"
         "                                   localreserved:<unix domain socket name>\n"
         "                                   localfilesystem:<unix domain socket name>\n"
@@ -1719,7 +1719,7 @@
             }
         }
 
-        std::string cmd;
+        std::string cmd, error;
         if (strcmp(argv[0], "--list") == 0) {
             if (argc != 1) return usage();
             return adb_query_command(host_prefix + ":list-forward");
@@ -1733,14 +1733,37 @@
         } else if (strcmp(argv[0], "--no-rebind") == 0) {
             // forward --no-rebind <local> <remote>
             if (argc != 3) return usage();
-            cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
+            if (forward_targets_are_valid(argv[1], argv[2], &error)) {
+                cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
+            }
         } else {
             // forward <local> <remote>
             if (argc != 2) return usage();
-            cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
+            if (forward_targets_are_valid(argv[0], argv[1], &error)) {
+                cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
+            }
         }
 
-        return adb_command(cmd) ? 0 : 1;
+        if (!error.empty()) {
+            fprintf(stderr, "error: %s\n", error.c_str());
+            return 1;
+        }
+
+        int fd = adb_connect(cmd, &error);
+        if (fd < 0 || !adb_status(fd, &error)) {
+            adb_close(fd);
+            fprintf(stderr, "error: %s\n", error.c_str());
+            return 1;
+        }
+
+        // Server or device may optionally return a resolved TCP port number.
+        std::string resolved_port;
+        if (ReadProtocolString(fd, &resolved_port, &error) && !resolved_port.empty()) {
+            printf("%s\n", resolved_port.c_str());
+        }
+
+        ReadOrderlyShutdown(fd);
+        return 0;
     }
     /* do_sync_*() commands */
     else if (!strcmp(argv[0], "ls")) {
@@ -1879,6 +1902,14 @@
     else if (!strcmp(argv[0], "jdwp")) {
         return adb_connect_command("jdwp");
     }
+    else if (!strcmp(argv[0], "track-jdwp")) {
+        return adb_connect_command("track-jdwp");
+    }
+    else if (!strcmp(argv[0], "track-devices")) {
+        return adb_connect_command("host:track-devices");
+    }
+
+
     /* "adb /?" is a common idiom under Windows */
     else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
         help();
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 7f40b96..916bedf 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -142,10 +142,8 @@
         std::string error;
         std::string local_name =
             android::base::StringPrintf("tcp:%d", server_port);
-        if (install_listener(local_name, "*smartsocket*", nullptr, 0,
-                             &error)) {
-            LOG(FATAL) << "Could not install *smartsocket* listener: "
-                       << error;
+        if (install_listener(local_name, "*smartsocket*", nullptr, 0, nullptr, &error)) {
+            LOG(FATAL) << "Could not install *smartsocket* listener: " << error;
         }
     }
 }
diff --git a/adb/mutex_list.h b/adb/mutex_list.h
index b59c9f2..4a188ee 100644
--- a/adb/mutex_list.h
+++ b/adb/mutex_list.h
@@ -8,7 +8,6 @@
 #endif
 ADB_MUTEX(basename_lock)
 ADB_MUTEX(dirname_lock)
-ADB_MUTEX(socket_list_lock)
 ADB_MUTEX(transport_lock)
 #if ADB_HOST
 ADB_MUTEX(local_transports_lock)
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index 3eeed34..374b468 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -412,7 +412,7 @@
         for (const char* message : messages) {
             WriteFdExactly(error_sfd->fd(), message);
         }
-        exit(-1);
+        abort();
     }
 
     if (make_pty_raw_) {
@@ -421,7 +421,7 @@
             int saved_errno = errno;
             WriteFdExactly(error_sfd->fd(), "tcgetattr failed: ");
             WriteFdExactly(error_sfd->fd(), strerror(saved_errno));
-            exit(-1);
+            abort();
         }
 
         cfmakeraw(&tattr);
@@ -429,7 +429,7 @@
             int saved_errno = errno;
             WriteFdExactly(error_sfd->fd(), "tcsetattr failed: ");
             WriteFdExactly(error_sfd->fd(), strerror(saved_errno));
-            exit(-1);
+            abort();
         }
     }
 
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index aecaba2..b2555d0 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -26,6 +26,7 @@
 #include <unistd.h>
 
 #include <algorithm>
+#include <mutex>
 #include <string>
 #include <vector>
 
@@ -35,17 +36,14 @@
 
 #include "adb.h"
 #include "adb_io.h"
+#include "sysdeps/mutex.h"
 #include "transport.h"
 
-ADB_MUTEX_DEFINE( socket_list_lock );
-
-static void local_socket_close_locked(asocket *s);
-
+static std::recursive_mutex& local_socket_list_lock = *new std::recursive_mutex();
 static unsigned local_socket_next_id = 1;
 
 static asocket local_socket_list = {
-    .next = &local_socket_list,
-    .prev = &local_socket_list,
+    .next = &local_socket_list, .prev = &local_socket_list,
 };
 
 /* the the list of currently closing local sockets.
@@ -53,62 +51,53 @@
 ** write to their fd.
 */
 static asocket local_socket_closing_list = {
-    .next = &local_socket_closing_list,
-    .prev = &local_socket_closing_list,
+    .next = &local_socket_closing_list, .prev = &local_socket_closing_list,
 };
 
 // Parse the global list of sockets to find one with id |local_id|.
 // If |peer_id| is not 0, also check that it is connected to a peer
 // with id |peer_id|. Returns an asocket handle on success, NULL on failure.
-asocket *find_local_socket(unsigned local_id, unsigned peer_id)
-{
-    asocket *s;
-    asocket *result = NULL;
+asocket* find_local_socket(unsigned local_id, unsigned peer_id) {
+    asocket* s;
+    asocket* result = NULL;
 
-    adb_mutex_lock(&socket_list_lock);
+    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
     for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
-        if (s->id != local_id)
+        if (s->id != local_id) {
             continue;
+        }
         if (peer_id == 0 || (s->peer && s->peer->id == peer_id)) {
             result = s;
         }
         break;
     }
-    adb_mutex_unlock(&socket_list_lock);
 
     return result;
 }
 
-static void
-insert_local_socket(asocket*  s, asocket*  list)
-{
-    s->next       = list;
-    s->prev       = s->next->prev;
+static void insert_local_socket(asocket* s, asocket* list) {
+    s->next = list;
+    s->prev = s->next->prev;
     s->prev->next = s;
     s->next->prev = s;
 }
 
-
-void install_local_socket(asocket *s)
-{
-    adb_mutex_lock(&socket_list_lock);
+void install_local_socket(asocket* s) {
+    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
 
     s->id = local_socket_next_id++;
 
     // Socket ids should never be 0.
-    if (local_socket_next_id == 0)
-      local_socket_next_id = 1;
+    if (local_socket_next_id == 0) {
+        fatal("local socket id overflow");
+    }
 
     insert_local_socket(s, &local_socket_list);
-
-    adb_mutex_unlock(&socket_list_lock);
 }
 
-void remove_socket(asocket *s)
-{
+void remove_socket(asocket* s) {
     // socket_list_lock should already be held
-    if (s->prev && s->next)
-    {
+    if (s->prev && s->next) {
         s->prev->next = s->next;
         s->next->prev = s->prev;
         s->next = 0;
@@ -117,50 +106,47 @@
     }
 }
 
-void close_all_sockets(atransport *t)
-{
-    asocket *s;
+void close_all_sockets(atransport* t) {
+    asocket* s;
 
-        /* this is a little gross, but since s->close() *will* modify
-        ** the list out from under you, your options are limited.
-        */
-    adb_mutex_lock(&socket_list_lock);
+    /* this is a little gross, but since s->close() *will* modify
+    ** the list out from under you, your options are limited.
+    */
+    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
 restart:
-    for(s = local_socket_list.next; s != &local_socket_list; s = s->next){
-        if(s->transport == t || (s->peer && s->peer->transport == t)) {
-            local_socket_close_locked(s);
+    for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
+        if (s->transport == t || (s->peer && s->peer->transport == t)) {
+            s->close(s);
             goto restart;
         }
     }
-    adb_mutex_unlock(&socket_list_lock);
 }
 
-static int local_socket_enqueue(asocket *s, apacket *p)
-{
+static int local_socket_enqueue(asocket* s, apacket* p) {
     D("LS(%d): enqueue %d", s->id, p->len);
 
     p->ptr = p->data;
 
-        /* if there is already data queue'd, we will receive
-        ** events when it's time to write.  just add this to
-        ** the tail
-        */
-    if(s->pkt_first) {
+    /* if there is already data queue'd, we will receive
+    ** events when it's time to write.  just add this to
+    ** the tail
+    */
+    if (s->pkt_first) {
         goto enqueue;
     }
 
-        /* write as much as we can, until we
-        ** would block or there is an error/eof
-        */
-    while(p->len > 0) {
+    /* write as much as we can, until we
+    ** would block or there is an error/eof
+    */
+    while (p->len > 0) {
         int r = adb_write(s->fd, p->ptr, p->len);
-        if(r > 0) {
+        if (r > 0) {
             p->len -= r;
             p->ptr += r;
             continue;
         }
-        if((r == 0) || (errno != EAGAIN)) {
-            D( "LS(%d): not ready, errno=%d: %s", s->id, errno, strerror(errno) );
+        if ((r == 0) || (errno != EAGAIN)) {
+            D("LS(%d): not ready, errno=%d: %s", s->id, errno, strerror(errno));
             put_apacket(p);
             s->has_write_error = true;
             s->close(s);
@@ -170,55 +156,46 @@
         }
     }
 
-    if(p->len == 0) {
+    if (p->len == 0) {
         put_apacket(p);
         return 0; /* ready for more data */
     }
 
 enqueue:
     p->next = 0;
-    if(s->pkt_first) {
+    if (s->pkt_first) {
         s->pkt_last->next = p;
     } else {
         s->pkt_first = p;
     }
     s->pkt_last = p;
 
-        /* make sure we are notified when we can drain the queue */
+    /* make sure we are notified when we can drain the queue */
     fdevent_add(&s->fde, FDE_WRITE);
 
     return 1; /* not ready (backlog) */
 }
 
-static void local_socket_ready(asocket *s)
-{
+static void local_socket_ready(asocket* s) {
     /* far side is ready for data, pay attention to
        readable events */
     fdevent_add(&s->fde, FDE_READ);
 }
 
-static void local_socket_close(asocket *s)
-{
-    adb_mutex_lock(&socket_list_lock);
-    local_socket_close_locked(s);
-    adb_mutex_unlock(&socket_list_lock);
-}
-
 // be sure to hold the socket list lock when calling this
-static void local_socket_destroy(asocket  *s)
-{
+static void local_socket_destroy(asocket* s) {
     apacket *p, *n;
     int exit_on_close = s->exit_on_close;
 
     D("LS(%d): destroying fde.fd=%d", s->id, s->fde.fd);
 
-        /* IMPORTANT: the remove closes the fd
-        ** that belongs to this socket
-        */
+    /* IMPORTANT: the remove closes the fd
+    ** that belongs to this socket
+    */
     fdevent_remove(&s->fde);
 
-        /* dispose of any unwritten data */
-    for(p = s->pkt_first; p; p = n) {
+    /* dispose of any unwritten data */
+    for (p = s->pkt_first; p; p = n) {
         D("LS(%d): discarding %d bytes", s->id, p->len);
         n = p->next;
         put_apacket(p);
@@ -232,41 +209,35 @@
     }
 }
 
-
-static void local_socket_close_locked(asocket *s)
-{
-    D("entered local_socket_close_locked. LS(%d) fd=%d", s->id, s->fd);
-    if(s->peer) {
-        D("LS(%d): closing peer. peer->id=%d peer->fd=%d",
-          s->id, s->peer->id, s->peer->fd);
+static void local_socket_close(asocket* s) {
+    D("entered local_socket_close. LS(%d) fd=%d", s->id, s->fd);
+    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
+    if (s->peer) {
+        D("LS(%d): closing peer. peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
         /* Note: it's important to call shutdown before disconnecting from
          * the peer, this ensures that remote sockets can still get the id
          * of the local socket they're connected to, to send a CLOSE()
          * protocol event. */
-        if (s->peer->shutdown)
-          s->peer->shutdown(s->peer);
-        s->peer->peer = 0;
-        // tweak to avoid deadlock
-        if (s->peer->close == local_socket_close) {
-            local_socket_close_locked(s->peer);
-        } else {
-            s->peer->close(s->peer);
+        if (s->peer->shutdown) {
+            s->peer->shutdown(s->peer);
         }
-        s->peer = 0;
+        s->peer->peer = nullptr;
+        s->peer->close(s->peer);
+        s->peer = nullptr;
     }
 
-        /* If we are already closing, or if there are no
-        ** pending packets, destroy immediately
-        */
+    /* If we are already closing, or if there are no
+    ** pending packets, destroy immediately
+    */
     if (s->closing || s->has_write_error || s->pkt_first == NULL) {
-        int   id = s->id;
+        int id = s->id;
         local_socket_destroy(s);
         D("LS(%d): closed", id);
         return;
     }
 
-        /* otherwise, put on the closing list
-        */
+    /* otherwise, put on the closing list
+    */
     D("LS(%d): closing", s->id);
     s->closing = 1;
     fdevent_del(&s->fde, FDE_READ);
@@ -276,8 +247,7 @@
     CHECK_EQ(FDE_WRITE, s->fde.state & FDE_WRITE);
 }
 
-static void local_socket_event_func(int fd, unsigned ev, void* _s)
-{
+static void local_socket_event_func(int fd, unsigned ev, void* _s) {
     asocket* s = reinterpret_cast<asocket*>(_s);
     D("LS(%d): event_func(fd=%d(==%d), ev=%04x)", s->id, s->fd, fd, ev);
 
@@ -334,10 +304,9 @@
         s->peer->ready(s->peer);
     }
 
-
     if (ev & FDE_READ) {
-        apacket *p = get_apacket();
-        unsigned char *x = p->data;
+        apacket* p = get_apacket();
+        unsigned char* x = p->data;
         const size_t max_payload = s->get_max_payload();
         size_t avail = max_payload;
         int r = 0;
@@ -345,8 +314,8 @@
 
         while (avail > 0) {
             r = adb_read(fd, x, avail);
-            D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu",
-              s->id, s->fd, r, r < 0 ? errno : 0, avail);
+            D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu", s->id, s->fd, r,
+              r < 0 ? errno : 0, avail);
             if (r == -1) {
                 if (errno == EAGAIN) {
                     break;
@@ -361,8 +330,8 @@
             is_eof = 1;
             break;
         }
-        D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d",
-          s->id, s->fd, r, is_eof, s->fde.force_eof);
+        D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d", s->id, s->fd, r, is_eof,
+          s->fde.force_eof);
         if ((avail == max_payload) || (s->peer == 0)) {
             put_apacket(p);
         } else {
@@ -376,48 +345,48 @@
             D("LS(%u): fd=%d post peer->enqueue(). r=%d", saved_id, saved_fd, r);
 
             if (r < 0) {
-                    /* error return means they closed us as a side-effect
-                    ** and we must return immediately.
-                    **
-                    ** note that if we still have buffered packets, the
-                    ** socket will be placed on the closing socket list.
-                    ** this handler function will be called again
-                    ** to process FDE_WRITE events.
-                    */
+                /* error return means they closed us as a side-effect
+                ** and we must return immediately.
+                **
+                ** note that if we still have buffered packets, the
+                ** socket will be placed on the closing socket list.
+                ** this handler function will be called again
+                ** to process FDE_WRITE events.
+                */
                 return;
             }
 
             if (r > 0) {
-                    /* if the remote cannot accept further events,
-                    ** we disable notification of READs.  They'll
-                    ** be enabled again when we get a call to ready()
-                    */
+                /* if the remote cannot accept further events,
+                ** we disable notification of READs.  They'll
+                ** be enabled again when we get a call to ready()
+                */
                 fdevent_del(&s->fde, FDE_READ);
             }
         }
         /* Don't allow a forced eof if data is still there */
         if ((s->fde.force_eof && !r) || is_eof) {
-            D(" closing because is_eof=%d r=%d s->fde.force_eof=%d",
-              is_eof, r, s->fde.force_eof);
+            D(" closing because is_eof=%d r=%d s->fde.force_eof=%d", is_eof, r, s->fde.force_eof);
             s->close(s);
             return;
         }
     }
 
-    if (ev & FDE_ERROR){
-            /* this should be caught be the next read or write
-            ** catching it here means we may skip the last few
-            ** bytes of readable data.
-            */
+    if (ev & FDE_ERROR) {
+        /* this should be caught be the next read or write
+        ** catching it here means we may skip the last few
+        ** bytes of readable data.
+        */
         D("LS(%d): FDE_ERROR (fd=%d)", s->id, s->fd);
         return;
     }
 }
 
-asocket *create_local_socket(int fd)
-{
-    asocket *s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
-    if (s == NULL) fatal("cannot allocate socket");
+asocket* create_local_socket(int fd) {
+    asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
+    if (s == NULL) {
+        fatal("cannot allocate socket");
+    }
     s->fd = fd;
     s->enqueue = local_socket_enqueue;
     s->ready = local_socket_ready;
@@ -430,32 +399,33 @@
     return s;
 }
 
-asocket *create_local_service_socket(const char *name,
-                                     const atransport* transport)
-{
+asocket* create_local_service_socket(const char* name, const atransport* transport) {
 #if !ADB_HOST
-    if (!strcmp(name,"jdwp")) {
+    if (!strcmp(name, "jdwp")) {
         return create_jdwp_service_socket();
     }
-    if (!strcmp(name,"track-jdwp")) {
+    if (!strcmp(name, "track-jdwp")) {
         return create_jdwp_tracker_service_socket();
     }
 #endif
     int fd = service_to_fd(name, transport);
-    if(fd < 0) return 0;
+    if (fd < 0) {
+        return 0;
+    }
 
     asocket* s = create_local_socket(fd);
     D("LS(%d): bound to '%s' via %d", s->id, name, fd);
 
 #if !ADB_HOST
     char debug[PROPERTY_VALUE_MAX];
-    if (!strncmp(name, "root:", 5))
+    if (!strncmp(name, "root:", 5)) {
         property_get("ro.debuggable", debug, "");
+    }
 
-    if ((!strncmp(name, "root:", 5) && getuid() != 0 && strcmp(debug, "1") == 0)
-        || (!strncmp(name, "unroot:", 7) && getuid() == 0)
-        || !strncmp(name, "usb:", 4)
-        || !strncmp(name, "tcpip:", 6)) {
+    if ((!strncmp(name, "root:", 5) && getuid() != 0 && strcmp(debug, "1") == 0) ||
+        (!strncmp(name, "unroot:", 7) && getuid() == 0) ||
+        !strncmp(name, "usb:", 4) ||
+        !strncmp(name, "tcpip:", 6)) {
         D("LS(%d): enabling exit_on_close", s->id);
         s->exit_on_close = 1;
     }
@@ -465,9 +435,8 @@
 }
 
 #if ADB_HOST
-static asocket *create_host_service_socket(const char *name, const char* serial)
-{
-    asocket *s;
+static asocket* create_host_service_socket(const char* name, const char* serial) {
+    asocket* s;
 
     s = host_service_to_socket(name, serial);
 
@@ -480,10 +449,8 @@
 }
 #endif /* ADB_HOST */
 
-static int remote_socket_enqueue(asocket *s, apacket *p)
-{
-    D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d",
-      s->id, s->fd, s->peer->fd);
+static int remote_socket_enqueue(asocket* s, apacket* p) {
+    D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d", s->id, s->fd, s->peer->fd);
     p->msg.command = A_WRTE;
     p->msg.arg0 = s->peer->id;
     p->msg.arg1 = s->id;
@@ -492,40 +459,35 @@
     return 1;
 }
 
-static void remote_socket_ready(asocket *s)
-{
-    D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d",
-      s->id, s->fd, s->peer->fd);
-    apacket *p = get_apacket();
+static void remote_socket_ready(asocket* s) {
+    D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d", s->id, s->fd, s->peer->fd);
+    apacket* p = get_apacket();
     p->msg.command = A_OKAY;
     p->msg.arg0 = s->peer->id;
     p->msg.arg1 = s->id;
     send_packet(p, s->transport);
 }
 
-static void remote_socket_shutdown(asocket *s)
-{
-    D("entered remote_socket_shutdown RS(%d) CLOSE fd=%d peer->fd=%d",
-      s->id, s->fd, s->peer?s->peer->fd:-1);
-    apacket *p = get_apacket();
+static void remote_socket_shutdown(asocket* s) {
+    D("entered remote_socket_shutdown RS(%d) CLOSE fd=%d peer->fd=%d", s->id, s->fd,
+      s->peer ? s->peer->fd : -1);
+    apacket* p = get_apacket();
     p->msg.command = A_CLSE;
-    if(s->peer) {
+    if (s->peer) {
         p->msg.arg0 = s->peer->id;
     }
     p->msg.arg1 = s->id;
     send_packet(p, s->transport);
 }
 
-static void remote_socket_close(asocket *s)
-{
+static void remote_socket_close(asocket* s) {
     if (s->peer) {
         s->peer->peer = 0;
-        D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d",
-          s->id, s->peer->id, s->peer->fd);
+        D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
         s->peer->close(s->peer);
     }
-    D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d",
-      s->id, s->fd, s->peer?s->peer->fd:-1);
+    D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d", s->id, s->fd,
+      s->peer ? s->peer->fd : -1);
     D("RS(%d): closed", s->id);
     free(s);
 }
@@ -534,12 +496,15 @@
 // |t|. Where |id| is the socket id of the corresponding service on the other
 //  side of the transport (it is allocated by the remote side and _cannot_ be 0).
 // Returns a new non-NULL asocket handle.
-asocket *create_remote_socket(unsigned id, atransport *t)
-{
-    if (id == 0) fatal("invalid remote socket id (0)");
+asocket* create_remote_socket(unsigned id, atransport* t) {
+    if (id == 0) {
+        fatal("invalid remote socket id (0)");
+    }
     asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
 
-    if (s == NULL) fatal("cannot allocate socket");
+    if (s == NULL) {
+        fatal("cannot allocate socket");
+    }
     s->id = id;
     s->enqueue = remote_socket_enqueue;
     s->ready = remote_socket_ready;
@@ -551,13 +516,12 @@
     return s;
 }
 
-void connect_to_remote(asocket *s, const char *destination)
-{
+void connect_to_remote(asocket* s, const char* destination) {
     D("Connect_to_remote call RS(%d) fd=%d", s->id, s->fd);
-    apacket *p = get_apacket();
+    apacket* p = get_apacket();
     size_t len = strlen(destination) + 1;
 
-    if(len > (s->get_max_payload()-1)) {
+    if (len > (s->get_max_payload() - 1)) {
         fatal("destination oversized");
     }
 
@@ -565,15 +529,13 @@
     p->msg.command = A_OPEN;
     p->msg.arg0 = s->id;
     p->msg.data_length = len;
-    strcpy((char*) p->data, destination);
+    strcpy((char*)p->data, destination);
     send_packet(p, s->transport);
 }
 
-
 /* this is used by magic sockets to rig local sockets to
    send the go-ahead message when they connect */
-static void local_socket_ready_notify(asocket *s)
-{
+static void local_socket_ready_notify(asocket* s) {
     s->ready = local_socket_ready;
     s->shutdown = NULL;
     s->close = local_socket_close;
@@ -584,8 +546,7 @@
 /* this is used by magic sockets to rig local sockets to
    send the failure message if they are closed before
    connected (to avoid closing them without a status message) */
-static void local_socket_close_notify(asocket *s)
-{
+static void local_socket_close_notify(asocket* s) {
     s->ready = local_socket_ready;
     s->shutdown = NULL;
     s->close = local_socket_close;
@@ -593,28 +554,41 @@
     s->close(s);
 }
 
-static unsigned unhex(unsigned char *s, int len)
-{
+static unsigned unhex(unsigned char* s, int len) {
     unsigned n = 0, c;
 
-    while(len-- > 0) {
-        switch((c = *s++)) {
-        case '0': case '1': case '2':
-        case '3': case '4': case '5':
-        case '6': case '7': case '8':
-        case '9':
-            c -= '0';
-            break;
-        case 'a': case 'b': case 'c':
-        case 'd': case 'e': case 'f':
-            c = c - 'a' + 10;
-            break;
-        case 'A': case 'B': case 'C':
-        case 'D': case 'E': case 'F':
-            c = c - 'A' + 10;
-            break;
-        default:
-            return 0xffffffff;
+    while (len-- > 0) {
+        switch ((c = *s++)) {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+                c -= '0';
+                break;
+            case 'a':
+            case 'b':
+            case 'c':
+            case 'd':
+            case 'e':
+            case 'f':
+                c = c - 'a' + 10;
+                break;
+            case 'A':
+            case 'B':
+            case 'C':
+            case 'D':
+            case 'E':
+            case 'F':
+                c = c - 'A' + 10;
+                break;
+            default:
+                return 0xffffffff;
         }
 
         n = (n << 4) | c;
@@ -671,31 +645,29 @@
 
 }  // namespace internal
 
-#endif // ADB_HOST
+#endif  // ADB_HOST
 
-static int smart_socket_enqueue(asocket *s, apacket *p)
-{
+static int smart_socket_enqueue(asocket* s, apacket* p) {
     unsigned len;
 #if ADB_HOST
-    char *service = nullptr;
+    char* service = nullptr;
     char* serial = nullptr;
     TransportType type = kTransportAny;
 #endif
 
     D("SS(%d): enqueue %d", s->id, p->len);
 
-    if(s->pkt_first == 0) {
+    if (s->pkt_first == 0) {
         s->pkt_first = p;
         s->pkt_last = p;
     } else {
-        if((s->pkt_first->len + p->len) > s->get_max_payload()) {
+        if ((s->pkt_first->len + p->len) > s->get_max_payload()) {
             D("SS(%d): overflow", s->id);
             put_apacket(p);
             goto fail;
         }
 
-        memcpy(s->pkt_first->data + s->pkt_first->len,
-               p->data, p->len);
+        memcpy(s->pkt_first->data + s->pkt_first->len, p->data, p->len);
         s->pkt_first->len += p->len;
         put_apacket(p);
 
@@ -703,7 +675,9 @@
     }
 
     /* don't bother if we can't decode the length */
-    if(p->len < 4) return 0;
+    if (p->len < 4) {
+        return 0;
+    }
 
     len = unhex(p->data, 4);
     if ((len < 1) || (len > MAX_PAYLOAD_V1)) {
@@ -711,27 +685,27 @@
         goto fail;
     }
 
-    D("SS(%d): len is %d", s->id, len );
+    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);
+    if ((len + 4) > p->len) {
+        D("SS(%d): waiting for %d more bytes", s->id, len + 4 - p->len);
         return 0;
     }
 
     p->data[len + 4] = 0;
 
-    D("SS(%d): '%s'", s->id, (char*) (p->data + 4));
+    D("SS(%d): '%s'", s->id, (char*)(p->data + 4));
 
 #if ADB_HOST
-    service = (char *)p->data + 4;
-    if(!strncmp(service, "host-serial:", strlen("host-serial:"))) {
+    service = (char*)p->data + 4;
+    if (!strncmp(service, "host-serial:", strlen("host-serial:"))) {
         char* serial_end;
         service += strlen("host-serial:");
 
         // serial number should follow "host:" and could be a host:port string.
         serial_end = internal::skip_host_serial(service);
         if (serial_end) {
-            *serial_end = 0; // terminate string
+            *serial_end = 0;  // terminate string
             serial = service;
             service = serial_end + 1;
         }
@@ -749,42 +723,42 @@
     }
 
     if (service) {
-        asocket *s2;
+        asocket* s2;
 
-            /* some requests are handled immediately -- in that
-            ** case the handle_host_request() routine has sent
-            ** the OKAY or FAIL message and all we have to do
-            ** is clean up.
-            */
-        if(handle_host_request(service, type, serial, s->peer->fd, s) == 0) {
-                /* XXX fail message? */
-            D( "SS(%d): handled host service '%s'", s->id, service );
+        /* some requests are handled immediately -- in that
+        ** case the handle_host_request() routine has sent
+        ** the OKAY or FAIL message and all we have to do
+        ** is clean up.
+        */
+        if (handle_host_request(service, type, serial, s->peer->fd, s) == 0) {
+            /* XXX fail message? */
+            D("SS(%d): handled host service '%s'", s->id, service);
             goto fail;
         }
         if (!strncmp(service, "transport", strlen("transport"))) {
-            D( "SS(%d): okay transport", s->id );
+            D("SS(%d): okay transport", s->id);
             p->len = 0;
             return 0;
         }
 
-            /* try to find a local service with this name.
-            ** if no such service exists, we'll fail out
-            ** and tear down here.
-            */
+        /* try to find a local service with this name.
+        ** if no such service exists, we'll fail out
+        ** and tear down here.
+        */
         s2 = create_host_service_socket(service, serial);
-        if(s2 == 0) {
-            D( "SS(%d): couldn't create host service '%s'", s->id, service );
+        if (s2 == 0) {
+            D("SS(%d): couldn't create host service '%s'", s->id, service);
             SendFail(s->peer->fd, "unknown host service");
             goto fail;
         }
 
-            /* we've connected to a local host service,
-            ** so we make our peer back into a regular
-            ** local socket and bind it to the new local
-            ** service socket, acknowledge the successful
-            ** connection, and close this smart socket now
-            ** that its work is done.
-            */
+        /* we've connected to a local host service,
+        ** so we make our peer back into a regular
+        ** local socket and bind it to the new local
+        ** service socket, acknowledge the successful
+        ** connection, and close this smart socket now
+        ** that its work is done.
+        */
         SendOkay(s->peer->fd);
 
         s->peer->ready = local_socket_ready;
@@ -793,10 +767,10 @@
         s->peer->peer = s2;
         s2->peer = s->peer;
         s->peer = 0;
-        D( "SS(%d): okay", s->id );
+        D("SS(%d): okay", s->id);
         s->close(s);
 
-            /* initial state is "ready" */
+        /* initial state is "ready" */
         s2->ready(s2);
         return 0;
     }
@@ -811,53 +785,50 @@
     }
 #endif
 
-    if(!(s->transport) || (s->transport->connection_state == kCsOffline)) {
-           /* if there's no remote we fail the connection
-            ** right here and terminate it
-            */
+    if (!(s->transport) || (s->transport->connection_state == kCsOffline)) {
+        /* if there's no remote we fail the connection
+         ** right here and terminate it
+         */
         SendFail(s->peer->fd, "device offline (x)");
         goto fail;
     }
 
-
-        /* instrument our peer to pass the success or fail
-        ** message back once it connects or closes, then
-        ** detach from it, request the connection, and
-        ** tear down
-        */
+    /* instrument our peer to pass the success or fail
+    ** message back once it connects or closes, then
+    ** detach from it, request the connection, and
+    ** tear down
+    */
     s->peer->ready = local_socket_ready_notify;
     s->peer->shutdown = nullptr;
     s->peer->close = local_socket_close_notify;
     s->peer->peer = 0;
-        /* give him our transport and upref it */
+    /* give him our transport and upref it */
     s->peer->transport = s->transport;
 
-    connect_to_remote(s->peer, (char*) (p->data + 4));
+    connect_to_remote(s->peer, (char*)(p->data + 4));
     s->peer = 0;
     s->close(s);
     return 1;
 
 fail:
-        /* we're going to close our peer as a side-effect, so
-        ** return -1 to signal that state to the local socket
-        ** who is enqueueing against us
-        */
+    /* we're going to close our peer as a side-effect, so
+    ** return -1 to signal that state to the local socket
+    ** who is enqueueing against us
+    */
     s->close(s);
     return -1;
 }
 
-static void smart_socket_ready(asocket *s)
-{
+static void smart_socket_ready(asocket* s) {
     D("SS(%d): ready", s->id);
 }
 
-static void smart_socket_close(asocket *s)
-{
+static void smart_socket_close(asocket* s) {
     D("SS(%d): closed", s->id);
-    if(s->pkt_first){
+    if (s->pkt_first) {
         put_apacket(s->pkt_first);
     }
-    if(s->peer) {
+    if (s->peer) {
         s->peer->peer = 0;
         s->peer->close(s->peer);
         s->peer = 0;
@@ -865,10 +836,9 @@
     free(s);
 }
 
-static asocket *create_smart_socket(void)
-{
+static asocket* create_smart_socket(void) {
     D("Creating smart socket");
-    asocket *s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
+    asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
     if (s == NULL) fatal("cannot allocate socket");
     s->enqueue = smart_socket_enqueue;
     s->ready = smart_socket_ready;
@@ -879,10 +849,9 @@
     return s;
 }
 
-void connect_to_smartsocket(asocket *s)
-{
+void connect_to_smartsocket(asocket* s) {
     D("Connecting to smart socket");
-    asocket *ss = create_smart_socket();
+    asocket* ss = create_smart_socket();
     s->peer = ss;
     ss->peer = s;
     s->ready(s);
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 81d201e..639f8eb 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -29,8 +29,9 @@
 #include <string>
 #include <vector>
 
-// Include this before open/unlink are defined as macros below.
+// Include this before open/close/unlink are defined as macros below.
 #include <android-base/errors.h>
+#include <android-base/unique_fd.h>
 #include <android-base/utf8.h>
 
 /*
@@ -287,6 +288,9 @@
 #undef   accept
 #define  accept  ___xxx_accept
 
+// Returns the local port number of a bound socket, or -1 on failure.
+int adb_socket_get_local_port(int fd);
+
 extern int  adb_setsockopt(int  fd, int  level, int  optname, const void*  optval, socklen_t  optlen);
 
 #undef   setsockopt
@@ -691,6 +695,10 @@
 #undef   accept
 #define  accept  ___xxx_accept
 
+inline int adb_socket_get_local_port(int fd) {
+    return socket_get_local_port(fd);
+}
+
 // Operate on a file descriptor returned from unix_open() or a well-known file
 // descriptor such as STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO.
 //
diff --git a/adb/sysdeps/mutex.h b/adb/sysdeps/mutex.h
new file mode 100644
index 0000000..73c9e6e
--- /dev/null
+++ b/adb/sysdeps/mutex.h
@@ -0,0 +1,107 @@
+#pragma once
+
+/*
+ * 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.
+ */
+
+#if defined(_WIN32)
+
+#include <windows.h>
+
+#include <android-base/macros.h>
+
+#include "adb.h"
+
+// The prebuilt version of mingw we use doesn't support mutex or recursive_mutex.
+// Therefore, implement our own using the Windows primitives.
+// Put them directly into the std namespace, so that when they're actually available, the build
+// breaks until they're removed.
+
+#include <mutex>
+namespace std {
+
+// CRITICAL_SECTION is recursive, so just wrap it in a Mutex-compatible class.
+class recursive_mutex {
+  public:
+    recursive_mutex() {
+        InitializeCriticalSection(&mutex_);
+    }
+
+    ~recursive_mutex() {
+        DeleteCriticalSection(&mutex_);
+    }
+
+    void lock() {
+        EnterCriticalSection(&mutex_);
+    }
+
+    bool try_lock() {
+        return TryEnterCriticalSection(&mutex_);
+    }
+
+    void unlock() {
+        LeaveCriticalSection(&mutex_);
+    }
+
+  private:
+    CRITICAL_SECTION mutex_;
+
+    DISALLOW_COPY_AND_ASSIGN(recursive_mutex);
+};
+
+class mutex {
+  public:
+    mutex() {
+    }
+
+    ~mutex() {
+    }
+
+    void lock() {
+        mutex_.lock();
+        if (++lock_count_ != 1) {
+            fatal("non-recursive mutex locked reentrantly");
+        }
+    }
+
+    void unlock() {
+        if (--lock_count_ != 0) {
+            fatal("non-recursive mutex unlock resulted in unexpected lock count: %d", lock_count_);
+        }
+        mutex_.unlock();
+    }
+
+    bool try_lock() {
+        if (!mutex_.try_lock()) {
+            return false;
+        }
+
+        if (lock_count_ != 0) {
+            mutex_.unlock();
+            return false;
+        }
+
+        ++lock_count_;
+        return true;
+    }
+
+  private:
+    recursive_mutex mutex_;
+    size_t lock_count_ = 0;
+};
+
+}
+
+#endif
diff --git a/adb/sysdeps_test.cpp b/adb/sysdeps_test.cpp
index fde344a..395d22d 100644
--- a/adb/sysdeps_test.cpp
+++ b/adb/sysdeps_test.cpp
@@ -244,3 +244,60 @@
         adb_close(fd);
     }
 }
+
+#include "sysdeps/mutex.h"
+TEST(sysdeps_mutex, mutex_smoke) {
+    static std::atomic<bool> finished(false);
+    static std::mutex &m = *new std::mutex();
+    m.lock();
+    ASSERT_FALSE(m.try_lock());
+    adb_thread_create([](void*) {
+        ASSERT_FALSE(m.try_lock());
+        m.lock();
+        finished.store(true);
+        adb_sleep_ms(200);
+        m.unlock();
+    }, nullptr);
+
+    ASSERT_FALSE(finished.load());
+    adb_sleep_ms(100);
+    ASSERT_FALSE(finished.load());
+    m.unlock();
+    adb_sleep_ms(100);
+    m.lock();
+    ASSERT_TRUE(finished.load());
+    m.unlock();
+}
+
+// Our implementation on Windows aborts on double lock.
+#if defined(_WIN32)
+TEST(sysdeps_mutex, mutex_reentrant_lock) {
+    std::mutex &m = *new std::mutex();
+
+    m.lock();
+    ASSERT_FALSE(m.try_lock());
+    EXPECT_DEATH(m.lock(), "non-recursive mutex locked reentrantly");
+}
+#endif
+
+TEST(sysdeps_mutex, recursive_mutex_smoke) {
+    static std::recursive_mutex &m = *new std::recursive_mutex();
+
+    m.lock();
+    ASSERT_TRUE(m.try_lock());
+    m.unlock();
+
+    adb_thread_create([](void*) {
+        ASSERT_FALSE(m.try_lock());
+        m.lock();
+        adb_sleep_ms(500);
+        m.unlock();
+    }, nullptr);
+
+    adb_sleep_ms(100);
+    m.unlock();
+    adb_sleep_ms(100);
+    ASSERT_FALSE(m.try_lock());
+    m.lock();
+    m.unlock();
+}
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index bc09fdc..faf7f3e 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -1128,6 +1128,24 @@
     return result;
 }
 
+int adb_socket_get_local_port(int fd) {
+    sockaddr_storage addr_storage;
+    socklen_t addr_len = sizeof(addr_storage);
+
+    if (adb_getsockname(fd, reinterpret_cast<sockaddr*>(&addr_storage), &addr_len) < 0) {
+        D("adb_socket_get_local_port: adb_getsockname failed: %s", strerror(errno));
+        return -1;
+    }
+
+    if (!(addr_storage.ss_family == AF_INET || addr_storage.ss_family == AF_INET6)) {
+        D("adb_socket_get_local_port: unknown address family received: %d", addr_storage.ss_family);
+        errno = ECONNABORTED;
+        return -1;
+    }
+
+    return ntohs(reinterpret_cast<sockaddr_in*>(&addr_storage)->sin_port);
+}
+
 int  adb_shutdown(int  fd)
 {
     FH   f = _fh_from_int(fd, __func__);
@@ -1154,9 +1172,7 @@
     int server = -1;
     int client = -1;
     int accepted = -1;
-    sockaddr_storage addr_storage;
-    socklen_t addr_len = sizeof(addr_storage);
-    sockaddr_in* addr = nullptr;
+    int local_port = -1;
     std::string error;
 
     server = network_loopback_server(0, SOCK_STREAM, &error);
@@ -1165,20 +1181,14 @@
         goto fail;
     }
 
-    if (adb_getsockname(server, reinterpret_cast<sockaddr*>(&addr_storage), &addr_len) < 0) {
-        D("adb_socketpair: adb_getsockname failed: %s", strerror(errno));
+    local_port = adb_socket_get_local_port(server);
+    if (local_port < 0) {
+        D("adb_socketpair: failed to get server port number: %s", error.c_str());
         goto fail;
     }
+    D("adb_socketpair: bound on port %d", local_port);
 
-    if (addr_storage.ss_family != AF_INET) {
-        D("adb_socketpair: unknown address family received: %d", addr_storage.ss_family);
-        errno = ECONNABORTED;
-        goto fail;
-    }
-
-    addr = reinterpret_cast<sockaddr_in*>(&addr_storage);
-    D("adb_socketpair: bound on port %d", ntohs(addr->sin_port));
-    client = network_loopback_client(ntohs(addr->sin_port), SOCK_STREAM, &error);
+    client = network_loopback_client(local_port, SOCK_STREAM, &error);
     if (client < 0) {
         D("adb_socketpair: failed to connect client: %s", error.c_str());
         goto fail;
diff --git a/adb/test_device.py b/adb/test_device.py
index 2a3be88..cdc57c6 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -191,6 +191,22 @@
         msg = self.device.forward_list()
         self.assertEqual('', msg.strip())
 
+    def test_forward_tcp_port_0(self):
+        self.assertEqual('', self.device.forward_list().strip(),
+                         'Forwarding list must be empty to run this test.')
+
+        try:
+            # If resolving TCP port 0 is supported, `adb forward` will print
+            # the actual port number.
+            port = self.device.forward('tcp:0', 'tcp:8888').strip()
+            if not port:
+                raise unittest.SkipTest('Forwarding tcp:0 is not available.')
+
+            self.assertTrue(re.search(r'tcp:{}.+tcp:8888'.format(port),
+                                      self.device.forward_list()))
+        finally:
+            self.device.forward_remove_all()
+
     def test_reverse(self):
         msg = self.device.reverse_list()
         self.assertEqual('', msg.strip(),
@@ -210,6 +226,22 @@
         msg = self.device.reverse_list()
         self.assertEqual('', msg.strip())
 
+    def test_reverse_tcp_port_0(self):
+        self.assertEqual('', self.device.reverse_list().strip(),
+                         'Reverse list must be empty to run this test.')
+
+        try:
+            # If resolving TCP port 0 is supported, `adb reverse` will print
+            # the actual port number.
+            port = self.device.reverse('tcp:0', 'tcp:8888').strip()
+            if not port:
+                raise unittest.SkipTest('Reversing tcp:0 is not available.')
+
+            self.assertTrue(re.search(r'tcp:{}.+tcp:8888'.format(port),
+                                      self.device.reverse_list()))
+        finally:
+            self.device.reverse_remove_all()
+
     # Note: If you run this test when adb connect'd to a physical device over
     # TCP, it will fail in adb reverse due to https://code.google.com/p/android/issues/detail?id=189821
     def test_forward_reverse_echo(self):
diff --git a/adb/test_track_devices.cpp b/adb/test_track_devices.cpp
deleted file mode 100644
index b10f8ee..0000000
--- a/adb/test_track_devices.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-// TODO: replace this with a shell/python script.
-
-/* a simple test program, connects to ADB server, and opens a track-devices session */
-#include <errno.h>
-#include <memory.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-#include <android-base/file.h>
-
-static void
-panic( const char*  msg )
-{
-    fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno));
-    exit(1);
-}
-
-int main(int argc, char* argv[]) {
-    const char* request = "host:track-devices";
-
-    if (argv[1] && strcmp(argv[1], "--jdwp") == 0) {
-        request = "track-jdwp";
-    }
-
-    int                  ret;
-    struct sockaddr_in   server;
-    char                 buffer[1024];
-
-    memset( &server, 0, sizeof(server) );
-    server.sin_family      = AF_INET;
-    server.sin_port        = htons(5037);
-    server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
-    int s = socket( PF_INET, SOCK_STREAM, 0 );
-    ret = connect( s, (struct sockaddr*) &server, sizeof(server) );
-    if (ret < 0) panic( "could not connect to server" );
-
-    /* send the request */
-    int len = snprintf(buffer, sizeof(buffer), "%04zx%s", strlen(request), request);
-    if (!android::base::WriteFully(s, buffer, len))
-        panic( "could not send request" );
-
-    /* read the OKAY answer */
-    if (!android::base::ReadFully(s, buffer, 4))
-        panic( "could not read request" );
-
-    printf( "server answer: %.*s\n", 4, buffer );
-
-    /* now loop */
-    while (true) {
-        char  head[5] = "0000";
-
-        if (!android::base::ReadFully(s, head, 4))
-            panic("could not read length");
-
-        int len;
-        if (sscanf(head, "%04x", &len) != 1 )
-            panic("could not decode length");
-
-        if (!android::base::ReadFully(s, buffer, len))
-            panic("could not read data");
-
-        printf( "received header %.*s (%d bytes):\n%.*s----\n", 4, head, len, len, buffer );
-    }
-    close(s);
-}
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index ab41c55..869e60f 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -39,25 +39,33 @@
 namespace android {
 namespace base {
 
-class unique_fd final {
+struct DefaultCloser {
+  static void Close(int fd) {
+    // Even if close(2) fails with EINTR, the fd will have been closed.
+    // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone
+    // else's fd.
+    // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
+    ::close(fd);
+  }
+};
+
+template <typename Closer>
+class unique_fd_impl final {
  public:
-  unique_fd() : value_(-1) {}
+  unique_fd_impl() : value_(-1) {}
 
-  explicit unique_fd(int value) : value_(value) {}
-  ~unique_fd() { clear(); }
+  explicit unique_fd_impl(int value) : value_(value) {}
+  ~unique_fd_impl() { clear(); }
 
-  unique_fd(unique_fd&& other) : value_(other.release()) {}
-  unique_fd& operator=(unique_fd&& s) {
+  unique_fd_impl(unique_fd_impl&& other) : value_(other.release()) {}
+  unique_fd_impl& operator=(unique_fd_impl&& s) {
     reset(s.release());
     return *this;
   }
 
   void reset(int new_value) {
     if (value_ != -1) {
-      // Even if close(2) fails with EINTR, the fd will have been closed.
-      // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone else's fd.
-      // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
-      close(value_);
+      Closer::Close(value_);
     }
     value_ = new_value;
   }
@@ -78,10 +86,12 @@
  private:
   int value_;
 
-  unique_fd(const unique_fd&);
-  void operator=(const unique_fd&);
+  unique_fd_impl(const unique_fd_impl&);
+  void operator=(const unique_fd_impl&);
 };
 
+using unique_fd = unique_fd_impl<DefaultCloser>;
+
 }  // namespace base
 }  // namespace android
 
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 6469db4..9ce94c5 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -54,7 +54,7 @@
 
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := crasher.c
+LOCAL_SRC_FILES := crasher.cpp
 LOCAL_SRC_FILES_arm    := arm/crashglue.S
 LOCAL_SRC_FILES_arm64  := arm64/crashglue.S
 LOCAL_SRC_FILES_mips   := mips/crashglue.S
@@ -63,9 +63,9 @@
 LOCAL_SRC_FILES_x86_64 := x86_64/crashglue.S
 LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
 LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS += -fstack-protector-all -Werror -Wno-free-nonheap-object -Wno-date-time
+LOCAL_CPPFLAGS := $(common_cppflags) -fstack-protector-all -Wno-free-nonheap-object -Wno-date-time
 #LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_SHARED_LIBRARIES := libcutils liblog libc
+LOCAL_SHARED_LIBRARIES := libcutils liblog
 
 # The arm emulator has VFP but not VFPv3-D32.
 ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
diff --git a/debuggerd/crasher.c b/debuggerd/crasher.cpp
similarity index 93%
rename from debuggerd/crasher.c
rename to debuggerd/crasher.cpp
index 75f070b..bdeaf0b 100644
--- a/debuggerd/crasher.c
+++ b/debuggerd/crasher.cpp
@@ -22,8 +22,9 @@
 
 extern const char* __progname;
 
-void crash1(void);
-void crashnostack(void);
+extern "C" void crash1(void);
+extern "C" void crashnostack(void);
+
 static int do_action(const char* arg);
 
 static void maybe_abort() {
@@ -159,6 +160,10 @@
         __assert("some_file.c", 123, "false");
     } else if (!strcmp(arg, "assert2")) {
         __assert2("some_file.c", 123, "some_function", "false");
+    } else if (!strcmp(arg, "fortify")) {
+        char buf[10];
+        __read_chk(-1, buf, 32, 10);
+        while (true) pause();
     } else if (!strcmp(arg, "LOG_ALWAYS_FATAL")) {
         LOG_ALWAYS_FATAL("hello %s", "world");
     } else if (!strcmp(arg, "LOG_ALWAYS_FATAL_IF")) {
@@ -172,7 +177,7 @@
     } else if (!strcmp(arg, "heap-usage")) {
         abuse_heap();
     } else if (!strcmp(arg, "SIGSEGV-unmapped")) {
-        char* map = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+        char* map = reinterpret_cast<char*>(mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0));
         munmap(map, sizeof(int));
         map[0] = '8';
     }
@@ -189,6 +194,7 @@
     fprintf(stderr, "  abort                 call abort()\n");
     fprintf(stderr, "  assert                call assert() without a function\n");
     fprintf(stderr, "  assert2               call assert() with a function\n");
+    fprintf(stderr, "  fortify               fail a _FORTIFY_SOURCE check\n");
     fprintf(stderr, "  LOG_ALWAYS_FATAL      call LOG_ALWAYS_FATAL\n");
     fprintf(stderr, "  LOG_ALWAYS_FATAL_IF   call LOG_ALWAYS_FATAL\n");
     fprintf(stderr, "  SIGFPE                cause a SIGFPE\n");
diff --git a/debuggerd/elf_utils.cpp b/debuggerd/elf_utils.cpp
index 9959f2e..3d99cab 100644
--- a/debuggerd/elf_utils.cpp
+++ b/debuggerd/elf_utils.cpp
@@ -29,7 +29,7 @@
 
 #include "elf_utils.h"
 
-#define NOTE_ALIGN(size)  ((size + 3) & ~3)
+#define NOTE_ALIGN(size)  (((size) + 3) & ~3)
 
 template <typename HdrType, typename PhdrType, typename NhdrType>
 static bool get_build_id(
diff --git a/debuggerd/test/host_signal_fixup.h b/debuggerd/test/host_signal_fixup.h
index c7796ef..762bae5 100644
--- a/debuggerd/test/host_signal_fixup.h
+++ b/debuggerd/test/host_signal_fixup.h
@@ -57,7 +57,7 @@
 #endif
 
 #if !defined(SI_DETHREAD)
-#define SI_DETHREAD -7
+#define SI_DETHREAD (-7)
 #endif
 
 #endif
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 94efcc3..1839d25 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -717,10 +717,10 @@
     return partition_type == "ext4";
 }
 
-static int load_buf_fd(Transport* transport, int fd, struct fastboot_buffer* buf) {
+static bool load_buf_fd(Transport* transport, int fd, struct fastboot_buffer* buf) {
     int64_t sz = get_file_size(fd);
     if (sz == -1) {
-        return -1;
+        return false;
     }
 
     lseek64(fd, 0, SEEK_SET);
@@ -728,7 +728,7 @@
     if (limit) {
         sparse_file** s = load_sparse_files(fd, limit);
         if (s == nullptr) {
-            return -1;
+            return false;
         }
         buf->type = FB_BUFFER_SPARSE;
         buf->data = s;
@@ -740,18 +740,14 @@
         buf->sz = sz;
     }
 
-    return 0;
+    return true;
 }
 
-static int load_buf(Transport* transport, const char *fname, struct fastboot_buffer *buf)
-{
-    int fd;
-
-    fd = open(fname, O_RDONLY | O_BINARY);
-    if (fd < 0) {
-        return -1;
+static bool load_buf(Transport* transport, const char* fname, struct fastboot_buffer* buf) {
+    int fd = open(fname, O_RDONLY | O_BINARY);
+    if (fd == -1) {
+        return false;
     }
-
     return load_buf_fd(transport, fd, buf);
 }
 
@@ -895,8 +891,8 @@
 static void do_flash(Transport* transport, const char* pname, const char* fname) {
     struct fastboot_buffer buf;
 
-    if (load_buf(transport, fname, &buf)) {
-        die("cannot load '%s'", fname);
+    if (!load_buf(transport, fname, &buf)) {
+        die("cannot load '%s': %s", fname, strerror(errno));
     }
     flash_buf(pname, &buf);
 }
@@ -940,8 +936,9 @@
             exit(1); // unzip_to_file already explained why.
         }
         fastboot_buffer buf;
-        int rc = load_buf_fd(transport, fd, &buf);
-        if (rc) die("cannot load %s from flash", images[i].img_name);
+        if (!load_buf_fd(transport, fd, &buf)) {
+            die("cannot load %s from flash: %s", images[i].img_name, strerror(errno));
+        }
 
         auto update = [&](const std::string &partition) {
             do_update_signature(zip, images[i].sig_name);
@@ -994,10 +991,9 @@
     for (size_t i = 0; i < ARRAY_SIZE(images); i++) {
         fname = find_item(images[i].part_name, product);
         fastboot_buffer buf;
-        if (load_buf(transport, fname.c_str(), &buf)) {
-            if (images[i].is_optional)
-                continue;
-            die("could not load %s\n", images[i].img_name);
+        if (!load_buf(transport, fname.c_str(), &buf)) {
+            if (images[i].is_optional) continue;
+            die("could not load '%s': %s", images[i].img_name, strerror(errno));
         }
 
         auto flashall = [&](const std::string &partition) {
@@ -1164,7 +1160,7 @@
         return;
     }
 
-    if (load_buf_fd(transport, fd, &buf)) {
+    if (!load_buf_fd(transport, fd, &buf)) {
         fprintf(stderr, "Cannot read image: %s\n", strerror(errno));
         close(fd);
         return;
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 129a5bb..72554a8 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -30,6 +30,7 @@
 #include <unistd.h>
 
 #include <android-base/file.h>
+#include <android-base/strings.h>
 #include <crypto_utils/android_pubkey.h>
 #include <cutils/properties.h>
 #include <logwrap/logwrap.h>
@@ -211,7 +212,7 @@
 }
 
 struct verity_table_params {
-    const char *table;
+    char *table;
     int mode;
     struct fec_ecc_metadata ecc;
     const char *ecc_dev;
@@ -843,15 +844,42 @@
     return rc;
 }
 
+static void update_verity_table_blk_device(char *blk_device, char **table)
+{
+    std::string result, word;
+    auto tokens = android::base::Split(*table, " ");
+
+    for (const auto token : tokens) {
+        if (android::base::StartsWith(token, "/dev/block/") &&
+            android::base::StartsWith(blk_device, token.c_str())) {
+            word = blk_device;
+        } else {
+            word = token;
+        }
+
+        if (result.empty()) {
+            result = word;
+        } else {
+            result += " " + word;
+        }
+    }
+
+    if (result.empty()) {
+        return;
+    }
+
+    free(*table);
+    *table = strdup(result.c_str());
+}
+
 int fs_mgr_setup_verity(struct fstab_rec *fstab)
 {
     int retval = FS_MGR_SETUP_VERITY_FAIL;
     int fd = -1;
-    char *invalid_table = NULL;
     char *verity_blk_name = NULL;
     struct fec_handle *f = NULL;
     struct fec_verity_metadata verity;
-    struct verity_table_params params;
+    struct verity_table_params params = { .table = NULL };
 
     alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
     struct dm_ioctl *io = (struct dm_ioctl *) buffer;
@@ -912,8 +940,17 @@
         params.mode = VERITY_MODE_EIO;
     }
 
+    if (!verity.table) {
+        goto out;
+    }
+
+    params.table = strdup(verity.table);
+    if (!params.table) {
+        goto out;
+    }
+
     // verify the signature on the table
-    if (verify_table(verity.signature, sizeof(verity.signature), verity.table,
+    if (verify_table(verity.signature, sizeof(verity.signature), params.table,
             verity.table_length) < 0) {
         if (params.mode == VERITY_MODE_LOGGING) {
             // the user has been warned, allow mounting without dm-verity
@@ -922,20 +959,18 @@
         }
 
         // invalidate root hash and salt to trigger device-specific recovery
-        invalid_table = strdup(verity.table);
-
-        if (!invalid_table ||
-                invalidate_table(invalid_table, verity.table_length) < 0) {
+        if (invalidate_table(params.table, verity.table_length) < 0) {
             goto out;
         }
-
-        params.table = invalid_table;
-    } else {
-        params.table = verity.table;
     }
 
     INFO("Enabling dm-verity for %s (mode %d)\n", mount_point, params.mode);
 
+    if (fstab->fs_mgr_flags & MF_SLOTSELECT) {
+        // Update the verity params using the actual block device path
+        update_verity_table_blk_device(fstab->blk_device, &params.table);
+    }
+
     // load the verity mapping table
     if (load_verity_table(io, mount_point, verity.data_size, fd, &params,
             format_verity_table) == 0) {
@@ -1001,7 +1036,7 @@
     }
 
     fec_close(f);
-    free(invalid_table);
+    free(params.table);
     free(verity_blk_name);
 
     return retval;
diff --git a/include/cutils/ashmem.h b/include/cutils/ashmem.h
index 25b233e..acedf73 100644
--- a/include/cutils/ashmem.h
+++ b/include/cutils/ashmem.h
@@ -12,6 +12,10 @@
 
 #include <stddef.h>
 
+#if defined(__BIONIC__)
+#include <linux/ashmem.h>
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -26,20 +30,4 @@
 }
 #endif
 
-#ifndef __ASHMEMIOC	/* in case someone included <linux/ashmem.h> too */
-
-#define ASHMEM_NAME_LEN		256
-
-#define ASHMEM_NAME_DEF		"dev/ashmem"
-
-/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
-#define ASHMEM_NOT_PURGED	0
-#define ASHMEM_WAS_PURGED	1
-
-/* Return values from ASHMEM_UNPIN: Is the mapping now pinned or unpinned? */
-#define ASHMEM_IS_UNPINNED	0
-#define ASHMEM_IS_PINNED	1
-
-#endif	/* ! __ASHMEMIOC */
-
 #endif	/* _CUTILS_ASHMEM_H */
diff --git a/include/private/canned_fs_config.h b/include/private/canned_fs_config.h
new file mode 100644
index 0000000..d9f51ca
--- /dev/null
+++ b/include/private/canned_fs_config.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2014 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 _CANNED_FS_CONFIG_H
+#define _CANNED_FS_CONFIG_H
+
+#include <inttypes.h>
+
+int load_canned_fs_config(const char* fn);
+void canned_fs_config(const char* path, int dir, const char* target_out_path,
+                      unsigned* uid, unsigned* gid, unsigned* mode, uint64_t* capabilities);
+
+#endif
diff --git a/init/devices.cpp b/init/devices.cpp
index d452dd3..1410e3b 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -43,6 +43,7 @@
 #include <sys/wait.h>
 
 #include <android-base/file.h>
+#include <android-base/stringprintf.h>
 #include <cutils/list.h>
 #include <cutils/uevent.h>
 
@@ -130,49 +131,6 @@
     return 0;
 }
 
-void fixup_sys_perms(const char *upath)
-{
-    char buf[512];
-    struct listnode *node;
-    struct perms_ *dp;
-
-    /* upaths omit the "/sys" that paths in this list
-     * contain, so we add 4 when comparing...
-     */
-    list_for_each(node, &sys_perms) {
-        dp = &(node_to_item(node, struct perm_node, plist))->dp;
-        if (dp->prefix) {
-            if (strncmp(upath, dp->name + 4, strlen(dp->name + 4)))
-                continue;
-        } else if (dp->wildcard) {
-            if (fnmatch(dp->name + 4, upath, FNM_PATHNAME) != 0)
-                continue;
-        } else {
-            if (strcmp(upath, dp->name + 4))
-                continue;
-        }
-
-        if ((strlen(upath) + strlen(dp->attr) + 6) > sizeof(buf))
-            break;
-
-        snprintf(buf, sizeof(buf), "/sys%s/%s", upath, dp->attr);
-        INFO("fixup %s %d %d 0%o\n", buf, dp->uid, dp->gid, dp->perm);
-        chown(buf, dp->uid, dp->gid);
-        chmod(buf, dp->perm);
-    }
-
-    // Now fixup SELinux file labels
-    int len = snprintf(buf, sizeof(buf), "/sys%s", upath);
-    if ((len < 0) || ((size_t) len >= sizeof(buf))) {
-        // Overflow
-        return;
-    }
-    if (access(buf, F_OK) == 0) {
-        INFO("restorecon_recursive: %s\n", buf);
-        restorecon_recursive(buf);
-    }
-}
-
 static bool perm_path_matches(const char *path, struct perms_ *dp)
 {
     if (dp->prefix) {
@@ -189,6 +147,44 @@
     return false;
 }
 
+static bool match_subsystem(perms_* dp, const char* pattern,
+                            const char* path, const char* subsystem) {
+    if (!pattern || !subsystem || strstr(dp->name, subsystem) == NULL) {
+        return false;
+    }
+
+    std::string subsys_path = android::base::StringPrintf(pattern, subsystem, basename(path));
+    return perm_path_matches(subsys_path.c_str(), dp);
+}
+
+static void fixup_sys_perms(const char* upath, const char* subsystem) {
+    // upaths omit the "/sys" that paths in this list
+    // contain, so we prepend it...
+    std::string path = std::string(SYSFS_PREFIX) + upath;
+
+    listnode* node;
+    list_for_each(node, &sys_perms) {
+        perms_* dp = &(node_to_item(node, perm_node, plist))->dp;
+        if (match_subsystem(dp, SYSFS_PREFIX "/class/%s/%s", path.c_str(), subsystem)) {
+            ; // matched
+        } else if (match_subsystem(dp, SYSFS_PREFIX "/bus/%s/devices/%s", path.c_str(), subsystem)) {
+            ; // matched
+        } else if (!perm_path_matches(path.c_str(), dp)) {
+            continue;
+        }
+
+        std::string attr_file = path + "/" + dp->attr;
+        INFO("fixup %s %d %d 0%o\n", attr_file.c_str(), dp->uid, dp->gid, dp->perm);
+        chown(attr_file.c_str(), dp->uid, dp->gid);
+        chmod(attr_file.c_str(), dp->perm);
+    }
+
+    if (access(path.c_str(), F_OK) == 0) {
+        INFO("restorecon_recursive: %s\n", path.c_str());
+        restorecon_recursive(path.c_str());
+    }
+}
+
 static mode_t get_device_perm(const char *path, const char **links,
                 unsigned *uid, unsigned *gid)
 {
@@ -747,7 +743,7 @@
 static void handle_device_event(struct uevent *uevent)
 {
     if (!strcmp(uevent->action,"add") || !strcmp(uevent->action, "change") || !strcmp(uevent->action, "online"))
-        fixup_sys_perms(uevent->path);
+        fixup_sys_perms(uevent->path, uevent->subsystem);
 
     if (!strncmp(uevent->subsystem, "block", 5)) {
         handle_block_device_event(uevent);
diff --git a/libbacktrace/GetPss.cpp b/libbacktrace/GetPss.cpp
index b4dc48d..6d750ea 100644
--- a/libbacktrace/GetPss.cpp
+++ b/libbacktrace/GetPss.cpp
@@ -24,7 +24,7 @@
 
 // This is an extremely simplified version of libpagemap.
 
-#define _BITS(x, offset, bits) (((x) >> offset) & ((1LL << (bits)) - 1))
+#define _BITS(x, offset, bits) (((x) >> (offset)) & ((1LL << (bits)) - 1))
 
 #define PAGEMAP_PRESENT(x)     (_BITS(x, 63, 1))
 #define PAGEMAP_SWAPPED(x)     (_BITS(x, 62, 1))
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index df6c6c1..7066c79 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -1420,7 +1420,7 @@
 #if defined(ENABLE_PSS_TESTS)
 #include "GetPss.h"
 
-#define MAX_LEAK_BYTES 32*1024UL
+#define MAX_LEAK_BYTES (32*1024UL)
 
 void CheckForLeak(pid_t pid, pid_t tid) {
   // Do a few runs to get the PSS stable.
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index b5780b8..822a7d3 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -19,6 +19,7 @@
 libcutils_common_sources := \
         config_utils.c \
         fs_config.c \
+        canned_fs_config.c \
         hashmap.c \
         iosched_policy.c \
         load_file.c \
diff --git a/libcutils/ashmem-host.c b/libcutils/ashmem-host.c
index c85f06b..1f9f753 100644
--- a/libcutils/ashmem-host.c
+++ b/libcutils/ashmem-host.c
@@ -62,12 +62,12 @@
 
 int ashmem_pin_region(int fd __unused, size_t offset __unused, size_t len __unused)
 {
-    return ASHMEM_NOT_PURGED;
+    return 0 /*ASHMEM_NOT_PURGED*/;
 }
 
 int ashmem_unpin_region(int fd __unused, size_t offset __unused, size_t len __unused)
 {
-    return ASHMEM_IS_UNPINNED;
+    return 0 /*ASHMEM_IS_UNPINNED*/;
 }
 
 int ashmem_get_size_region(int fd)
diff --git a/libcutils/canned_fs_config.c b/libcutils/canned_fs_config.c
new file mode 100644
index 0000000..5800857
--- /dev/null
+++ b/libcutils/canned_fs_config.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2014 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 <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include <private/android_filesystem_config.h>
+#include <private/canned_fs_config.h>
+
+typedef struct {
+	const char* path;
+	unsigned uid;
+	unsigned gid;
+	unsigned mode;
+	uint64_t capabilities;
+} Path;
+
+static Path* canned_data = NULL;
+static int canned_alloc = 0;
+static int canned_used = 0;
+
+static int path_compare(const void* a, const void* b) {
+	return strcmp(((Path*)a)->path, ((Path*)b)->path);
+}
+
+int load_canned_fs_config(const char* fn) {
+	FILE* f = fopen(fn, "r");
+	if (f == NULL) {
+		fprintf(stderr, "failed to open %s: %s\n", fn, strerror(errno));
+		return -1;
+	}
+
+	char line[PATH_MAX + 200];
+	while (fgets(line, sizeof(line), f)) {
+		while (canned_used >= canned_alloc) {
+			canned_alloc = (canned_alloc+1) * 2;
+			canned_data = (Path*) realloc(canned_data, canned_alloc * sizeof(Path));
+		}
+		Path* p = canned_data + canned_used;
+		p->path = strdup(strtok(line, " "));
+		p->uid = atoi(strtok(NULL, " "));
+		p->gid = atoi(strtok(NULL, " "));
+		p->mode = strtol(strtok(NULL, " "), NULL, 8);   // mode is in octal
+		p->capabilities = 0;
+
+		char* token = NULL;
+		do {
+			token = strtok(NULL, " ");
+			if (token && strncmp(token, "capabilities=", 13) == 0) {
+				p->capabilities = strtoll(token+13, NULL, 0);
+				break;
+			}
+		} while (token);
+
+		canned_used++;
+	}
+
+	fclose(f);
+
+	qsort(canned_data, canned_used, sizeof(Path), path_compare);
+	printf("loaded %d fs_config entries\n", canned_used);
+
+	return 0;
+}
+
+static const int kDebugCannedFsConfig = 0;
+
+void canned_fs_config(const char* path, int dir, const char* target_out_path,
+					  unsigned* uid, unsigned* gid, unsigned* mode, uint64_t* capabilities) {
+	Path key;
+    key.path = path;
+    if (path[0] == '/')
+        key.path++;   // canned paths lack the leading '/'
+	Path* p = (Path*) bsearch(&key, canned_data, canned_used, sizeof(Path), path_compare);
+	if (p == NULL) {
+		fprintf(stderr, "failed to find [%s] in canned fs_config\n", path);
+		exit(1);
+	}
+	*uid = p->uid;
+	*gid = p->gid;
+	*mode = p->mode;
+	*capabilities = p->capabilities;
+
+	if (kDebugCannedFsConfig) {
+		// for debugging, run the built-in fs_config and compare the results.
+
+		unsigned c_uid, c_gid, c_mode;
+		uint64_t c_capabilities;
+		fs_config(path, dir, target_out_path, &c_uid, &c_gid, &c_mode, &c_capabilities);
+
+		if (c_uid != *uid) printf("%s uid %d %d\n", path, *uid, c_uid);
+		if (c_gid != *gid) printf("%s gid %d %d\n", path, *gid, c_gid);
+		if (c_mode != *mode) printf("%s mode 0%o 0%o\n", path, *mode, c_mode);
+		if (c_capabilities != *capabilities)
+			printf("%s capabilities %" PRIx64 " %" PRIx64 "\n",
+				path,
+				*capabilities,
+				c_capabilities);
+        }
+}
diff --git a/libion/kernel-headers/linux/ion.h b/libion/kernel-headers/linux/ion.h
index 5af39d0..3c28080 100644
--- a/libion/kernel-headers/linux/ion.h
+++ b/libion/kernel-headers/linux/ion.h
@@ -38,7 +38,7 @@
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT)
 #define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA)
-#define ION_NUM_HEAP_IDS sizeof(unsigned int) * 8
+#define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8)
 #define ION_FLAG_CACHED 1
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define ION_FLAG_CACHED_NEEDS_SYNC 2
diff --git a/liblog/config_read.h b/liblog/config_read.h
index 67f4c20..49a3b75 100644
--- a/liblog/config_read.h
+++ b/liblog/config_read.h
@@ -27,21 +27,21 @@
 extern LIBLOG_HIDDEN struct listnode __android_log_persist_read;
 
 #define read_transport_for_each(transp, transports)                         \
-    for (transp = node_to_item((transports)->next,                          \
+    for ((transp) = node_to_item((transports)->next,                        \
                                struct android_log_transport_read, node);    \
-         (transp != node_to_item(transports,                                \
+         ((transp) != node_to_item(transports,                              \
                                  struct android_log_transport_read, node)); \
-         transp = node_to_item(transp->node.next,                           \
+         (transp) = node_to_item((transp)->node.next,                       \
                                struct android_log_transport_read, node))    \
 
 #define read_transport_for_each_safe(transp, n, transports)                 \
-    for (transp = node_to_item((transports)->next,                          \
+    for ((transp) = node_to_item((transports)->next,                        \
                                struct android_log_transport_read, node),    \
-         n = transp->node.next;                                             \
-         (transp != node_to_item(transports,                                \
+         (n) = (transp)->node.next;                                         \
+         ((transp) != node_to_item(transports,                              \
                                  struct android_log_transport_read, node)); \
-         transp = node_to_item(n, struct android_log_transport_read, node), \
-         n = transp->node.next)
+         (transp) = node_to_item(n, struct android_log_transport_read, node), \
+         (n) = (transp)->node.next)
 
 LIBLOG_HIDDEN void __android_log_config_read();
 
diff --git a/liblog/config_write.h b/liblog/config_write.h
index 3a02a4e..3b01a9a 100644
--- a/liblog/config_write.h
+++ b/liblog/config_write.h
@@ -27,21 +27,21 @@
 extern LIBLOG_HIDDEN struct listnode __android_log_persist_write;
 
 #define write_transport_for_each(transp, transports)                         \
-    for (transp = node_to_item((transports)->next,                           \
-                               struct android_log_transport_write, node);    \
-         (transp != node_to_item(transports,                                 \
+    for ((transp) = node_to_item((transports)->next,                         \
+                                 struct android_log_transport_write, node);  \
+         ((transp) != node_to_item(transports,                               \
                                  struct android_log_transport_write, node)); \
-         transp = node_to_item(transp->node.next,                            \
-                               struct android_log_transport_write, node))    \
+         (transp) = node_to_item((transp)->node.next,                        \
+                                 struct android_log_transport_write, node))  \
 
 #define write_transport_for_each_safe(transp, n, transports)                 \
-    for (transp = node_to_item((transports)->next,                           \
-                               struct android_log_transport_write, node),    \
-         n = transp->node.next;                                              \
-         (transp != node_to_item(transports,                                 \
-                                 struct android_log_transport_write, node)); \
-         transp = node_to_item(n, struct android_log_transport_write, node), \
-         n = transp->node.next)
+    for ((transp) = node_to_item((transports)->next,                         \
+                                 struct android_log_transport_write, node),  \
+         (n) = (transp)->node.next;                                          \
+         ((transp) != node_to_item(transports,                               \
+                                   struct android_log_transport_write, node)); \
+         (transp) = node_to_item(n, struct android_log_transport_write, node), \
+         (n) = (transp)->node.next)
 
 LIBLOG_HIDDEN void __android_log_config_write();
 
diff --git a/liblog/logger.h b/liblog/logger.h
index c727f29..5087256 100644
--- a/liblog/logger.h
+++ b/liblog/logger.h
@@ -124,23 +124,23 @@
 
 /* assumes caller has structures read-locked, single threaded, or fenced */
 #define transport_context_for_each(transp, logger_list)              \
-  for (transp = node_to_item((logger_list)->transport.next,          \
+  for ((transp) = node_to_item((logger_list)->transport.next,        \
                              struct android_log_transport_context,   \
                              node);                                  \
-       (transp != node_to_item(&(logger_list)->transport,            \
+       ((transp) != node_to_item(&(logger_list)->transport,          \
                                struct android_log_transport_context, \
                                node)) &&                             \
-           (transp->parent == (logger_list));                        \
-       transp = node_to_item(transp->node.next,                      \
+           ((transp)->parent == (logger_list));                      \
+       (transp) = node_to_item((transp)->node.next,                  \
                              struct android_log_transport_context, node))
 
 #define logger_for_each(logp, logger_list)                          \
-    for (logp = node_to_item((logger_list)->logger.next,            \
+    for ((logp) = node_to_item((logger_list)->logger.next,          \
                              struct android_log_logger, node);      \
-         (logp != node_to_item(&(logger_list)->logger,              \
+         ((logp) != node_to_item(&(logger_list)->logger,            \
                                struct android_log_logger, node)) && \
-             (logp->parent == (logger_list));                       \
-         logp = node_to_item((logp)->node.next,                     \
+             ((logp)->parent == (logger_list));                     \
+         (logp) = node_to_item((logp)->node.next,                   \
                              struct android_log_logger, node))
 
 /* OS specific dribs and drabs */
diff --git a/liblog/logger_read.c b/liblog/logger_read.c
index 0d6ba08..00157b7 100644
--- a/liblog/logger_read.c
+++ b/liblog/logger_read.c
@@ -125,7 +125,7 @@
     ssize_t ret = -EINVAL;                                                    \
     struct android_log_transport_context *transp;                             \
     struct android_log_logger *logger_internal =                              \
-            (struct android_log_logger *)logger;                              \
+            (struct android_log_logger *)(logger);                            \
                                                                               \
     if (!logger_internal) {                                                   \
         return ret;                                                           \
@@ -186,7 +186,7 @@
 #define LOGGER_LIST_FUNCTION(logger_list, def, func, args...)                 \
     struct android_log_transport_context *transp;                             \
     struct android_log_logger_list *logger_list_internal =                    \
-            (struct android_log_logger_list *)logger_list;                    \
+            (struct android_log_logger_list *)(logger_list);                  \
                                                                               \
     ssize_t ret = init_transport_context(logger_list_internal);               \
     if (ret < 0) {                                                            \
@@ -341,6 +341,43 @@
     return logger_list;
 }
 
+/* Validate log_msg packet, read function has already been null checked */
+static int android_transport_read(struct android_log_logger_list *logger_list,
+                                  struct android_log_transport_context *transp,
+                                  struct log_msg *log_msg)
+{
+    int ret = (*transp->transport->read)(logger_list, transp, log_msg);
+
+    if (ret > (int)sizeof(*log_msg)) {
+        ret = sizeof(*log_msg);
+    }
+
+    transp->ret = ret;
+
+    /* propagate errors, or make sure len & hdr_size members visible */
+    if (ret < (int)(sizeof(log_msg->entry.len) +
+                    sizeof(log_msg->entry.hdr_size))) {
+        if (ret >= (int)sizeof(log_msg->entry.len)) {
+            log_msg->entry.len = 0;
+        }
+        return ret;
+    }
+
+    /* hdr_size correction (logger_entry -> logger_entry_v2+ conversion) */
+    if (log_msg->entry_v2.hdr_size == 0) {
+        log_msg->entry_v2.hdr_size = sizeof(struct logger_entry);
+    }
+
+    /* len validation */
+    if (ret <= log_msg->entry_v2.hdr_size) {
+        log_msg->entry.len = 0;
+    } else {
+        log_msg->entry.len = ret - log_msg->entry_v2.hdr_size;
+    }
+
+    return ret;
+}
+
 /* Read from the selected logs */
 LIBLOG_ABI_PUBLIC int android_logger_list_read(struct logger_list *logger_list,
                                                struct log_msg *log_msg)
@@ -378,7 +415,7 @@
                     } else if ((logger_list_internal->mode &
                                 ANDROID_LOG_NONBLOCK) ||
                             !transp->transport->poll) {
-                        retval = transp->ret = (*transp->transport->read)(
+                        retval = android_transport_read(
                                 logger_list_internal,
                                 transp,
                                 &transp->logMsg);
@@ -397,7 +434,7 @@
                             }
                             retval = transp->ret = pollval;
                         } else if (pollval > 0) {
-                            retval = transp->ret = (*transp->transport->read)(
+                            retval = android_transport_read(
                                     logger_list_internal,
                                     transp,
                                     &transp->logMsg);
@@ -434,16 +471,22 @@
         if (!oldest) {
             return ret;
         }
-        memcpy(log_msg, &oldest->logMsg, oldest->logMsg.entry.len +
-                    (oldest->logMsg.entry.hdr_size ?
-                        oldest->logMsg.entry.hdr_size :
-                        sizeof(struct logger_entry)));
+        // ret is a positive value less than sizeof(struct log_msg)
+        ret = oldest->ret;
+        if (ret < oldest->logMsg.entry.hdr_size) {
+            // zero truncated header fields.
+            memset(log_msg, 0,
+                   (oldest->logMsg.entry.hdr_size > sizeof(oldest->logMsg) ?
+                       sizeof(oldest->logMsg) :
+                       oldest->logMsg.entry.hdr_size));
+        }
+        memcpy(log_msg, &oldest->logMsg, ret);
         oldest->logMsg.entry.len = 0; /* Mark it as copied */
-        return oldest->ret;
+        return ret;
     }
 
     /* if only one, no need to copy into transport_context and merge-sort */
-    return (transp->transport->read)(logger_list_internal, transp, log_msg);
+    return android_transport_read(logger_list_internal, transp, log_msg);
 }
 
 /* Close all the logs */
diff --git a/liblog/tests/benchmark.h b/liblog/tests/benchmark.h
index 7f96e6d..57b3748 100644
--- a/liblog/tests/benchmark.h
+++ b/liblog/tests/benchmark.h
@@ -141,7 +141,7 @@
 void StopBenchmarkTiming(uint64_t);
 
 #define BENCHMARK(f) \
-    static ::testing::Benchmark* _benchmark_##f __attribute__((unused)) = \
-        (::testing::Benchmark*)::testing::BenchmarkFactory(#f, f)
+    static ::testing::Benchmark* _benchmark_##f __attribute__((unused)) = /* NOLINT */ \
+        (::testing::Benchmark*)::testing::BenchmarkFactory(#f, f) /* NOLINT */
 
 #endif // BIONIC_BENCHMARK_H_
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 1a7d4aa..df2c766 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -1368,6 +1368,7 @@
             snprintf(key, sizeof(key), "%s%s", log_namespace, tag);
             fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
                     i, j, key, buf);
+            usleep(20000);
             property_set(key, buf);
             bool android_log_is_loggable = __android_log_is_loggable(
                 levels[i].level, tag, ANDROID_LOG_DEBUG);
@@ -1393,6 +1394,7 @@
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
             }
+            usleep(20000);
             property_set(key, "");
 
             fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
@@ -1422,6 +1424,7 @@
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
             }
+            usleep(20000);
             property_set(key + base_offset, "");
 
             strcpy(key, log_namespace);
@@ -1453,6 +1456,7 @@
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
             }
+            usleep(20000);
             property_set(key, "");
 
             fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
@@ -1482,6 +1486,7 @@
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
             }
+            usleep(20000);
             property_set(key + base_offset, "");
         }
     }
@@ -1489,6 +1494,7 @@
     // All combinations of level and tag properties, but with global set to INFO
     strcpy(key, log_namespace);
     key[sizeof(log_namespace) - 2] = '\0';
+    usleep(20000);
     property_set(key, "I");
     snprintf(key, sizeof(key), "%s%s", log_namespace, tag);
     for(size_t i = 0; i < (sizeof(levels) / sizeof(levels[0])); ++i) {
@@ -1502,6 +1508,7 @@
 
             fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
                     i, j, key, buf);
+            usleep(20000);
             property_set(key, buf);
             bool android_log_is_loggable = __android_log_is_loggable(
                 levels[i].level, tag, ANDROID_LOG_DEBUG);
@@ -1527,6 +1534,7 @@
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
             }
+            usleep(20000);
             property_set(key, "");
 
             fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
@@ -1556,12 +1564,14 @@
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
             }
+            usleep(20000);
             property_set(key + base_offset, "");
         }
     }
 
     // reset parms
     snprintf(key, sizeof(key), "%s%s", log_namespace, tag);
+    usleep(20000);
     property_set(key, hold[0]);
     property_set(key + base_offset, hold[1]);
     strcpy(key, log_namespace);
diff --git a/libmemtrack/memtrack.c b/libmemtrack/memtrack.c
index 21d9ebd..b528214 100644
--- a/libmemtrack/memtrack.c
+++ b/libmemtrack/memtrack.c
@@ -26,7 +26,7 @@
 
 #include <hardware/memtrack.h>
 
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
 
 static const memtrack_module_t *module;
 
diff --git a/libmemunreachable/tests/LeakFolding_test.cpp b/libmemunreachable/tests/LeakFolding_test.cpp
index 879a3a0..e85df5f 100644
--- a/libmemunreachable/tests/LeakFolding_test.cpp
+++ b/libmemunreachable/tests/LeakFolding_test.cpp
@@ -37,10 +37,10 @@
   Heap heap_;
 };
 
-#define buffer_begin(buffer) reinterpret_cast<uintptr_t>(&buffer[0])
-#define buffer_end(buffer) (reinterpret_cast<uintptr_t>(&buffer[0]) + sizeof(buffer))
+#define buffer_begin(buffer) reinterpret_cast<uintptr_t>(&(buffer)[0])
+#define buffer_end(buffer) (reinterpret_cast<uintptr_t>(&(buffer)[0]) + sizeof(buffer))
 #define ALLOCATION(heap_walker, buffer) \
-  ASSERT_EQ(true, heap_walker.Allocation(buffer_begin(buffer), buffer_end(buffer)))
+  ASSERT_EQ(true, (heap_walker).Allocation(buffer_begin(buffer), buffer_end(buffer)))
 
 TEST_F(LeakFoldingTest, one) {
   void* buffer1[1] = {nullptr};
diff --git a/libnativeloader/dlext_namespaces.h b/libnativeloader/dlext_namespaces.h
new file mode 100644
index 0000000..13a44e2
--- /dev/null
+++ b/libnativeloader/dlext_namespaces.h
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#ifndef __ANDROID_DLEXT_NAMESPACES_H__
+#define __ANDROID_DLEXT_NAMESPACES_H__
+
+#include <android/dlext.h>
+
+__BEGIN_DECLS
+
+/*
+ * Initializes public and anonymous namespaces. The public_ns_sonames is the list of sonames
+ * to be included into public namespace separated by colon. Example: "libc.so:libm.so:libdl.so".
+ * The libraries in this list should be loaded prior to this call.
+ *
+ * The anon_ns_library_path is the search path for anonymous namespace. The anonymous namespace
+ * is used in the case when linker cannot identify the caller of dlopen/dlsym. This happens
+ * for the code not loaded by dynamic linker; for example calls from the mono-compiled code.
+ */
+extern bool android_init_namespaces(const char* public_ns_sonames,
+                                    const char* anon_ns_library_path);
+
+
+enum {
+  /* A regular namespace is the namespace with a custom search path that does
+   * not impose any restrictions on the location of native libraries.
+   */
+  ANDROID_NAMESPACE_TYPE_REGULAR = 0,
+
+  /* An isolated namespace requires all the libraries to be on the search path
+   * or under permitted_when_isolated_path. The search path is the union of
+   * ld_library_path and default_library_path.
+   */
+  ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
+
+  /* The shared namespace clones the list of libraries of the caller namespace upon creation
+   * which means that they are shared between namespaces - the caller namespace and the new one
+   * will use the same copy of a library if it was loaded prior to android_create_namespace call.
+   *
+   * Note that libraries loaded after the namespace is created will not be shared.
+   *
+   * Shared namespaces can be isolated or regular. Note that they do not inherit the search path nor
+   * permitted_path from the caller's namespace.
+   */
+  ANDROID_NAMESPACE_TYPE_SHARED = 2,
+  ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED |
+                                           ANDROID_NAMESPACE_TYPE_ISOLATED,
+};
+
+/*
+ * Creates new linker namespace.
+ * ld_library_path and default_library_path represent the search path
+ * for the libraries in the namespace.
+ *
+ * The libraries in the namespace are searched by folowing order:
+ * 1. ld_library_path (Think of this as namespace-local LD_LIBRARY_PATH)
+ * 2. In directories specified by DT_RUNPATH of the "needed by" binary.
+ * 3. deault_library_path (This of this as namespace-local default library path)
+ *
+ * When type is ANDROID_NAMESPACE_TYPE_ISOLATED the resulting namespace requires all of
+ * the libraries to be on the search path or under the permitted_when_isolated_path;
+ * the search_path is ld_library_path:default_library_path. Note that the
+ * permitted_when_isolated_path path is not part of the search_path and
+ * does not affect the search order. It is a way to allow loading libraries from specific
+ * locations when using absolute path.
+ * If a library or any of its dependencies are outside of the permitted_when_isolated_path
+ * and search_path, and it is not part of the public namespace dlopen will fail.
+ */
+extern struct android_namespace_t* android_create_namespace(const char* name,
+                                                            const char* ld_library_path,
+                                                            const char* default_library_path,
+                                                            uint64_t type,
+                                                            const char* permitted_when_isolated_path,
+                                                            android_namespace_t* parent);
+
+__END_DECLS
+
+#endif /* __ANDROID_DLEXT_NAMESPACES_H__ */
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 33d5b62..713a59d 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -19,7 +19,7 @@
 
 #include <dlfcn.h>
 #ifdef __ANDROID__
-#include <android/dlext.h>
+#include "dlext_namespaces.h"
 #include "cutils/properties.h"
 #include "log/log.h"
 #endif
@@ -39,6 +39,11 @@
 static constexpr const char* kPublicNativeLibrariesSystemConfigPathFromRoot = "/etc/public.libraries.txt";
 static constexpr const char* kPublicNativeLibrariesVendorConfig = "/vendor/etc/public.libraries.txt";
 
+// (http://b/27588281) This is a workaround for apps using custom classloaders and calling
+// System.load() with an absolute path which is outside of the classloader library search path.
+// This list includes all directories app is allowed to access this way.
+static constexpr const char* kWhitelistedDirectories = "/data:/mnt/expand";
+
 static bool is_debuggable() {
   char debuggable[PROP_VALUE_MAX];
   property_get("ro.debuggable", debuggable, "0");
@@ -61,10 +66,19 @@
       library_path = library_path_utf_chars.c_str();
     }
 
-    std::string permitted_path;
+    // (http://b/27588281) This is a workaround for apps using custom
+    // classloaders and calling System.load() with an absolute path which
+    // is outside of the classloader library search path.
+    //
+    // This part effectively allows such a classloader to access anything
+    // under /data and /mnt/expand
+    std::string permitted_path = kWhitelistedDirectories;
+
     if (java_permitted_path != nullptr) {
       ScopedUtfChars path(env, java_permitted_path);
-      permitted_path = path.c_str();
+      if (path.c_str() != nullptr && path.size() > 0) {
+        permitted_path = permitted_path + ":" + path.c_str();
+      }
     }
 
     if (!initialized_ && !InitPublicNamespace(library_path.c_str())) {
@@ -81,13 +95,14 @@
       namespace_type |= ANDROID_NAMESPACE_TYPE_SHARED;
     }
 
+    android_namespace_t* parent_ns = FindParentNamespaceByClassLoader(env, class_loader);
+
     ns = android_create_namespace("classloader-namespace",
                                   nullptr,
                                   library_path.c_str(),
                                   namespace_type,
-                                  java_permitted_path != nullptr ?
-                                      permitted_path.c_str() :
-                                      nullptr);
+                                  permitted_path.c_str(),
+                                  parent_ns);
 
     if (ns != nullptr) {
       namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), ns));
@@ -105,6 +120,13 @@
   }
 
   void Initialize() {
+    // Once public namespace is initialized there is no
+    // point in running this code - it will have no effect
+    // on the current list of public libraries.
+    if (initialized_) {
+      return;
+    }
+
     std::vector<std::string> sonames;
     const char* android_root_env = getenv("ANDROID_ROOT");
     std::string root_dir = android_root_env != nullptr ? android_root_env : "/system";
@@ -181,6 +203,29 @@
     return initialized_;
   }
 
+  jobject GetParentClassLoader(JNIEnv* env, jobject class_loader) {
+    jclass class_loader_class = env->FindClass("java/lang/ClassLoader");
+    jmethodID get_parent = env->GetMethodID(class_loader_class,
+                                            "getParent",
+                                            "()Ljava/lang/ClassLoader;");
+
+    return env->CallObjectMethod(class_loader, get_parent);
+  }
+
+  android_namespace_t* FindParentNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
+    jobject parent_class_loader = GetParentClassLoader(env, class_loader);
+
+    while (parent_class_loader != nullptr) {
+      android_namespace_t* ns = FindNamespaceByClassLoader(env, parent_class_loader);
+      if (ns != nullptr) {
+        return ns;
+      }
+
+      parent_class_loader = GetParentClassLoader(env, parent_class_loader);
+    }
+    return nullptr;
+  }
+
   bool initialized_;
   std::vector<std::pair<jweak, android_namespace_t*>> namespaces_;
   std::string public_libraries_;
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index c6b9fe4..56e1d59 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -243,12 +243,8 @@
     property_set(result_prop_name, "");
 
     /* Start the daemon and wait until it's ready */
-    if (property_get(HOSTNAME_PROP_NAME, prop_value, NULL) && (prop_value[0] != '\0'))
-        snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:-f %s -h %s %s", DAEMON_NAME,
-                 p2p_interface, DHCP_CONFIG_PATH, prop_value, interface);
-    else
-        snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:-f %s %s", DAEMON_NAME,
-                 p2p_interface, DHCP_CONFIG_PATH, interface);
+    snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s", DAEMON_NAME,
+            p2p_interface);
     memset(prop_value, '\0', PROPERTY_VALUE_MAX);
     property_set(ctrl_prop, daemon_cmd);
     if (wait_for_property(daemon_prop_name, desired_status, 10) < 0) {
@@ -288,7 +284,8 @@
             DAEMON_PROP_NAME,
             p2p_interface);
 
-    snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s", DAEMON_NAME, p2p_interface);
+    snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s", DAEMON_NAME,
+            p2p_interface);
 
     /* Stop the daemon and wait until it's reported to be stopped */
     property_set(ctrl_prop, daemon_cmd);
@@ -317,7 +314,8 @@
             DAEMON_PROP_NAME,
             p2p_interface);
 
-    snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s", DAEMON_NAME, p2p_interface);
+    snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s", DAEMON_NAME,
+            p2p_interface);
 
     /* Stop the daemon and wait until it's reported to be stopped */
     property_set(ctrl_prop, daemon_cmd);
@@ -357,8 +355,8 @@
     property_set(result_prop_name, "");
 
     /* Start the renew daemon and wait until it's ready */
-    snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:%s", DAEMON_NAME_RENEW,
-            p2p_interface, interface);
+    snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s", DAEMON_NAME_RENEW,
+            p2p_interface);
     memset(prop_value, '\0', PROPERTY_VALUE_MAX);
     property_set(ctrl_prop, daemon_cmd);
 
diff --git a/libpixelflinger/scanline.cpp b/libpixelflinger/scanline.cpp
index f48e1d0..aa18360 100644
--- a/libpixelflinger/scanline.cpp
+++ b/libpixelflinger/scanline.cpp
@@ -26,10 +26,6 @@
 #include <cutils/memory.h>
 #include <cutils/log.h>
 
-#ifdef __arm__
-#include <machine/cpu-features.h>
-#endif
-
 #include "buffer.h"
 #include "scanline.h"
 
diff --git a/libsparse/output_file.c b/libsparse/output_file.c
index cd30800..d284736 100644
--- a/libsparse/output_file.c
+++ b/libsparse/output_file.c
@@ -57,7 +57,7 @@
 #define CHUNK_HEADER_LEN (sizeof(chunk_header_t))
 
 #define container_of(inner, outer_t, elem) \
-	((outer_t *)((char *)inner - offsetof(outer_t, elem)))
+	((outer_t *)((char *)(inner) - offsetof(outer_t, elem)))
 
 struct output_file_ops {
 	int (*open)(struct output_file *, int fd);
diff --git a/libutils/SystemClock.cpp b/libutils/SystemClock.cpp
index c5ae327..965e32c 100644
--- a/libutils/SystemClock.cpp
+++ b/libutils/SystemClock.cpp
@@ -19,18 +19,13 @@
  * System clock functions.
  */
 
-#if defined(__ANDROID__)
-#include <linux/ioctl.h>
-#include <linux/rtc.h>
-#include <utils/Atomic.h>
-#include <linux/android_alarm.h>
-#endif
-
 #include <sys/time.h>
 #include <limits.h>
 #include <fcntl.h>
 #include <string.h>
+#include <errno.h>
 
+#include <cutils/compiler.h>
 #include <utils/SystemClock.h>
 #include <utils/Timers.h>
 
@@ -61,30 +56,16 @@
  */
 int64_t elapsedRealtimeNano()
 {
-#if defined(__ANDROID__)
-    static int s_fd = -1;
-
-    if (s_fd == -1) {
-        int fd = open("/dev/alarm", O_RDONLY);
-        if (android_atomic_cmpxchg(-1, fd, &s_fd)) {
-            close(fd);
-        }
-    }
-
+#if defined(__linux__)
     struct timespec ts;
-    if (ioctl(s_fd, ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts) == 0) {
-        return seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
+    int err = clock_gettime(CLOCK_BOOTTIME, &ts);
+    if (CC_UNLIKELY(err)) {
+        // This should never happen, but just in case ...
+        ALOGE("clock_gettime(CLOCK_BOOTTIME) failed: %s", strerror(errno));
+        return 0;
     }
 
-    // /dev/alarm doesn't exist, fallback to CLOCK_BOOTTIME
-    if (clock_gettime(CLOCK_BOOTTIME, &ts) == 0) {
-        return seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
-    }
-
-    // XXX: there was an error, probably because the driver didn't
-    // exist ... this should return
-    // a real error, like an exception!
-    return systemTime(SYSTEM_TIME_MONOTONIC);
+    return seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
 #else
     return systemTime(SYSTEM_TIME_MONOTONIC);
 #endif
diff --git a/libutils/tests/Android.mk b/libutils/tests/Android.mk
index 8f07f1a..21fe19c 100644
--- a/libutils/tests/Android.mk
+++ b/libutils/tests/Android.mk
@@ -28,6 +28,7 @@
     LruCache_test.cpp \
     String8_test.cpp \
     StrongPointer_test.cpp \
+    SystemClock_test.cpp \
     Unicode_test.cpp \
     Vector_test.cpp \
 
diff --git a/libutils/tests/SystemClock_test.cpp b/libutils/tests/SystemClock_test.cpp
new file mode 100644
index 0000000..5ad060b
--- /dev/null
+++ b/libutils/tests/SystemClock_test.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+#include <unistd.h>
+#include <utils/SystemClock.h>
+
+#include <gtest/gtest.h>
+
+static const auto MS_IN_NS = 1000000;
+
+static const int64_t SLEEP_MS = 500;
+static const int64_t SLEEP_NS = SLEEP_MS * MS_IN_NS;
+// Conservatively assume that we might be descheduled for up to 50 ms
+static const int64_t SLACK_MS = 50;
+static const int64_t SLACK_NS = SLACK_MS * MS_IN_NS;
+
+TEST(SystemClock, SystemClock) {
+    auto startUptimeMs = android::uptimeMillis();
+    auto startRealtimeMs = android::elapsedRealtime();
+    auto startRealtimeNs = android::elapsedRealtimeNano();
+
+    ASSERT_GT(startUptimeMs, 0)
+            << "uptimeMillis() reported an impossible uptime";
+    ASSERT_GE(startRealtimeMs, startUptimeMs)
+            << "elapsedRealtime() thinks we've suspended for negative time";
+    ASSERT_GE(startRealtimeNs, startUptimeMs * MS_IN_NS)
+            << "elapsedRealtimeNano() thinks we've suspended for negative time";
+
+    ASSERT_GE(startRealtimeNs, startRealtimeMs * MS_IN_NS)
+            << "elapsedRealtime() and elapsedRealtimeNano() are inconsistent";
+    ASSERT_LT(startRealtimeNs, (startRealtimeMs + SLACK_MS) * MS_IN_NS)
+            << "elapsedRealtime() and elapsedRealtimeNano() are inconsistent";
+
+    timespec ts;
+    ts.tv_sec = 0;
+    ts.tv_nsec = SLEEP_MS * MS_IN_NS;
+    auto nanosleepErr = TEMP_FAILURE_RETRY(nanosleep(&ts, nullptr));
+    ASSERT_EQ(nanosleepErr, 0) << "nanosleep() failed: " << strerror(errno);
+
+    auto endUptimeMs = android::uptimeMillis();
+    auto endRealtimeMs = android::elapsedRealtime();
+    auto endRealtimeNs = android::elapsedRealtimeNano();
+
+    EXPECT_GE(endUptimeMs - startUptimeMs, SLEEP_MS)
+            << "uptimeMillis() advanced too little after nanosleep()";
+    EXPECT_LT(endUptimeMs - startUptimeMs, SLEEP_MS + SLACK_MS)
+            << "uptimeMillis() advanced too much after nanosleep()";
+    EXPECT_GE(endRealtimeMs - startRealtimeMs, SLEEP_MS)
+            << "elapsedRealtime() advanced too little after nanosleep()";
+    EXPECT_LT(endRealtimeMs - startRealtimeMs, SLEEP_MS + SLACK_MS)
+            << "elapsedRealtime() advanced too much after nanosleep()";
+    EXPECT_GE(endRealtimeNs - startRealtimeNs, SLEEP_NS)
+            << "elapsedRealtimeNano() advanced too little after nanosleep()";
+    EXPECT_LT(endRealtimeNs - startRealtimeNs, SLEEP_NS + SLACK_NS)
+            << "elapsedRealtimeNano() advanced too much after nanosleep()";
+
+    EXPECT_GE(endRealtimeNs, endRealtimeMs * MS_IN_NS)
+            << "elapsedRealtime() and elapsedRealtimeNano() are inconsistent after nanosleep()";
+    EXPECT_LT(endRealtimeNs, (endRealtimeMs + SLACK_MS) * MS_IN_NS)
+            << "elapsedRealtime() and elapsedRealtimeNano() are inconsistent after nanosleep()";
+}
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 6f7d264..b32c27d 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -33,7 +33,7 @@
 #include "LogUtils.h"
 
 #define log_id_for_each(i) \
-    for (log_id_t i = LOG_ID_MIN; i < LOG_ID_MAX; i = (log_id_t) (i + 1))
+    for (log_id_t i = LOG_ID_MIN; (i) < LOG_ID_MAX; (i) = (log_id_t) ((i) + 1))
 
 class LogStatistics;
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index aa32343..ef70bf2 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -140,7 +140,6 @@
     chown system system /dev/cpuctl
     chown system system /dev/cpuctl/tasks
     chmod 0666 /dev/cpuctl/tasks
-    write /dev/cpuctl/cpu.shares 1024
     write /dev/cpuctl/cpu.rt_runtime_us 800000
     write /dev/cpuctl/cpu.rt_period_us 1000000
 
diff --git a/rootdir/init.usb.configfs.rc b/rootdir/init.usb.configfs.rc
index 186384b..e19b058 100644
--- a/rootdir/init.usb.configfs.rc
+++ b/rootdir/init.usb.configfs.rc
@@ -1,6 +1,7 @@
 on property:sys.usb.config=none && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/UDC "none"
     stop adbd
+    setprop sys.usb.ffs.ready 0
     write /config/usb_gadget/g1/bDeviceClass 0
     write /config/usb_gadget/g1/bDeviceSubClass 0
     write /config/usb_gadget/g1/bDeviceProtocol 0