Merge "Add a header-version argument to fastboot"
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index 9776c1b..cf441cf 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -75,6 +75,7 @@
 static bool main_thread_valid;
 static uint64_t main_thread_id;
 
+static bool run_needs_flush = false;
 static auto& run_queue_notify_fd = *new unique_fd();
 static auto& run_queue_mutex = *new std::mutex();
 static auto& run_queue GUARDED_BY(run_queue_mutex) = *new std::deque<std::function<void()>>();
@@ -317,7 +318,8 @@
         PLOG(FATAL) << "failed to empty run queue notify fd";
     }
 
-    fdevent_run_flush();
+    // Mark that we need to flush, and then run it at the end of fdevent_loop.
+    run_needs_flush = true;
 }
 
 static void fdevent_run_setup() {
@@ -378,6 +380,11 @@
             g_pending_list.pop_front();
             fdevent_call_fdfunc(fde);
         }
+
+        if (run_needs_flush) {
+            fdevent_run_flush();
+            run_needs_flush = false;
+        }
     }
 }
 
diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp
index e3d5a35..2f0ff18 100644
--- a/adb/fdevent_test.cpp
+++ b/adb/fdevent_test.cpp
@@ -80,30 +80,7 @@
 
 TEST_F(FdeventTest, fdevent_terminate) {
     PrepareThread();
-
-    std::thread thread(fdevent_loop);
-    TerminateThread(thread);
-}
-
-static void FdEventThreadFunc(ThreadArg* arg) {
-    std::vector<int> read_fds;
-    std::vector<int> write_fds;
-
-    read_fds.push_back(arg->first_read_fd);
-    for (size_t i = 0; i < arg->middle_pipe_count; ++i) {
-        int fds[2];
-        ASSERT_EQ(0, adb_socketpair(fds));
-        read_fds.push_back(fds[0]);
-        write_fds.push_back(fds[1]);
-    }
-    write_fds.push_back(arg->last_write_fd);
-
-    std::vector<std::unique_ptr<FdHandler>> fd_handlers;
-    for (size_t i = 0; i < read_fds.size(); ++i) {
-        fd_handlers.push_back(std::make_unique<FdHandler>(read_fds[i], write_fds[i]));
-    }
-
-    fdevent_loop();
+    TerminateThread();
 }
 
 TEST_F(FdeventTest, smoke) {
@@ -122,7 +99,26 @@
     int reader = fd_pair2[0];
 
     PrepareThread();
-    std::thread thread(FdEventThreadFunc, &thread_arg);
+
+    std::vector<std::unique_ptr<FdHandler>> fd_handlers;
+    fdevent_run_on_main_thread([&thread_arg, &fd_handlers]() {
+        std::vector<int> read_fds;
+        std::vector<int> write_fds;
+
+        read_fds.push_back(thread_arg.first_read_fd);
+        for (size_t i = 0; i < thread_arg.middle_pipe_count; ++i) {
+            int fds[2];
+            ASSERT_EQ(0, adb_socketpair(fds));
+            read_fds.push_back(fds[0]);
+            write_fds.push_back(fds[1]);
+        }
+        write_fds.push_back(thread_arg.last_write_fd);
+
+        for (size_t i = 0; i < read_fds.size(); ++i) {
+            fd_handlers.push_back(std::make_unique<FdHandler>(read_fds[i], write_fds[i]));
+        }
+    });
+    WaitForFdeventLoop();
 
     for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) {
         std::string read_buffer = MESSAGE;
@@ -132,7 +128,10 @@
         ASSERT_EQ(read_buffer, write_buffer);
     }
 
-    TerminateThread(thread);
+    fdevent_run_on_main_thread([&fd_handlers]() { fd_handlers.clear(); });
+    WaitForFdeventLoop();
+
+    TerminateThread();
     ASSERT_EQ(0, adb_close(writer));
     ASSERT_EQ(0, adb_close(reader));
 }
@@ -143,7 +142,7 @@
     size_t* happened_event_count;
 };
 
