Merge "Fix access check"
diff --git a/adb/Android.mk b/adb/Android.mk
index 3512323..1aa3dc1 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -52,6 +52,7 @@
     adb_utils.cpp \
     fdevent.cpp \
     sockets.cpp \
+    socket_spec.cpp \
     transport.cpp \
     transport_local.cpp \
     transport_usb.cpp \
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index 0299be3..18b1492 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -23,12 +23,10 @@
 #include <android-base/strings.h>
 #include <cutils/sockets.h>
 
+#include "socket_spec.h"
 #include "sysdeps.h"
 #include "transport.h"
 
-// Not static because it is used in commandline.c.
-int gListenAll = 0;
-
 // 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.
 //
@@ -120,48 +118,6 @@
     }
 }
 
-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 (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'",
-                                         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;
@@ -230,11 +186,20 @@
 
     std::unique_ptr<alistener> listener(new alistener(local_name, connect_to));
 
-    listener->fd = local_name_to_fd(listener.get(), resolved_tcp_port, error);
+    int resolved = 0;
+    listener->fd = socket_spec_listen(listener->local_name, error, &resolved);
     if (listener->fd < 0) {
         return INSTALL_STATUS_CANNOT_BIND;
     }
 
+    // If the caller requested port 0, update the listener name with the resolved port.
+    if (resolved != 0) {
+        listener->local_name = android::base::StringPrintf("tcp:%d", resolved);
+        if (resolved_tcp_port) {
+            *resolved_tcp_port = resolved;
+        }
+    }
+
     close_on_exec(listener->fd);
     if (listener->connect_to == "*smartsocket*") {
         fdevent_install(&listener->fde, listener->fd, ss_listener_event_func, listener.get());
diff --git a/adb/services.cpp b/adb/services.cpp
index 3b212e9..2207a3e 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -49,6 +49,7 @@
 #include "remount_service.h"
 #include "services.h"
 #include "shell_service.h"
+#include "socket_spec.h"
 #include "sysdeps.h"
 #include "transport.h"
 
@@ -278,36 +279,12 @@
 int service_to_fd(const char* name, const atransport* transport) {
     int ret = -1;
 
-    if(!strncmp(name, "tcp:", 4)) {
-        int port = atoi(name + 4);
-        name = strchr(name + 4, ':');
-        if(name == 0) {
-            std::string error;
-            ret = network_loopback_client(port, SOCK_STREAM, &error);
-            if (ret >= 0)
-                disable_tcp_nagle(ret);
-        } else {
-#if ADB_HOST
-            std::string error;
-            ret = network_connect(name + 1, port, SOCK_STREAM, 0, &error);
-#else
-            return -1;
-#endif
+    if (is_socket_spec(name)) {
+        std::string error;
+        ret = socket_spec_connect(name, &error);
+        if (ret < 0) {
+            LOG(ERROR) << "failed to connect to socket '" << name << "': " << error;
         }
-#if !defined(_WIN32)   /* winsock doesn't implement unix domain sockets */
-    } else if(!strncmp(name, "local:", 6)) {
-        ret = socket_local_client(name + 6,
-                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
-    } else if(!strncmp(name, "localreserved:", 14)) {
-        ret = socket_local_client(name + 14,
-                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
-    } else if(!strncmp(name, "localabstract:", 14)) {
-        ret = socket_local_client(name + 14,
-                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
-    } else if(!strncmp(name, "localfilesystem:", 16)) {
-        ret = socket_local_client(name + 16,
-                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
-#endif
 #if !ADB_HOST
     } else if(!strncmp("dev:", name, 4)) {
         ret = unix_open(name + 4, O_RDWR | O_CLOEXEC);
diff --git a/adb/socket_spec.cpp b/adb/socket_spec.cpp
new file mode 100644
index 0000000..f8bbbb3
--- /dev/null
+++ b/adb/socket_spec.cpp
@@ -0,0 +1,220 @@
+/*
+ * 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 "socket_spec.h"
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <cutils/sockets.h>
+
+#include "adb.h"
+#include "sysdeps.h"
+
+using android::base::StartsWith;
+using android::base::StringPrintf;
+
+#if defined(__linux__)
+#define ADB_LINUX 1
+#else
+#define ADB_LINUX 0
+#endif
+
+#if defined(_WIN32)
+#define ADB_WINDOWS 1
+#else
+#define ADB_WINDOWS 0
+#endif
+
+// Not static because it is used in commandline.c.
+int gListenAll = 0;
+
+struct LocalSocketType {
+    int socket_namespace;
+    bool available;
+};
+
+static auto& kLocalSocketTypes = *new std::unordered_map<std::string, LocalSocketType>({
+#if ADB_HOST
+    { "local", { ANDROID_SOCKET_NAMESPACE_FILESYSTEM, !ADB_WINDOWS } },
+#else
+    { "local", { ANDROID_SOCKET_NAMESPACE_RESERVED, !ADB_WINDOWS } },
+#endif
+
+    { "localreserved", { ANDROID_SOCKET_NAMESPACE_RESERVED, !ADB_HOST } },
+    { "localabstract", { ANDROID_SOCKET_NAMESPACE_ABSTRACT, ADB_LINUX } },
+    { "localfilesystem", { ANDROID_SOCKET_NAMESPACE_FILESYSTEM, !ADB_WINDOWS } },
+});
+
+static bool parse_tcp_spec(const std::string& spec, std::string* hostname, int* port,
+                           std::string* error) {
+    std::vector<std::string> fragments = android::base::Split(spec, ":");
+    if (fragments.size() == 1 || fragments.size() > 3) {
+        *error = StringPrintf("invalid tcp specification: '%s'", spec.c_str());
+        return false;
+    }
+
+    if (fragments[0] != "tcp") {
+        *error = StringPrintf("specification is not tcp: '%s'", spec.c_str());
+        return false;
+    }
+
+    // strtol accepts leading whitespace.
+    const std::string& port_str = fragments.back();
+    if (port_str.empty() || port_str[0] < '0' || port_str[0] > '9') {
+        *error = StringPrintf("invalid port '%s'", port_str.c_str());
+        return false;
+    }
+
+    char* parsed_end;
+    long parsed_port = strtol(port_str.c_str(), &parsed_end, 10);
+    if (*parsed_end != '\0') {
+        *error = StringPrintf("trailing chars in port: '%s'", port_str.c_str());
+        return false;
+    }
+    if (parsed_port > 65535) {
+        *error = StringPrintf("invalid port %ld", parsed_port);
+        return false;
+    }
+
+    // tcp:123 is valid, tcp::123 isn't.
+    if (fragments.size() == 2) {
+        // Empty hostname.
+        if (hostname) {
+            *hostname = "";
+        }
+    } else {
+        if (fragments[1].empty()) {
+            *error = StringPrintf("empty host in '%s'", spec.c_str());
+            return false;
+        }
+        if (hostname) {
+            *hostname = fragments[1];
+        }
+    }
+
+    if (port) {
+        *port = parsed_port;
+    }
+
+    return true;
+}
+
+static bool tcp_host_is_local(const std::string& hostname) {
+    // FIXME
+    return hostname.empty() || hostname == "localhost";
+}
+
+bool is_socket_spec(const std::string& spec) {
+    for (const auto& it : kLocalSocketTypes) {
+        std::string prefix = it.first + ":";
+        if (StartsWith(spec, prefix.c_str())) {
+            return true;
+        }
+    }
+    return StartsWith(spec, "tcp:");
+}
+
+int socket_spec_connect(const std::string& spec, std::string* error) {
+    if (StartsWith(spec, "tcp:")) {
+        std::string hostname;
+        int port;
+        if (!parse_tcp_spec(spec, &hostname, &port, error)) {
+            return -1;
+        }
+
+        int result;
+        if (tcp_host_is_local(hostname)) {
+            result = network_loopback_client(port, SOCK_STREAM, error);
+        } else {
+#if ADB_HOST
+            result = network_connect(hostname, port, SOCK_STREAM, 0, error);
+#else
+            // Disallow arbitrary connections in adbd.
+            *error = "adbd does not support arbitrary tcp connections";
+            return -1;
+#endif
+        }
+
+        if (result >= 0) {
+            disable_tcp_nagle(result);
+        }
+        return result;
+    }
+
+    for (const auto& it : kLocalSocketTypes) {
+        std::string prefix = it.first + ":";
+        if (StartsWith(spec, prefix.c_str())) {
+            if (!it.second.available) {
+                *error = StringPrintf("socket type %s is unavailable on this platform",
+                                      it.first.c_str());
+                return -1;
+            }
+
+            return network_local_client(&spec[prefix.length()], it.second.socket_namespace,
+                                        SOCK_STREAM, error);
+        }
+    }
+
+    *error = StringPrintf("unknown socket specification '%s'", spec.c_str());
+    return -1;
+}
+
+int socket_spec_listen(const std::string& spec, std::string* error, int* resolved_tcp_port) {
+    if (StartsWith(spec, "tcp:")) {
+        std::string hostname;
+        int port;
+        if (!parse_tcp_spec(spec, &hostname, &port, error)) {
+            return -1;
+        }
+
+        int result;
+        if (hostname.empty() && gListenAll) {
+            result = network_inaddr_any_server(port, SOCK_STREAM, error);
+        } else if (tcp_host_is_local(hostname)) {
+            result = network_loopback_server(port, SOCK_STREAM, error);
+        } else {
+            // TODO: Implement me.
+            *error = "listening on specified hostname currently unsupported";
+            return -1;
+        }
+
+        if (result >= 0 && port == 0 && resolved_tcp_port) {
+            *resolved_tcp_port = adb_socket_get_local_port(result);
+        }
+        return result;
+    }
+
+    for (const auto& it : kLocalSocketTypes) {
+        std::string prefix = it.first + ":";
+        if (StartsWith(spec, prefix.c_str())) {
+            if (!it.second.available) {
+                *error = StringPrintf("attempted to listen on unavailable socket type: '%s'",
+                                      spec.c_str());
+                return -1;
+            }
+
+            return network_local_server(&spec[prefix.length()], it.second.socket_namespace,
+                                        SOCK_STREAM, error);
+        }
+    }
+
+    *error = StringPrintf("unknown socket specification '%s'", spec.c_str());
+    return -1;
+}
diff --git a/adb/socket_spec.h b/adb/socket_spec.h
new file mode 100644
index 0000000..69efb07
--- /dev/null
+++ b/adb/socket_spec.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+
+// Returns true if the argument starts with a plausible socket prefix.
+bool is_socket_spec(const std::string& spec);
+
+int socket_spec_connect(const std::string& spec, std::string* error);
+int socket_spec_listen(const std::string& spec, std::string* error,
+                       int* resolved_tcp_port = nullptr);
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 322f992..8d99722 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -277,6 +277,15 @@
 int network_loopback_client(int port, int type, std::string* error);
 int network_loopback_server(int port, int type, std::string* error);
 int network_inaddr_any_server(int port, int type, std::string* error);
+
+inline int network_local_client(const char* name, int namespace_id, int type, std::string* error) {
+    abort();
+}
+
+inline int network_local_server(const char* name, int namespace_id, int type, std::string* error) {
+    abort();
+}
+
 int network_connect(const std::string& host, int port, int type, int timeout,
                     std::string* error);
 
@@ -638,10 +647,12 @@
   return _fd_set_error_str(socket_inaddr_any_server(port, type), error);
 }
 
-inline int network_local_server(const char *name, int namespace_id, int type,
-                                std::string* error) {
-  return _fd_set_error_str(socket_local_server(name, namespace_id, type),
-                           error);
+inline int network_local_client(const char* name, int namespace_id, int type, std::string* error) {
+    return _fd_set_error_str(socket_local_client(name, namespace_id, type), error);
+}
+
+inline int network_local_server(const char* name, int namespace_id, int type, std::string* error) {
+    return _fd_set_error_str(socket_local_server(name, namespace_id, type), error);
 }
 
 inline int network_connect(const std::string& host, int port, int type,
diff --git a/base/include/android-base/macros.h b/base/include/android-base/macros.h
index 299ec35..ee16d02 100644
--- a/base/include/android-base/macros.h
+++ b/base/include/android-base/macros.h
@@ -60,9 +60,18 @@
 // This should be used in the private: declarations for a class
 // that wants to prevent anyone from instantiating it. This is
 // especially useful for classes containing only static methods.
+//
+// When building with C++11 toolchains, just use the language support
+// for explicitly deleted methods.
+#if __cplusplus >= 201103L
+#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+  TypeName() = delete;                           \
+  DISALLOW_COPY_AND_ASSIGN(TypeName)
+#else
 #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
   TypeName();                                    \
   DISALLOW_COPY_AND_ASSIGN(TypeName)
+#endif
 
 // The arraysize(arr) macro returns the # of elements in an array arr.
 // The expression is a compile-time constant, and therefore can be
diff --git a/bootstat/Android.bp b/bootstat/Android.bp
new file mode 100644
index 0000000..89b4598
--- /dev/null
+++ b/bootstat/Android.bp
@@ -0,0 +1,94 @@
+//
+// 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.
+//
+
+bootstat_lib_src_files = [
+    "boot_event_record_store.cpp",
+    "event_log_list_builder.cpp",
+    "histogram_logger.cpp",
+    "uptime_parser.cpp",
+]
+
+cc_defaults {
+    name: "bootstat_defaults",
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+
+        // 524291 corresponds to sysui_histogram, from
+        // frameworks/base/core/java/com/android/internal/logging/EventLogTags.logtags
+        "-DHISTOGRAM_LOG_TAG=524291",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+    ],
+    whole_static_libs: ["libgtest_prod"],
+    // Clang is required because of C++14
+    clang: true,
+}
+
+// bootstat static library
+// -----------------------------------------------------------------------------
+cc_library_static {
+    name: "libbootstat",
+    defaults: ["bootstat_defaults"],
+    srcs: bootstat_lib_src_files,
+}
+
+// bootstat static library, debug
+// -----------------------------------------------------------------------------
+cc_library_static {
+    name: "libbootstat_debug",
+    defaults: ["bootstat_defaults"],
+    host_supported: true,
+    srcs: bootstat_lib_src_files,
+
+    target: {
+        host: {
+            cflags: ["-UNDEBUG"],
+        },
+    },
+}
+
+// bootstat binary
+// -----------------------------------------------------------------------------
+cc_binary {
+    name: "bootstat",
+    defaults: ["bootstat_defaults"],
+    static_libs: ["libbootstat"],
+    init_rc: ["bootstat.rc"],
+    srcs: ["bootstat.cpp"],
+}
+
+// Native tests
+// -----------------------------------------------------------------------------
+cc_test {
+    name: "bootstat_tests",
+    defaults: ["bootstat_defaults"],
+    host_supported: true,
+    static_libs: [
+        "libbootstat_debug",
+        "libgmock",
+    ],
+    srcs: [
+        "boot_event_record_store_test.cpp",
+        "event_log_list_builder_test.cpp",
+        "testrunner.cpp",
+    ],
+}
diff --git a/bootstat/Android.mk b/bootstat/Android.mk
deleted file mode 100644
index bdd680d..0000000
--- a/bootstat/Android.mk
+++ /dev/null
@@ -1,141 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-bootstat_lib_src_files := \
-        boot_event_record_store.cpp \
-        event_log_list_builder.cpp \
-        histogram_logger.cpp \
-        uptime_parser.cpp \
-
-bootstat_src_files := \
-        bootstat.cpp \
-
-bootstat_test_src_files := \
-        boot_event_record_store_test.cpp \
-        event_log_list_builder_test.cpp \
-        testrunner.cpp \
-
-bootstat_shared_libs := \
-        libbase \
-        libcutils \
-        liblog \
-
-bootstat_cflags := \
-        -Wall \
-        -Wextra \
-        -Werror \
-
-# 524291 corresponds to sysui_histogram, from
-# frameworks/base/core/java/com/android/internal/logging/EventLogTags.logtags
-bootstat_cflags += -DHISTOGRAM_LOG_TAG=524291
-
-bootstat_debug_cflags := \
-        $(bootstat_cflags) \
-        -UNDEBUG \
-
-# bootstat static library
-# -----------------------------------------------------------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libbootstat
-LOCAL_CFLAGS := $(bootstat_cflags)
-LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_prod
-LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
-LOCAL_SRC_FILES := $(bootstat_lib_src_files)
-# Clang is required because of C++14
-LOCAL_CLANG := true
-
-include $(BUILD_STATIC_LIBRARY)
-
-# bootstat static library, debug
-# -----------------------------------------------------------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libbootstat_debug
-LOCAL_CFLAGS := $(bootstat_cflags)
-LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_prod
-LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
-LOCAL_SRC_FILES := $(bootstat_lib_src_files)
-# Clang is required because of C++14
-LOCAL_CLANG := true
-
-include $(BUILD_STATIC_LIBRARY)
-
-# bootstat host static library, debug
-# -----------------------------------------------------------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libbootstat_host_debug
-LOCAL_CFLAGS := $(bootstat_debug_cflags)
-LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_prod
-LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
-LOCAL_SRC_FILES := $(bootstat_lib_src_files)
-# Clang is required because of C++14
-LOCAL_CLANG := true
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-# bootstat binary
-# -----------------------------------------------------------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := bootstat
-LOCAL_CFLAGS := $(bootstat_cflags)
-LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_prod
-LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
-LOCAL_STATIC_LIBRARIES := libbootstat
-LOCAL_INIT_RC := bootstat.rc
-LOCAL_SRC_FILES := $(bootstat_src_files)
-# Clang is required because of C++14
-LOCAL_CLANG := true
-
-include $(BUILD_EXECUTABLE)
-
-# Native tests
-# -----------------------------------------------------------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := bootstat_tests
-LOCAL_CFLAGS := $(bootstat_tests_cflags)
-LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
-LOCAL_STATIC_LIBRARIES := libbootstat_debug libgmock
-LOCAL_SRC_FILES := $(bootstat_test_src_files)
-# Clang is required because of C++14
-LOCAL_CLANG := true
-
-include $(BUILD_NATIVE_TEST)
-
-# Host native tests
-# -----------------------------------------------------------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := bootstat_tests
-LOCAL_CFLAGS := $(bootstat_tests_cflags)
-LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
-LOCAL_STATIC_LIBRARIES := libbootstat_host_debug libgmock_host
-LOCAL_SRC_FILES := $(bootstat_test_src_files)
-# Clang is required because of C++14
-LOCAL_CLANG := true
-
-include $(BUILD_HOST_NATIVE_TEST)
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index 3ddd2b0..8506765 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -136,8 +136,13 @@
 #if defined(SEGV_BNDERR)
         case SEGV_BNDERR: return "SEGV_BNDERR";
 #endif
+#if defined(SEGV_PKUERR)
+        case SEGV_PKUERR: return "SEGV_PKUERR";
+#endif
       }
-#if defined(SEGV_BNDERR)
+#if defined(SEGV_PKUERR)
+      static_assert(NSIGSEGV == SEGV_PKUERR, "missing SEGV_* si_code");
+#elif defined(SEGV_BNDERR)
       static_assert(NSIGSEGV == SEGV_BNDERR, "missing SEGV_* si_code");
 #else
       static_assert(NSIGSEGV == SEGV_ACCERR, "missing SEGV_* si_code");
diff --git a/libmemunreachable/Android.bp b/libmemunreachable/Android.bp
new file mode 100644
index 0000000..85bc421
--- /dev/null
+++ b/libmemunreachable/Android.bp
@@ -0,0 +1,80 @@
+cc_defaults {
+    name: "libmemunreachable_defaults",
+
+    cflags: [
+        "-std=c++14",
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    clang: true,
+    shared_libs: [
+        "libbase",
+        "liblog",
+    ],
+}
+
+cc_library_shared {
+    name: "libmemunreachable",
+    defaults: ["libmemunreachable_defaults"],
+    srcs: [
+        "Allocator.cpp",
+        "HeapWalker.cpp",
+        "LeakFolding.cpp",
+        "LeakPipe.cpp",
+        "LineBuffer.cpp",
+        "MemUnreachable.cpp",
+        "ProcessMappings.cpp",
+        "PtracerThread.cpp",
+        "ThreadCapture.cpp",
+    ],
+
+    static_libs: [
+        "libc_malloc_debug_backtrace",
+        "libc_logging",
+    ],
+    // Only need this for arm since libc++ uses its own unwind code that
+    // doesn't mix with the other default unwind code.
+    arch: {
+        arm: {
+            static_libs: ["libunwind_llvm"],
+        },
+    },
+    export_include_dirs: ["include"],
+    local_include_dirs: ["include"],
+}
+
+cc_test {
+    name: "memunreachable_test",
+    defaults: ["libmemunreachable_defaults"],
+    host_supported: true,
+    srcs: [
+        "tests/Allocator_test.cpp",
+        "tests/HeapWalker_test.cpp",
+        "tests/LeakFolding_test.cpp",
+    ],
+
+    target: {
+        android: {
+            srcs: [
+                "tests/DisableMalloc_test.cpp",
+                "tests/MemUnreachable_test.cpp",
+                "tests/ThreadCapture_test.cpp",
+            ],
+            shared_libs: [
+                "libmemunreachable",
+            ],
+        },
+        host: {
+            srcs: [
+                "Allocator.cpp",
+                "HeapWalker.cpp",
+                "LeakFolding.cpp",
+                "tests/HostMallocStub.cpp",
+            ],
+        },
+        darwin: {
+            enabled: false,
+        },
+    },
+}
diff --git a/libmemunreachable/Android.mk b/libmemunreachable/Android.mk
deleted file mode 100644
index 7b66d44..0000000
--- a/libmemunreachable/Android.mk
+++ /dev/null
@@ -1,65 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-memunreachable_srcs := \
-   Allocator.cpp \
-   HeapWalker.cpp \
-   LeakFolding.cpp \
-   LeakPipe.cpp \
-   LineBuffer.cpp \
-   MemUnreachable.cpp \
-   ProcessMappings.cpp \
-   PtracerThread.cpp \
-   ThreadCapture.cpp \
-
-memunreachable_test_srcs := \
-   tests/Allocator_test.cpp \
-   tests/DisableMalloc_test.cpp \
-   tests/HeapWalker_test.cpp \
-   tests/LeakFolding_test.cpp \
-   tests/MemUnreachable_test.cpp \
-   tests/ThreadCapture_test.cpp \
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libmemunreachable
-LOCAL_SRC_FILES := $(memunreachable_srcs)
-LOCAL_CFLAGS := -std=c++14 -Wall -Wextra -Werror
-LOCAL_SHARED_LIBRARIES := libbase liblog
-LOCAL_STATIC_LIBRARIES := libc_malloc_debug_backtrace libc_logging
-# Only need this for arm since libc++ uses its own unwind code that
-# doesn't mix with the other default unwind code.
-LOCAL_STATIC_LIBRARIES_arm := libunwind_llvm
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_CLANG := true
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := memunreachable_test
-LOCAL_SRC_FILES := $(memunreachable_test_srcs)
-LOCAL_CFLAGS := -std=c++14 -Wall -Wextra -Werror
-LOCAL_CLANG := true
-LOCAL_SHARED_LIBRARIES := libmemunreachable libbase liblog
-
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := memunreachable_test
-LOCAL_SRC_FILES := \
-   Allocator.cpp \
-   HeapWalker.cpp  \
-   LeakFolding.cpp \
-   tests/Allocator_test.cpp \
-   tests/HeapWalker_test.cpp \
-   tests/HostMallocStub.cpp \
-   tests/LeakFolding_test.cpp \
-
-LOCAL_CFLAGS := -std=c++14 -Wall -Wextra -Werror
-LOCAL_CLANG := true
-LOCAL_SHARED_LIBRARIES := libbase liblog
-LOCAL_MODULE_HOST_OS := linux
-
-include $(BUILD_HOST_NATIVE_TEST)
diff --git a/libsync/Android.bp b/libsync/Android.bp
new file mode 100644
index 0000000..4948aa5
--- /dev/null
+++ b/libsync/Android.bp
@@ -0,0 +1,42 @@
+cc_defaults {
+    name: "libsync_defaults",
+    srcs: ["sync.c"],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    cflags: ["-Werror"],
+}
+
+cc_library_shared {
+    name: "libsync",
+    defaults: ["libsync_defaults"],
+}
+
+// libsync_recovery is only intended for the recovery binary.
+// Future versions of the kernel WILL require an updated libsync, and will break
+// anything statically linked against the current libsync.
+cc_library_static {
+    name: "libsync_recovery",
+    defaults: ["libsync_defaults"],
+}
+
+cc_test {
+    name: "sync_test",
+    defaults: ["libsync_defaults"],
+    gtest: false,
+    srcs: ["sync_test.c"],
+}
+
+cc_test {
+    name: "sync-unit-tests",
+    shared_libs: ["libsync"],
+    srcs: ["tests/sync_test.cpp"],
+    cflags: [
+        "-g",
+        "-Wall",
+        "-Werror",
+        "-std=gnu++11",
+        "-Wno-missing-field-initializers",
+        "-Wno-sign-compare",
+    ],
+    clang: true,
+}
diff --git a/libsync/Android.mk b/libsync/Android.mk
deleted file mode 100644
index f407bd1..0000000
--- a/libsync/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := sync.c
-LOCAL_MODULE := libsync
-LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror
-include $(BUILD_SHARED_LIBRARY)
-
-# libsync_recovery is only intended for the recovery binary.
-# Future versions of the kernel WILL require an updated libsync, and will break
-# anything statically linked against the current libsync.
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := sync.c
-LOCAL_MODULE := libsync_recovery
-LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := sync.c sync_test.c
-LOCAL_MODULE := sync_test
-LOCAL_MODULE_TAGS := optional tests
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror
-include $(BUILD_EXECUTABLE)
diff --git a/libsync/sync.c b/libsync/sync.c
index d73bb11..169dc36 100644
--- a/libsync/sync.c
+++ b/libsync/sync.c
@@ -21,13 +21,27 @@
 #include <stdint.h>
 #include <string.h>
 
-#include <linux/sync.h>
 #include <linux/sw_sync.h>
 
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <sync/sync.h>
+
+// The sync code is undergoing a major change. Add enough in to get
+// everything to compile wih the latest uapi headers.
+struct sync_merge_data {
+  int32_t fd2;
+  char name[32];
+  int32_t fence;
+};
+
+#define SYNC_IOC_MAGIC '>'
+#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32)
+#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 1, struct sync_merge_data)
+#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2, struct sync_fence_info_data)
+
 int sync_wait(int fd, int timeout)
 {
     __s32 to = timeout;
diff --git a/libsync/tests/Android.mk b/libsync/tests/Android.mk
deleted file mode 100644
index 8137c7a..0000000
--- a/libsync/tests/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_CLANG := true
-LOCAL_MODULE := sync-unit-tests
-LOCAL_CFLAGS += -g -Wall -Werror -std=gnu++11 -Wno-missing-field-initializers -Wno-sign-compare
-LOCAL_SHARED_LIBRARIES += libsync
-LOCAL_STATIC_LIBRARIES += libgtest_main
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/..
-LOCAL_SRC_FILES := \
-    sync_test.cpp
-include $(BUILD_NATIVE_TEST)