-static void InvalidFdEventCallback(int fd, unsigned events, void* userdata) {
+static void InvalidFdEventCallback(int, unsigned events, void* userdata) {
     InvalidFdArg* arg = reinterpret_cast<InvalidFdArg*>(userdata);
     ASSERT_EQ(arg->expected_events, events);
     fdevent_remove(&arg->fde);
@@ -179,7 +178,6 @@
     std::vector<int> vec;
 
     PrepareThread();
-    std::thread thread(fdevent_loop);
 
     // Block the main thread for a long time while we queue our callbacks.
     fdevent_run_on_main_thread([]() {
@@ -194,7 +192,7 @@
         });
     }
 
-    TerminateThread(thread);
+    TerminateThread();
 
     ASSERT_EQ(1000000u, vec.size());
     for (int i = 0; i < 1000000; ++i) {
@@ -218,11 +216,8 @@
     std::vector<int> vec;
 
     PrepareThread();
-    std::thread thread(fdevent_loop);
-
     fdevent_run_on_main_thread(make_appender(&vec, 0));
-
-    TerminateThread(thread);
+    TerminateThread();
 
     ASSERT_EQ(100u, vec.size());
     for (int i = 0; i < 100; ++i) {
diff --git a/adb/fdevent_test.h b/adb/fdevent_test.h
index 1a2d41c..5a417e0 100644
--- a/adb/fdevent_test.h
+++ b/adb/fdevent_test.h
@@ -16,10 +16,31 @@
 
 #include <gtest/gtest.h>
 
+#include <condition_variable>
+#include <mutex>
 #include <thread>
 
 #include "socket.h"
 #include "sysdeps.h"
+#include "sysdeps/chrono.h"
+
+static void WaitForFdeventLoop() {
+    // Sleep for a bit to make sure that network events have propagated.
+    std::this_thread::sleep_for(100ms);
+
+    // fdevent_run_on_main_thread has a guaranteed ordering, and is guaranteed to happen after
+    // socket events, so as soon as our function is called, we know that we've processed all
+    // previous events.
+    std::mutex mutex;
+    std::condition_variable cv;
+    std::unique_lock<std::mutex> lock(mutex);
+    fdevent_run_on_main_thread([&]() {
+        mutex.lock();
+        mutex.unlock();
+        cv.notify_one();
+    });
+    cv.wait(lock);
+}
 
 class FdeventTest : public ::testing::Test {
   protected:
@@ -49,6 +70,9 @@
         }
         dummy_socket->ready(dummy_socket);
         dummy = dummy_fds[0];
+
+        thread_ = std::thread([]() { fdevent_loop(); });
+        WaitForFdeventLoop();
     }
 
     size_t GetAdditionalLocalSocketCount() {
@@ -56,10 +80,12 @@
         return 2;
     }
 
-    void TerminateThread(std::thread& thread) {
+    void TerminateThread() {
         fdevent_terminate_loop();
         ASSERT_TRUE(WriteFdExactly(dummy, "", 1));
-        thread.join();
+        thread_.join();
         ASSERT_EQ(0, adb_close(dummy));
     }
+
+    std::thread thread_;
 };
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index 6b40056..6c4a8b2 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -42,8 +42,6 @@
 
 class LocalSocketTest : public FdeventTest {};
 
-constexpr auto SLEEP_FOR_FDEVENT = 100ms;
-
 TEST_F(LocalSocketTest, smoke) {
     // Join two socketpairs with a chain of intermediate socketpairs.
     int first[2];
@@ -84,7 +82,6 @@
     connect(prev_tail, end);
 
     PrepareThread();
-    std::thread thread(fdevent_loop);
 
     for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) {
         std::string read_buffer = MESSAGE;
@@ -98,9 +95,9 @@
     ASSERT_EQ(0, adb_close(last[1]));
 
     // Wait until the local sockets are closed.
-    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+    WaitForFdeventLoop();
     ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
-    TerminateThread(thread);
+    TerminateThread();
 }
 
 struct CloseWithPacketArg {
@@ -109,24 +106,39 @@
     int cause_close_fd;
 };
 
-static void CloseWithPacketThreadFunc(CloseWithPacketArg* arg) {
-    asocket* s = create_local_socket(arg->socket_fd);
-    ASSERT_TRUE(s != nullptr);
-    arg->bytes_written = 0;
+static void CreateCloser(CloseWithPacketArg* arg) {
+    fdevent_run_on_main_thread([arg]() {
+        asocket* s = create_local_socket(arg->socket_fd);
+        ASSERT_TRUE(s != nullptr);
+        arg->bytes_written = 0;
 
-    std::string data;
-    data.resize(MAX_PAYLOAD);
-    arg->bytes_written += data.size();
-    int ret = s->enqueue(s, std::move(data));
-    ASSERT_EQ(1, ret);
+        // On platforms that implement sockets via underlying sockets (e.g. Wine),
+        // a socket can appear to be full, and then become available for writes
+        // again without read being called on the other end. Loop and sleep after
+        // each write to give the underlying implementation time to flush.
+        bool socket_filled = false;
+        for (int i = 0; i < 128; ++i) {
+            std::string data;
+            data.resize(MAX_PAYLOAD);
+            arg->bytes_written += data.size();
+            int ret = s->enqueue(s, std::move(data));
+            if (ret == 1) {
+                socket_filled = true;
+                break;
+            }
+            ASSERT_NE(-1, ret);
 
-    asocket* cause_close_s = create_local_socket(arg->cause_close_fd);
-    ASSERT_TRUE(cause_close_s != nullptr);
-    cause_close_s->peer = s;
-    s->peer = cause_close_s;
-    cause_close_s->ready(cause_close_s);
+            std::this_thread::sleep_for(250ms);
+        }
+        ASSERT_TRUE(socket_filled);
 
-    fdevent_loop();
+        asocket* cause_close_s = create_local_socket(arg->cause_close_fd);
+        ASSERT_TRUE(cause_close_s != nullptr);
+        cause_close_s->peer = s;
+        s->peer = cause_close_s;
+        cause_close_s->ready(cause_close_s);
+    });
+    WaitForFdeventLoop();
 }
 
 // This test checks if we can close local socket in the following situation:
@@ -143,16 +155,17 @@
     arg.cause_close_fd = cause_close_fd[1];
 
     PrepareThread();
-    std::thread thread(CloseWithPacketThreadFunc, &arg);
-    // Wait until the fdevent_loop() starts.
-    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+    CreateCloser(&arg);
+
     ASSERT_EQ(0, adb_close(cause_close_fd[0]));
-    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+
+    WaitForFdeventLoop();
     EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
     ASSERT_EQ(0, adb_close(socket_fd[0]));
-    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+
+    WaitForFdeventLoop();
     ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
-    TerminateThread(thread);
+    TerminateThread();
 }
 
 // This test checks if we can read packets from a closing local socket.
@@ -166,11 +179,12 @@
     arg.cause_close_fd = cause_close_fd[1];
 
     PrepareThread();
-    std::thread thread(CloseWithPacketThreadFunc, &arg);
-    // Wait until the fdevent_loop() starts.
-    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+    CreateCloser(&arg);
+
+    WaitForFdeventLoop();
     ASSERT_EQ(0, adb_close(cause_close_fd[0]));
-    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+
+    WaitForFdeventLoop();
     EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
 
     // Verify if we can read successfully.
@@ -179,9 +193,9 @@
     ASSERT_EQ(true, ReadFdExactly(socket_fd[0], buf.data(), buf.size()));
     ASSERT_EQ(0, adb_close(socket_fd[0]));
 
-    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+    WaitForFdeventLoop();
     ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
-    TerminateThread(thread);
+    TerminateThread();
 }
 
 // This test checks if we can close local socket in the following situation:
@@ -198,15 +212,15 @@
     arg.cause_close_fd = cause_close_fd[1];
 
     PrepareThread();
-    std::thread thread(CloseWithPacketThreadFunc, &arg);
-    // Wait until the fdevent_loop() starts.
-    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+    CreateCloser(&arg);
+
+    WaitForFdeventLoop();
     EXPECT_EQ(2u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
     ASSERT_EQ(0, adb_close(socket_fd[0]));
 
-    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+    WaitForFdeventLoop();
     ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
-    TerminateThread(thread);
+    TerminateThread();
 }
 
 // Ensure that if we fail to write output to an fd, we will still flush data coming from it.
@@ -226,7 +240,6 @@
     tail->ready(tail);
 
     PrepareThread();
-    std::thread thread(fdevent_loop);
 
     EXPECT_TRUE(WriteFdExactly(head_fd[0], "foo", 3));
 
@@ -242,10 +255,9 @@
     adb_close(head_fd[0]);
     adb_close(tail_fd[0]);
 
-    // Wait until the local sockets are closed.
-    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+    WaitForFdeventLoop();
     ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
-    TerminateThread(thread);
+    TerminateThread();
 }
 
 #if defined(__linux__)
@@ -254,21 +266,10 @@
     std::string error;
     int fd = network_loopback_client(5038, SOCK_STREAM, &error);
     ASSERT_GE(fd, 0) << error;
-    std::this_thread::sleep_for(200ms);
+    std::this_thread::sleep_for(1s);
     ASSERT_EQ(0, adb_close(fd));
 }
 
-struct CloseRdHupSocketArg {
-    int socket_fd;
-};
-
-static void CloseRdHupSocketThreadFunc(CloseRdHupSocketArg* arg) {
-    asocket* s = create_local_socket(arg->socket_fd);
-    ASSERT_TRUE(s != nullptr);
-
-    fdevent_loop();
-}
-
 // This test checks if we can close sockets in CLOSE_WAIT state.
 TEST_F(LocalSocketTest, close_socket_in_CLOSE_WAIT_state) {
     std::string error;
@@ -279,22 +280,23 @@
 
     int accept_fd = adb_socket_accept(listen_fd, nullptr, nullptr);
     ASSERT_GE(accept_fd, 0);
-    CloseRdHupSocketArg arg;
-    arg.socket_fd = accept_fd;
 
     PrepareThread();
-    std::thread thread(CloseRdHupSocketThreadFunc, &arg);
 
-    // Wait until the fdevent_loop() starts.
-    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+    fdevent_run_on_main_thread([accept_fd]() {
+        asocket* s = create_local_socket(accept_fd);
+        ASSERT_TRUE(s != nullptr);
+    });
+
+    WaitForFdeventLoop();
     EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
 
     // Wait until the client closes its socket.
     client_thread.join();
 
-    std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
+    WaitForFdeventLoop();
     ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
-    TerminateThread(thread);
+    TerminateThread();
 }
 
 #endif  // defined(__linux__)
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index e05a3db..0887e6f 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -126,12 +126,12 @@
         } else if (rc == -1 && errno == EAGAIN) {
             fdevent_add(&s->fde, FDE_WRITE);
             return SocketFlushResult::TryAgain;
+        } else {
+            // We failed to write, but it's possible that we can still read from the socket.
+            // Give that a try before giving up.
+            s->has_write_error = true;
+            break;
         }
-
-        // We failed to write, but it's possible that we can still read from the socket.
-        // Give that a try before giving up.
-        s->has_write_error = true;
-        break;
     }
 
     // If we sent the last packet of a closing socket, we can now destroy it.
diff --git a/adb/sysdeps_test.cpp b/adb/sysdeps_test.cpp
index fd19882..79cebe6 100644
--- a/adb/sysdeps_test.cpp
+++ b/adb/sysdeps_test.cpp
@@ -121,10 +121,13 @@
     adb_pollfd pfd[3] = {};
     pfd[0].fd = fds[0];
     pfd[0].events = POLLRDNORM;
+    pfd[0].revents = ~0;
     pfd[1].fd = INT_MAX;
     pfd[1].events = POLLRDNORM;
+    pfd[1].revents = ~0;
     pfd[2].fd = fds[1];
     pfd[2].events = POLLWRNORM;
+    pfd[2].revents = ~0;
 
     ASSERT_TRUE(WriteFdExactly(fds[1], "foo", 4));
 
@@ -136,6 +139,17 @@
     EXPECT_EQ(POLLRDNORM, pfd[0].revents);
     EXPECT_EQ(POLLNVAL, pfd[1].revents);
     EXPECT_EQ(POLLWRNORM, pfd[2].revents);
+
+    // Make sure that we return immediately if an invalid FD is given.
+    pfd[0].fd = fds[0];
+    pfd[0].events = POLLRDNORM;
+    pfd[0].revents = ~0;
+    pfd[1].fd = INT_MAX;
+    pfd[1].events = POLLRDNORM;
+    pfd[1].revents = ~0;
+    EXPECT_EQ(2, adb_poll(pfd, 2, -1));
+    EXPECT_EQ(POLLRDNORM, pfd[0].revents);
+    EXPECT_EQ(POLLNVAL, pfd[1].revents);
 }
 
 TEST_F(sysdeps_poll, duplicate_fd) {
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 62f4ac8..7d35fb6 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -529,6 +529,7 @@
     int skipped = 0;
     std::vector<WSAPOLLFD> sockets;
     std::vector<adb_pollfd*> original;
+
     for (size_t i = 0; i < nfds; ++i) {
         FH fh = _fh_from_int(fds[i].fd, __func__);
         if (!fh || !fh->used || fh->clazz != &_fh_socket_class) {
@@ -549,6 +550,11 @@
         return skipped;
     }
 
+    // If we have any invalid FDs in our FD set, make sure to return immediately.
+    if (skipped > 0) {
+        timeout = 0;
+    }
+
     int result = WSAPoll(sockets.data(), sockets.size(), timeout);
     if (result == SOCKET_ERROR) {
         _socket_set_errno(WSAGetLastError());
@@ -560,7 +566,7 @@
         original[i]->revents = sockets[i].revents;
     }
 
-    // WSAPoll appears to return the number of unique FDs with avaiable events, instead of how many
+    // WSAPoll appears to return the number of unique FDs with available events, instead of how many
     // of the pollfd elements have a non-zero revents field, which is what it and poll are specified
     // to do. Ignore its result and calculate the proper return value.
     result = 0;
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index f5bcc26..944b00b 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -22,7 +22,8 @@
 
 LOCAL_C_INCLUDES := \
   $(LOCAL_PATH)/../adb \
-  $(LOCAL_PATH)/../mkbootimg \
+
+LOCAL_HEADER_LIBRARIES := bootimg_headers
 
 LOCAL_SRC_FILES := \
     bootimg_utils.cpp \
diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp
index 60b7124..551ddba 100644
--- a/fastboot/engine.cpp
+++ b/fastboot/engine.cpp
@@ -109,32 +109,32 @@
 
 void fb_set_active(const std::string& slot) {
     Action& a = queue_action(OP_COMMAND, "set_active:" + slot);
-    a.msg = "Setting current slot to '" + slot + "'...";
+    a.msg = "Setting current slot to '" + slot + "'";
 }
 
 void fb_queue_erase(const std::string& partition) {
     Action& a = queue_action(OP_COMMAND, "erase:" + partition);
-    a.msg = "Erasing '" + partition + "'...";
+    a.msg = "Erasing '" + partition + "'";
 }
 
 void fb_queue_flash_fd(const std::string& partition, int fd, uint32_t sz) {
     Action& a = queue_action(OP_DOWNLOAD_FD, "");
     a.fd = fd;
     a.size = sz;
-    a.msg = android::base::StringPrintf("Sending '%s' (%d KB)...", partition.c_str(), sz / 1024);
+    a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024);
 
     Action& b = queue_action(OP_COMMAND, "flash:" + partition);
-    b.msg = "Writing '" + partition + "'...";
+    b.msg = "Writing '" + partition + "'";
 }
 
 void fb_queue_flash(const std::string& partition, void* data, uint32_t sz) {
     Action& a = queue_action(OP_DOWNLOAD, "");
     a.data = data;
     a.size = sz;
-    a.msg = android::base::StringPrintf("Sending '%s' (%d KB)...", partition.c_str(), sz / 1024);
+    a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024);
 
     Action& b = queue_action(OP_COMMAND, "flash:" + partition);
-    b.msg = "Writing '" + partition + "'...";
+    b.msg = "Writing '" + partition + "'";
 }
 
 void fb_queue_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz,
@@ -142,12 +142,12 @@
     Action& a = queue_action(OP_DOWNLOAD_SPARSE, "");
     a.data = s;
     a.size = 0;
-    a.msg = android::base::StringPrintf("Sending sparse '%s' %zu/%zu (%d KB)...", partition.c_str(),
+    a.msg = android::base::StringPrintf("Sending sparse '%s' %zu/%zu (%u KB)", partition.c_str(),
                                         current, total, sz / 1024);
 
     Action& b = queue_action(OP_COMMAND, "flash:" + partition);
-    b.msg =
-        android::base::StringPrintf("Writing '%s' %zu/%zu...", partition.c_str(), current, total);
+    b.msg = android::base::StringPrintf("Writing sparse '%s' %zu/%zu", partition.c_str(), current,
+                                        total);
 }
 
 static int match(const char* str, const char** value, unsigned count) {
@@ -270,7 +270,7 @@
 void fb_queue_reboot() {
     Action& a = queue_action(OP_COMMAND, "reboot");
     a.func = cb_do_nothing;
-    a.msg = "Rebooting...";
+    a.msg = "Rebooting";
 }
 
 void fb_queue_command(const std::string& cmd, const std::string& msg) {
@@ -289,7 +289,7 @@
     Action& a = queue_action(OP_DOWNLOAD_FD, "");
     a.fd = fd;
     a.size = sz;
-    a.msg = android::base::StringPrintf("Sending '%s' (%d KB)", name.c_str(), sz / 1024);
+    a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", name.c_str(), sz / 1024);
 }
 
 void fb_queue_upload(const std::string& outfile) {
@@ -312,7 +312,8 @@
     for (auto& a : action_list) {
         a->start = now();
         if (!a->msg.empty()) {
-            fprintf(stderr, "%s\n", a->msg.c_str());
+            fprintf(stderr, "%-50s ", a->msg.c_str());
+            verbose("\n");
         }
         if (a->op == OP_DOWNLOAD) {
             status = fb_download_data(transport, a->data, a->size);
@@ -333,6 +334,7 @@
             if (status) break;
         } else if (a->op == OP_NOTICE) {
             // We already showed the notice because it's in `Action::msg`.
+            fprintf(stderr, "\n");
         } else if (a->op == OP_DOWNLOAD_SPARSE) {
             status = fb_download_data_sparse(transport, reinterpret_cast<sparse_file*>(a->data));
             status = a->func(*a, status, status ? fb_get_error().c_str() : "");
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 0ce3855..c5b357c 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -238,7 +238,7 @@
 // Opens a new Transport connected to a device. If |serial| is non-null it will be used to identify
 // a specific device, otherwise the first USB device found will be used.
 //
-// If |serial| is non-null but invalid, this prints an error message to stderr and returns nullptr.
+// If |serial| is non-null but invalid, this exits.
 // Otherwise it blocks until the target is available.
 //
 // The returned Transport is a singleton, so multiple calls to this function will return the same
@@ -270,9 +270,7 @@
         if (net_address != nullptr) {
             std::string error;
             if (!android::base::ParseNetAddress(net_address, &host, &port, nullptr, &error)) {
-                fprintf(stderr, "error: Invalid network address '%s': %s\n", net_address,
-                        error.c_str());
-                return nullptr;
+                die("invalid network address '%s': %s\n", net_address, error.c_str());
             }
         }
     }
@@ -426,7 +424,7 @@
             "                                           trigger a reboot.\n"
             "  --disable-verity                         Set the disable-verity flag in the\n"
             "                                           the vbmeta image being flashed.\n"
-            "  --disable-verification                   Set the disable-verification flag in"
+            "  --disable-verification                   Set the disable-verification flag in\n"
             "                                           the vbmeta image being flashed.\n"
 #if !defined(_WIN32)
             "  --wipe-and-use-fbe                       On devices which support it,\n"
@@ -434,6 +432,7 @@
             "                                           enable file-based encryption\n"
 #endif
             "  --unbuffered                             Do not buffer input or output.\n"
+            "  -v, --verbose                            Verbose output.\n"
             "  --version                                Display version.\n"
             "  --header-version                         Set boot image header version while\n"
             "                                           using flash:raw and boot commands to \n"
@@ -548,7 +547,7 @@
     die("make_temporary_directory not supported under Windows, sorry!");
 }
 
-static int make_temporary_fd() {
+static int make_temporary_fd(const char* /*what*/) {
     // TODO: reimplement to avoid leaking a FILE*.
     return fileno(tmpfile());
 }
@@ -564,18 +563,16 @@
 static std::string make_temporary_directory() {
     std::string result(make_temporary_template());
     if (mkdtemp(&result[0]) == nullptr) {
-        fprintf(stderr, "Unable to create temporary directory: %s\n", strerror(errno));
-        return "";
+        die("unable to create temporary directory: %s", strerror(errno));
     }
     return result;
 }
 
-static int make_temporary_fd() {
+static int make_temporary_fd(const char* what) {
     std::string path_template(make_temporary_template());
     int fd = mkstemp(&path_template[0]);
     if (fd == -1) {
-        fprintf(stderr, "Unable to create temporary file: %s\n", strerror(errno));
-        return -1;
+        die("failed to create temporary file for %s: %s\n", what, strerror(errno));
     }
     unlink(path_template.c_str());
     return fd;
@@ -585,16 +582,11 @@
 
 static std::string create_fbemarker_tmpdir() {
     std::string dir = make_temporary_directory();
-    if (dir.empty()) {
-        fprintf(stderr, "Unable to create local temp directory for FBE marker\n");
-        return "";
-    }
     std::string marker_file = dir + "/" + convert_fbe_marker_filename;
     int fd = open(marker_file.c_str(), O_CREAT | O_WRONLY | O_CLOEXEC, 0666);
     if (fd == -1) {
-        fprintf(stderr, "Unable to create FBE marker file %s locally: %d, %s\n",
-            marker_file.c_str(), errno, strerror(errno));
-        return "";
+        die("unable to create FBE marker file %s locally: %s",
+            marker_file.c_str(), strerror(errno));
     }
     close(fd);
     return dir;
@@ -615,10 +607,7 @@
 }
 
 static int unzip_to_file(ZipArchiveHandle zip, const char* entry_name) {
-    unique_fd fd(make_temporary_fd());
-    if (fd == -1) {
-        die("failed to create temporary file for '%s': %s", entry_name, strerror(errno));
-    }
+    unique_fd fd(make_temporary_fd(entry_name));
 
     ZipString zip_entry_name(entry_name);
     ZipEntry zip_entry;
@@ -779,8 +768,8 @@
 static int64_t get_target_sparse_limit(Transport* transport) {
     std::string max_download_size;
     if (!fb_getvar(transport, "max-download-size", &max_download_size) ||
-            max_download_size.empty()) {
-        fprintf(stderr, "target didn't report max-download-size\n");
+        max_download_size.empty()) {
+        verbose("target didn't report max-download-size");
         return 0;
     }
 
@@ -792,9 +781,7 @@
         fprintf(stderr, "couldn't parse max-download-size '%s'\n", max_download_size.c_str());
         return 0;
     }
-    if (limit > 0) {
-        fprintf(stderr, "target reported max download size of %" PRId64 " bytes\n", limit);
-    }
+    if (limit > 0) verbose("target reported max download size of %" PRId64 " bytes", limit);
     return limit;
 }
 
@@ -885,10 +872,7 @@
         return;
     }
 
-    int fd = make_temporary_fd();
-    if (fd == -1) {
-        die("Failed to create temporary file for vbmeta rewriting");
-    }
+    int fd = make_temporary_fd("vbmeta rewriting");
 
     std::string data;
     if (!android::base::ReadFdToString(buf->fd, &data)) {
@@ -1527,12 +1511,13 @@
         {"tags-offset", required_argument, 0, 't'},
         {"help", no_argument, 0, 'h'},
         {"unbuffered", no_argument, 0, 0},
-        {"version", no_argument, 0, 0},
         {"slot", required_argument, 0, 0},
         {"set_active", optional_argument, 0, 'a'},
         {"set-active", optional_argument, 0, 'a'},
         {"skip-secondary", no_argument, 0, 0},
         {"skip-reboot", no_argument, 0, 0},
+        {"verbose", no_argument, 0, 'v'},
+        {"version", no_argument, 0, 0},
         {"disable-verity", no_argument, 0, 0},
         {"disable-verification", no_argument, 0, 0},
         {"header-version", required_argument, 0, 0},
@@ -1545,7 +1530,7 @@
     serial = getenv("ANDROID_SERIAL");
 
     while (1) {
-        int c = getopt_long(argc, argv, "wub:k:n:r:t:s:S:lc:i:m:ha::", longopts, &longindex);
+        int c = getopt_long(argc, argv, "vwub:k:n:r:t:s:S:lc:i:m:ha::", longopts, &longindex);
         if (c < 0) {
             break;
         }
@@ -1600,6 +1585,9 @@
         case 'u':
             erase_first = false;
             break;
+        case 'v':
+            set_verbose();
+            break;
         case 'w':
             wants_wipe = true;
             break;
@@ -1631,9 +1619,7 @@
             } else if (strcmp("header-version", longopts[longindex].name) == 0) {
                 header_version = strtoul(optarg, nullptr, 0);
             } else {
-                fprintf(stderr, "Internal error in options processing for %s\n",
-                    longopts[longindex].name);
-                return 1;
+                die("unknown option %s", longopts[longindex].name);
             }
             break;
         default:
@@ -1862,14 +1848,10 @@
     }
 
     if (wants_wipe) {
-        fprintf(stderr, "wiping userdata...\n");
         fb_queue_erase("userdata");
         if (set_fbe_marker) {
-            fprintf(stderr, "setting FBE marker...\n");
+            fprintf(stderr, "setting FBE marker on initial userdata...\n");
             std::string initial_userdata_dir = create_fbemarker_tmpdir();
-            if (initial_userdata_dir.empty()) {
-                return 1;
-            }
             fb_perform_format(transport, "userdata", 1, "", "", initial_userdata_dir);
             delete_fbemarker_tmpdir(initial_userdata_dir);
         } else {
@@ -1878,7 +1860,6 @@
 
         std::string cache_type;
         if (fb_getvar(transport, "partition-type:cache", &cache_type) && !cache_type.empty()) {
-            fprintf(stderr, "wiping cache...\n");
             fb_queue_erase("cache");
             fb_perform_format(transport, "cache", 1, "", "", "");
         }
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index a31057a..005ba5a 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -75,6 +75,7 @@
 /* util stuff */
 double now();
 char* xstrdup(const char*);
+void set_verbose();
 
 // These printf-like functions are implemented in terms of vsnprintf, so they
 // use the same attribute for compile-time format string checking. On Windows,
@@ -90,6 +91,7 @@
 #endif
 void die(const char* fmt, ...) __attribute__((__noreturn__))
 __attribute__((__format__(FASTBOOT_FORMAT_ARCHETYPE, 1, 2)));
+void verbose(const char* fmt, ...) __attribute__((__format__(FASTBOOT_FORMAT_ARCHETYPE, 1, 2)));
 #undef FASTBOOT_FORMAT_ARCHETYPE
 
 /* Current product */
diff --git a/fastboot/protocol.cpp b/fastboot/protocol.cpp
index c239861..133a2d0 100644
--- a/fastboot/protocol.cpp
+++ b/fastboot/protocol.cpp
@@ -75,18 +75,21 @@
         }
 
         if (!memcmp(status, "INFO", 4)) {
-            fprintf(stderr,"(bootloader) %s\n", status + 4);
+            verbose("received INFO %s", status + 4);
+            fprintf(stderr, "(bootloader) %s\n", status + 4);
             continue;
         }
 
         if (!memcmp(status, "OKAY", 4)) {
+            verbose("received OKAY %s", status + 4);
             if (response) {
-                strcpy(response, (char*) status + 4);
+                strcpy(response, status + 4);
             }
             return 0;
         }
 
         if (!memcmp(status, "FAIL", 4)) {
+            verbose("received FAIL %s", status + 4);
             if (r > 4) {
                 g_error = android::base::StringPrintf("remote: %s", status + 4);
             } else {
@@ -96,6 +99,7 @@
         }
 
         if (!memcmp(status, "DATA", 4) && size > 0){
+            verbose("received DATA %s", status + 4);
             uint32_t dsize = strtol(status + 4, 0, 16);
             if (dsize > size) {
                 g_error = android::base::StringPrintf("data size too large (%d)", dsize);
@@ -105,6 +109,7 @@
             return dsize;
         }
 
+        verbose("received unknown status code \"%4.4s\"", status);
         g_error = "unknown status code";
         transport->Close();
         break;
@@ -124,6 +129,8 @@
         response[0] = 0;
     }
 
+    verbose("sending command \"%s\"", cmd.c_str());
+
     if (transport->Write(cmd.c_str(), cmd.size()) != static_cast<int>(cmd.size())) {
         g_error = android::base::StringPrintf("command write failed (%s)", strerror(errno));
         transport->Close();
@@ -134,6 +141,8 @@
 }
 
 static int64_t _command_write_data(Transport* transport, const void* data, uint32_t size) {
+    verbose("sending data (%" PRIu32 " bytes)", size);
+
     int64_t r = transport->Write(data, size);
     if (r < 0) {
         g_error = android::base::StringPrintf("data write failure (%s)", strerror(errno));
@@ -149,6 +158,8 @@
 }
 
 static int64_t _command_read_data(Transport* transport, void* data, uint32_t size) {
+    verbose("reading data (%" PRIu32 " bytes)", size);
+
     int64_t r = transport->Read(data, size);
     if (r < 0) {
         g_error = android::base::StringPrintf("data read failure (%s)", strerror(errno));
diff --git a/fastboot/util.cpp b/fastboot/util.cpp
index fb085e7..140270f 100644
--- a/fastboot/util.cpp
+++ b/fastboot/util.cpp
@@ -35,6 +35,8 @@
 
 #include "fastboot.h"
 
+static bool g_verbose = false;
+
 double now() {
     struct timeval tv;
     gettimeofday(&tv, NULL);
@@ -44,13 +46,30 @@
 void die(const char* fmt, ...) {
     va_list ap;
     va_start(ap, fmt);
-    fprintf(stderr,"error: ");
+    fprintf(stderr, "fastboot: error: ");
     vfprintf(stderr, fmt, ap);
-    fprintf(stderr,"\n");
+    fprintf(stderr, "\n");
     va_end(ap);
     exit(EXIT_FAILURE);
 }
 
+void set_verbose() {
+    g_verbose = true;
+}
+
+void verbose(const char* fmt, ...) {
+    if (!g_verbose) return;
+
+    if (*fmt != '\n') {
+        va_list ap;
+        va_start(ap, fmt);
+        fprintf(stderr, "fastboot: verbose: ");
+        vfprintf(stderr, fmt, ap);
+        va_end(ap);
+    }
+    fprintf(stderr, "\n");
+}
+
 char* xstrdup(const char* s) {
     char* result = strdup(s);
     if (!result) die("out of memory");
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 72a65d2..3fbef9f 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -116,17 +116,21 @@
 #define EM_ICE          2
 #define EM_AES_256_CTS  3
 #define EM_AES_256_HEH  4
+#define EM_SPECK_128_256_XTS 5
+#define EM_SPECK_128_256_CTS 6
 
 static const struct flag_list file_contents_encryption_modes[] = {
     {"aes-256-xts", EM_AES_256_XTS},
+    {"speck128/256-xts", EM_SPECK_128_256_XTS},
     {"software", EM_AES_256_XTS}, /* alias for backwards compatibility */
-    {"ice", EM_ICE}, /* hardware-specific inline cryptographic engine */
+    {"ice", EM_ICE},              /* hardware-specific inline cryptographic engine */
     {0, 0},
 };
 
 static const struct flag_list file_names_encryption_modes[] = {
     {"aes-256-cts", EM_AES_256_CTS},
     {"aes-256-heh", EM_AES_256_HEH},
+    {"speck128/256-cts", EM_SPECK_128_256_CTS},
     {0, 0},
 };
 
diff --git a/init/Android.bp b/init/Android.bp
index 31c8efb..70a4ac6 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -127,9 +127,7 @@
         "watchdogd.cpp",
     ],
     whole_static_libs: ["libcap"],
-    include_dirs: [
-        "system/core/mkbootimg",
-    ],
+    header_libs: ["bootimg_headers"],
     proto: {
         type: "lite",
         export_proto_headers: true,
diff --git a/mkbootimg/Android.bp b/mkbootimg/Android.bp
new file mode 100644
index 0000000..b494346
--- /dev/null
+++ b/mkbootimg/Android.bp
@@ -0,0 +1,32 @@
+// Copyright 2012 The Android Open Source Project
+
+cc_library_headers {
+    name: "libmkbootimg_abi_headers",
+    vendor_available: true,
+    export_include_dirs: ["include"],
+}
+
+cc_library_headers {
+    name: "bootimg_headers",
+    vendor_available: true,
+    export_include_dirs: ["include/bootimg"],
+    host_supported: true,
+    target: {
+        windows: {
+            enabled: true,
+        },
+    },
+}
+
+cc_library {
+    name: "libmkbootimg_abi_check",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "mkbootimg_dummy.cpp",
+    ],
+    header_libs: ["libmkbootimg_abi_headers"],
+    export_header_lib_headers: ["libmkbootimg_abi_headers"],
+}
diff --git a/mkbootimg/include/abi_check/mkbootimg_abi_check.h b/mkbootimg/include/abi_check/mkbootimg_abi_check.h
new file mode 100644
index 0000000..d478aba
--- /dev/null
+++ b/mkbootimg/include/abi_check/mkbootimg_abi_check.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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 <bootimg/bootimg.h>
+
+// This header has been created for the following reaons:
+//    1) In order for a change in a user defined type to be classified as API /
+//       ABI breaking, it needs to be referenced by an 'exported interface'
+//       (in this case the function mkbootimg_dummy).
+//    2) Since 'mkbootimg_dummy' needs to be exported, we need to have it
+//       exposed through a public header.
+//    3) It is desirable not to pollute bootimg.h with interfaces which are not
+//       'used' in reality by on device binaries. Furthermore, bootimg.h might
+//       be exported by a library in the future, so we must avoid polluting it.
+void mkbootimg_dummy(boot_img_hdr*);
diff --git a/mkbootimg/bootimg.h b/mkbootimg/include/bootimg/bootimg.h
similarity index 91%
rename from mkbootimg/bootimg.h
rename to mkbootimg/include/bootimg/bootimg.h
index 1be8c22..4311b46 100644
--- a/mkbootimg/bootimg.h
+++ b/mkbootimg/include/bootimg/bootimg.h
@@ -2,16 +2,16 @@
 **
 ** Copyright 2007, 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 
+** 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 
+**     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 
+** 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.
 */
 
@@ -34,17 +34,17 @@
 struct boot_img_hdr_v0 {
     uint8_t magic[BOOT_MAGIC_SIZE];
 
-    uint32_t kernel_size;  /* size in bytes */
-    uint32_t kernel_addr;  /* physical load addr */
+    uint32_t kernel_size; /* size in bytes */
+    uint32_t kernel_addr; /* physical load addr */
 
     uint32_t ramdisk_size; /* size in bytes */
     uint32_t ramdisk_addr; /* physical load addr */
 
-    uint32_t second_size;  /* size in bytes */
-    uint32_t second_addr;  /* physical load addr */
+    uint32_t second_size; /* size in bytes */
+    uint32_t second_addr; /* physical load addr */
 
-    uint32_t tags_addr;    /* physical addr for kernel tags */
-    uint32_t page_size;    /* flash page size we assume */
+    uint32_t tags_addr; /* physical addr for kernel tags */
+    uint32_t page_size; /* flash page size we assume */
     /*
      * version for the boot image header.
      */
diff --git a/mkbootimg/mkbootimg_dummy.cpp b/mkbootimg/mkbootimg_dummy.cpp
new file mode 100644
index 0000000..410d379
--- /dev/null
+++ b/mkbootimg/mkbootimg_dummy.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2018 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 <abi_check/mkbootimg_abi_check.h>
+
+void mkbootimg_dummy(boot_img_hdr* hdr) {
+    // TODO: Hack to trigger abi checks, remove this.
+    if (hdr) {
+        hdr--;
+    }
+}
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 94465f4..ba96cc8 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -218,13 +218,20 @@
 namespace.vndk.asan.permitted.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%/hw
 namespace.vndk.asan.permitted.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%/hw
 
+# The "vndk" namespace links to "default" namespace for LLNDK libs and links to
+# "sphal" namespace for vendor libs.  The ordering matters.  The "default"
+# namespace has higher priority than the "sphal" namespace.
+namespace.vndk.links = default,sphal
+
 # When these NDK libs are required inside this namespace, then it is redirected
 # to the default namespace. This is possible since their ABI is stable across
 # Android releases.
-namespace.vndk.links = default
 namespace.vndk.link.default.shared_libs  = %LLNDK_LIBRARIES%
 namespace.vndk.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
 
+# Allow VNDK-SP extensions to use vendor libraries
+namespace.vndk.link.sphal.allow_all_shared_libs = true
+
 ###############################################################################
 # Namespace config for vendor processes. In O, no restriction is enforced for
 # them. However, in O-MR1, access to /system/${LIB} will not be allowed to