Merge "Use async safe logging in signal handlers."
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 39e71e5..0181daa 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -31,6 +31,8 @@
 #include <time.h>
 
 #include <chrono>
+#include <condition_variable>
+#include <mutex>
 #include <string>
 #include <thread>
 #include <vector>
@@ -48,6 +50,7 @@
 #include "adb_io.h"
 #include "adb_listeners.h"
 #include "adb_utils.h"
+#include "sysdeps/chrono.h"
 #include "transport.h"
 
 #if !ADB_HOST
@@ -313,19 +316,15 @@
     if (type == "bootloader") {
         D("setting connection_state to kCsBootloader");
         t->SetConnectionState(kCsBootloader);
-        update_transports();
     } else if (type == "device") {
         D("setting connection_state to kCsDevice");
         t->SetConnectionState(kCsDevice);
-        update_transports();
     } else if (type == "recovery") {
         D("setting connection_state to kCsRecovery");
         t->SetConnectionState(kCsRecovery);
-        update_transports();
     } else if (type == "sideload") {
         D("setting connection_state to kCsSideload");
         t->SetConnectionState(kCsSideload);
-        update_transports();
     } else {
         D("setting connection_state to kCsHost");
         t->SetConnectionState(kCsHost);
@@ -353,6 +352,8 @@
         send_auth_request(t);
     }
 #endif
+
+    update_transports();
 }
 
 void handle_packet(apacket *p, atransport *t)
@@ -1229,4 +1230,50 @@
       return ret - 1;
     return -1;
 }
+
+static auto& init_mutex = *new std::mutex();
+static auto& init_cv = *new std::condition_variable();
+static bool device_scan_complete = false;
+static bool transports_ready = false;
+
+void update_transport_status() {
+    bool result = iterate_transports([](const atransport* t) {
+        if (t->type == kTransportUsb && t->online != 1) {
+            return false;
+        }
+        return true;
+    });
+
+    D("update_transport_status: transports_ready = %s", result ? "true" : "false");
+
+    bool ready;
+
+    {
+        std::lock_guard<std::mutex> lock(init_mutex);
+        transports_ready = result;
+        ready = transports_ready && device_scan_complete;
+    }
+
+    if (ready) {
+        D("update_transport_status: notifying");
+        init_cv.notify_all();
+    }
+}
+
+void adb_notify_device_scan_complete() {
+    D("device scan complete");
+
+    {
+        std::lock_guard<std::mutex> lock(init_mutex);
+        device_scan_complete = true;
+    }
+
+    update_transport_status();
+}
+
+void adb_wait_for_device_initialization() {
+    std::unique_lock<std::mutex> lock(init_mutex);
+    init_cv.wait_for(lock, 3s, []() { return device_scan_complete && transports_ready; });
+}
+
 #endif  // ADB_HOST
diff --git a/adb/adb.h b/adb/adb.h
index e3675d8..d6b2b81 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -228,4 +228,18 @@
 
 void parse_banner(const std::string&, atransport* t);
 
+// On startup, the adb server needs to wait until all of the connected devices are ready.
+// To do this, we need to know when the scan has identified all of the potential new transports, and
+// when each transport becomes ready.
+// TODO: Do this for mDNS as well, instead of just USB?
+
+// We've found all of the transports we potentially care about.
+void adb_notify_device_scan_complete();
+
+// One or more transports have changed status, check to see if we're ready.
+void update_transport_status();
+
+// Wait until device scan has completed and every transport is ready, or a timeout elapses.
+void adb_wait_for_device_initialization();
+
 #endif
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index b656887..4f3ff25 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -28,12 +28,15 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <condition_variable>
+#include <mutex>
 #include <string>
 #include <thread>
 #include <vector>
 
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
+#include <android-base/thread_annotations.h>
 #include <cutils/sockets.h>
 
 #include "adb_io.h"
@@ -177,9 +180,8 @@
         } else {
             fprintf(stderr, "* daemon started successfully\n");
         }
-        // Give the server some time to start properly and detect devices.
-        std::this_thread::sleep_for(3s);
-        // fall through to _adb_connect
+        // The server will wait until it detects all of its connected devices before acking.
+        // Fall through to _adb_connect.
     } else {
         // If a server is already running, check its version matches.
         int version = ADB_SERVER_VERSION - 1;
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 606203c..fe5099c 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -156,33 +156,38 @@
         }
 #endif
 
-        // Inform our parent that we are up and running.
+        // Wait for the USB scan to complete before notifying the parent that we're up.
+        // We need to perform this in a thread, because we would otherwise block the event loop.
+        std::thread notify_thread([ack_reply_fd]() {
+            adb_wait_for_device_initialization();
 
-        // Any error output written to stderr now goes to adb.log. We could
-        // keep around a copy of the stderr fd and use that to write any errors
-        // encountered by the following code, but that is probably overkill.
+            // Any error output written to stderr now goes to adb.log. We could
+            // keep around a copy of the stderr fd and use that to write any errors
+            // encountered by the following code, but that is probably overkill.
 #if defined(_WIN32)
-        const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd);
-        const CHAR ack[] = "OK\n";
-        const DWORD bytes_to_write = arraysize(ack) - 1;
-        DWORD written = 0;
-        if (!WriteFile(ack_reply_handle, ack, bytes_to_write, &written, NULL)) {
-            fatal("adb: cannot write ACK to handle 0x%p: %s", ack_reply_handle,
-                  android::base::SystemErrorCodeToString(GetLastError()).c_str());
-        }
-        if (written != bytes_to_write) {
-            fatal("adb: cannot write %lu bytes of ACK: only wrote %lu bytes",
-                  bytes_to_write, written);
-        }
-        CloseHandle(ack_reply_handle);
+            const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd);
+            const CHAR ack[] = "OK\n";
+            const DWORD bytes_to_write = arraysize(ack) - 1;
+            DWORD written = 0;
+            if (!WriteFile(ack_reply_handle, ack, bytes_to_write, &written, NULL)) {
+                fatal("adb: cannot write ACK to handle 0x%p: %s", ack_reply_handle,
+                      android::base::SystemErrorCodeToString(GetLastError()).c_str());
+            }
+            if (written != bytes_to_write) {
+                fatal("adb: cannot write %lu bytes of ACK: only wrote %lu bytes", bytes_to_write,
+                      written);
+            }
+            CloseHandle(ack_reply_handle);
 #else
-        // TODO(danalbert): Can't use SendOkay because we're sending "OK\n", not
-        // "OKAY".
-        if (!android::base::WriteStringToFd("OK\n", ack_reply_fd)) {
-            fatal_errno("error writing ACK to fd %d", ack_reply_fd);
-        }
-        unix_close(ack_reply_fd);
+            // TODO(danalbert): Can't use SendOkay because we're sending "OK\n", not
+            // "OKAY".
+            if (!android::base::WriteStringToFd("OK\n", ack_reply_fd)) {
+                fatal_errno("error writing ACK to fd %d", ack_reply_fd);
+            }
+            unix_close(ack_reply_fd);
 #endif
+        });
+        notify_thread.detach();
     }
 
     D("Event loop starting");
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index d39884a..20610ee 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -352,6 +352,8 @@
         }
         libusb_free_device_list(list, 1);
 
+        adb_notify_device_scan_complete();
+
         std::this_thread::sleep_for(500ms);
     }
 }
diff --git a/adb/client/usb_osx.cpp b/adb/client/usb_osx.cpp
index e4a543b..e366754 100644
--- a/adb/client/usb_osx.cpp
+++ b/adb/client/usb_osx.cpp
@@ -38,6 +38,7 @@
 
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
+#include <android-base/thread_annotations.h>
 
 #include "adb.h"
 #include "transport.h"
@@ -429,7 +430,7 @@
     VLOG(USB) << "RunLoopThread done";
 }
 
-static void usb_cleanup() {
+static void usb_cleanup() NO_THREAD_SAFETY_ANALYSIS {
     VLOG(USB) << "usb_cleanup";
     // Wait until usb operations in RunLoopThread finish, and prevent further operations.
     operate_device_lock.lock();
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index 72c9eef..b28de4b 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -26,15 +26,19 @@
 #include <unistd.h>
 
 #include <atomic>
+#include <functional>
 #include <list>
+#include <mutex>
 #include <unordered_map>
 #include <vector>
 
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
+#include <android-base/thread_annotations.h>
 
 #include "adb_io.h"
 #include "adb_trace.h"
+#include "adb_unique_fd.h"
 #include "adb_utils.h"
 
 #if !ADB_HOST
@@ -75,6 +79,10 @@
 static bool main_thread_valid;
 static unsigned long main_thread_id;
 
+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::vector<std::function<void()>>();
+
 void check_main_thread() {
     if (main_thread_valid) {
         CHECK_EQ(main_thread_id, adb_thread_id());
@@ -112,8 +120,7 @@
     return android::base::StringPrintf("(fdevent %d %s)", fde->fd, state.c_str());
 }
 
-fdevent *fdevent_create(int fd, fd_func func, void *arg)
-{
+fdevent* fdevent_create(int fd, fd_func func, void* arg) {
     check_main_thread();
     fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
     if(fde == 0) return 0;
@@ -122,8 +129,7 @@
     return fde;
 }
 
-void fdevent_destroy(fdevent *fde)
-{
+void fdevent_destroy(fdevent* fde) {
     check_main_thread();
     if(fde == 0) return;
     if(!(fde->state & FDE_CREATED)) {
@@ -278,8 +284,7 @@
     }
 }
 
-static void fdevent_call_fdfunc(fdevent* fde)
-{
+static void fdevent_call_fdfunc(fdevent* fde) {
     unsigned events = fde->events;
     fde->events = 0;
     CHECK(fde->state & FDE_PENDING);
@@ -292,10 +297,7 @@
 
 #include <sys/ioctl.h>
 
-static void fdevent_subproc_event_func(int fd, unsigned ev,
-                                       void* /* userdata */)
-{
-
+static void fdevent_subproc_event_func(int fd, unsigned ev, void* /* userdata */) {
     D("subproc handling on fd = %d, ev = %x", fd, ev);
 
     CHECK_GE(fd, 0);
@@ -342,8 +344,7 @@
     }
 }
 
-void fdevent_subproc_setup()
-{
+static void fdevent_subproc_setup() {
     int s[2];
 
     if(adb_socketpair(s)) {
@@ -358,12 +359,63 @@
 }
 #endif // !ADB_HOST
 
-void fdevent_loop()
-{
+static void fdevent_run_flush() REQUIRES(run_queue_mutex) {
+    for (auto& f : run_queue) {
+        f();
+    }
+    run_queue.clear();
+}
+
+static void fdevent_run_func(int fd, unsigned ev, void* /* userdata */) {
+    CHECK_GE(fd, 0);
+    CHECK(ev & FDE_READ);
+
+    char buf[1024];
+
+    // Empty the fd.
+    if (adb_read(fd, buf, sizeof(buf)) == -1) {
+        PLOG(FATAL) << "failed to empty run queue notify fd";
+    }
+
+    std::lock_guard<std::mutex> lock(run_queue_mutex);
+    fdevent_run_flush();
+}
+
+static void fdevent_run_setup() {
+    std::lock_guard<std::mutex> lock(run_queue_mutex);
+    CHECK(run_queue_notify_fd.get() == -1);
+    int s[2];
+    if (adb_socketpair(s) != 0) {
+        PLOG(FATAL) << "failed to create run queue notify socketpair";
+    }
+
+    run_queue_notify_fd.reset(s[0]);
+    fdevent* fde = fdevent_create(s[1], fdevent_run_func, nullptr);
+    CHECK(fde != nullptr);
+    fdevent_add(fde, FDE_READ);
+
+    fdevent_run_flush();
+}
+
+void fdevent_run_on_main_thread(std::function<void()> fn) {
+    std::lock_guard<std::mutex> lock(run_queue_mutex);
+    run_queue.push_back(std::move(fn));
+
+    // run_queue_notify_fd could still be -1 if we're called before fdevent has finished setting up.
+    // In that case, rely on the setup code to flush the queue without a notification being needed.
+    if (run_queue_notify_fd != -1) {
+        if (adb_write(run_queue_notify_fd.get(), "", 1) != 1) {
+            PLOG(FATAL) << "failed to write to run queue notify fd";
+        }
+    }
+}
+
+void fdevent_loop() {
     set_main_thread();
 #if !ADB_HOST
     fdevent_subproc_setup();
 #endif // !ADB_HOST
+    fdevent_run_setup();
 
     while (true) {
         if (terminate_loop) {
@@ -393,6 +445,11 @@
 void fdevent_reset() {
     g_poll_node_map.clear();
     g_pending_list.clear();
+
+    std::lock_guard<std::mutex> lock(run_queue_mutex);
+    run_queue_notify_fd.reset();
+    run_queue.clear();
+
     main_thread_valid = false;
     terminate_loop = false;
 }
diff --git a/adb/fdevent.h b/adb/fdevent.h
index e32845a..896400a 100644
--- a/adb/fdevent.h
+++ b/adb/fdevent.h
@@ -20,6 +20,8 @@
 #include <stddef.h>
 #include <stdint.h>  /* for int64_t */
 
+#include <functional>
+
 /* events that may be observed */
 #define FDE_READ              0x0001
 #define FDE_WRITE             0x0002
@@ -78,6 +80,9 @@
 
 void check_main_thread();
 
+// Queue an operation to run on the main thread.
+void fdevent_run_on_main_thread(std::function<void()> fn);
+
 // The following functions are used only for tests.
 void fdevent_terminate_loop();
 size_t fdevent_installed_count();
diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp
index bdb973a..86e0209 100644
--- a/adb/fdevent_test.cpp
+++ b/adb/fdevent_test.cpp
@@ -173,3 +173,24 @@
     std::thread thread(InvalidFdThreadFunc);
     thread.join();
 }
+
+TEST_F(FdeventTest, run_on_main_thread) {
+    std::vector<int> vec;
+
+    PrepareThread();
+    std::thread thread(fdevent_loop);
+
+    for (int i = 0; i < 100; ++i) {
+        fdevent_run_on_main_thread([i, &vec]() {
+            check_main_thread();
+            vec.push_back(i);
+        });
+    }
+
+    TerminateThread(thread);
+
+    ASSERT_EQ(100u, vec.size());
+    for (int i = 0; i < 100; ++i) {
+        ASSERT_EQ(i, vec[i]);
+    }
+}
diff --git a/adb/fdevent_test.h b/adb/fdevent_test.h
index f4215ae..5ca49ac 100644
--- a/adb/fdevent_test.h
+++ b/adb/fdevent_test.h
@@ -53,11 +53,11 @@
 
     size_t GetAdditionalLocalSocketCount() {
 #if ADB_HOST
-        // dummy socket installed in PrepareThread()
-        return 1;
-#else
-        // dummy socket and one more socket installed in fdevent_subproc_setup()
+        // dummy socket installed in PrepareThread() + fdevent_run_on_main_thread socket
         return 2;
+#else
+        // dummy socket + fdevent_run_on_main_thread + fdevent_subproc_setup() sockets
+        return 3;
 #endif
     }
 
diff --git a/adb/transport.cpp b/adb/transport.cpp
index cc8c162..20de642 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -400,8 +400,27 @@
     return &tracker->socket;
 }
 
+// Check if all of the USB transports are connected.
+bool iterate_transports(std::function<bool(const atransport*)> fn) {
+    std::lock_guard<std::mutex> lock(transport_lock);
+    for (const auto& t : transport_list) {
+        if (!fn(t)) {
+            return false;
+        }
+    }
+    for (const auto& t : pending_list) {
+        if (!fn(t)) {
+            return false;
+        }
+    }
+    return true;
+}
+
 // Call this function each time the transport list has changed.
 void update_transports() {
+    update_transport_status();
+
+    // Notify `adb track-devices` clients.
     std::string transports = list_transports(false);
 
     device_tracker* tracker = device_tracker_list;
diff --git a/adb/transport.h b/adb/transport.h
index 8c15d66..e129355 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -198,6 +198,10 @@
 void kick_transport(atransport* t);
 void update_transports(void);
 
+// Iterates across all of the current and pending transports.
+// Stops iteration and returns false if fn returns false, otherwise returns true.
+bool iterate_transports(std::function<bool(const atransport*)> fn);
+
 void init_transport_registration(void);
 void init_mdns_transport_discovery(void);
 std::string list_transports(bool long_listing);
diff --git a/adb/transport_mdns.cpp b/adb/transport_mdns.cpp
index e49b1c6..3603f09 100644
--- a/adb/transport_mdns.cpp
+++ b/adb/transport_mdns.cpp
@@ -24,6 +24,8 @@
 #include <arpa/inet.h>
 #endif
 
+#include <thread>
+
 #include <android-base/stringprintf.h>
 #include <dns_sd.h>
 
@@ -262,19 +264,22 @@
     }
 }
 
-void init_mdns_transport_discovery(void) {
-    DNSServiceErrorType errorCode =
-        DNSServiceBrowse(&service_ref, 0, 0, kADBServiceType, nullptr,
-                         register_mdns_transport, nullptr);
+void init_mdns_transport_discovery_thread(void) {
+    DNSServiceErrorType errorCode = DNSServiceBrowse(&service_ref, 0, 0, kADBServiceType, nullptr,
+                                                     register_mdns_transport, nullptr);
 
     if (errorCode != kDNSServiceErr_NoError) {
         D("Got %d initiating mDNS browse.", errorCode);
         return;
     }
 
-    fdevent_install(&service_ref_fde,
-                    adb_DNSServiceRefSockFD(service_ref),
-                    pump_service_ref,
-                    &service_ref);
-    fdevent_set(&service_ref_fde, FDE_READ);
+    fdevent_run_on_main_thread([]() {
+        fdevent_install(&service_ref_fde, adb_DNSServiceRefSockFD(service_ref), pump_service_ref,
+                        &service_ref);
+        fdevent_set(&service_ref_fde, FDE_READ);
+    });
+}
+
+void init_mdns_transport_discovery(void) {
+    std::thread(init_mdns_transport_discovery_thread).detach();
 }
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index e438801..5d5ac9b 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -75,7 +75,6 @@
 char cur_product[FB_RESPONSE_SZ + 1];
 
 static const char* serial = nullptr;
-static const char* product = nullptr;
 static const char* cmdline = nullptr;
 static unsigned short vendor_id = 0;
 static int long_listing = 0;
@@ -108,66 +107,46 @@
 };
 
 static struct {
-    char img_name[17];
-    char sig_name[17];
-    char part_name[9];
+    const char* nickname;
+    const char* img_name;
+    const char* sig_name;
+    const char* part_name;
     bool is_optional;
     bool is_secondary;
 } images[] = {
-    {"boot.img", "boot.sig", "boot", false, false},
-    {"boot_other.img", "boot.sig", "boot", true, true},
-    {"recovery.img", "recovery.sig", "recovery", true, false},
-    {"system.img", "system.sig", "system", false, false},
-    {"system_other.img", "system.sig", "system", true, true},
-    {"vendor.img", "vendor.sig", "vendor", true, false},
-    {"vendor_other.img", "vendor.sig", "vendor", true, true},
-    {"vbmeta.img", "vbmeta.sig", "vbmeta", true, false},
-    {"dtbo.img", "dtbo.sig", "dtbo", true, false},
+    // clang-format off
+    { "boot",     "boot.img",         "boot.sig",     "boot",     false, false },
+    { nullptr,    "boot_other.img",   "boot.sig",     "boot",     true,  true  },
+    { "dtbo",     "dtbo.img",         "dtbo.sig",     "dtbo",     true,  false },
+    { "recovery", "recovery.img",     "recovery.sig", "recovery", true,  false },
+    { "system",   "system.img",       "system.sig",   "system",   false, false },
+    { nullptr,    "system_other.img", "system.sig",   "system",   true,  true  },
+    { "vbmeta",   "vbmeta.img",       "vbmeta.sig",   "vbmeta",   true,  false },
+    { "vendor",   "vendor.img",       "vendor.sig",   "vendor",   true,  false },
+    { nullptr,    "vendor_other.img", "vendor.sig",   "vendor",   true,  true  },
+    // clang-format on
 };
 
-static std::string find_item_given_name(const char* img_name, const char* product) {
-    if(product) {
-        std::string path = android::base::GetExecutablePath();
-        path.erase(path.find_last_of('/'));
-        return android::base::StringPrintf("%s/../../../target/product/%s/%s",
-                                           path.c_str(), product, img_name);
-    }
-
-    char *dir = getenv("ANDROID_PRODUCT_OUT");
+static std::string find_item_given_name(const char* img_name) {
+    char* dir = getenv("ANDROID_PRODUCT_OUT");
     if (dir == nullptr || dir[0] == '\0') {
-        die("neither -p product specified nor ANDROID_PRODUCT_OUT set");
+        die("ANDROID_PRODUCT_OUT not set");
     }
-
     return android::base::StringPrintf("%s/%s", dir, img_name);
 }
 
-std::string find_item(const char* item, const char* product) {
-    const char *fn;
-
-    if (!strcmp(item,"boot")) {
-        fn = "boot.img";
-    } else if(!strcmp(item,"recovery")) {
-        fn = "recovery.img";
-    } else if(!strcmp(item,"system")) {
-        fn = "system.img";
-    } else if(!strcmp(item,"vendor")) {
-        fn = "vendor.img";
-    } else if(!strcmp(item,"vbmeta")) {
-        fn = "vbmeta.img";
-    } else if(!strcmp(item,"dtbo")) {
-        fn = "dtbo.img";
-    } else if(!strcmp(item,"userdata")) {
-        fn = "userdata.img";
-    } else if(!strcmp(item,"cache")) {
-        fn = "cache.img";
-    } else if(!strcmp(item,"info")) {
-        fn = "android-info.txt";
-    } else {
-        fprintf(stderr,"unknown partition '%s'\n", item);
-        return "";
+std::string find_item(const char* item) {
+    for (size_t i = 0; i < arraysize(images); ++i) {
+        if (images[i].nickname && !strcmp(images[i].nickname, item)) {
+            return find_item_given_name(images[i].img_name);
+        }
     }
 
-    return find_item_given_name(fn, product);
+    if (!strcmp(item, "userdata")) return find_item_given_name("userdata.img");
+    if (!strcmp(item, "cache")) return find_item_given_name("cache.img");
+
+    fprintf(stderr, "unknown partition '%s'\n", item);
+    return "";
 }
 
 static int64_t get_file_size(int fd) {
@@ -391,7 +370,6 @@
             "                                           For ethernet, provide an address in the\n"
             "                                           form <protocol>:<hostname>[:port] where\n"
             "                                           <protocol> is either tcp or udp.\n"
-            "  -p <product>                             Specify product name.\n"
             "  -c <cmdline>                             Override kernel commandline.\n"
             "  -i <vendor id>                           Specify a custom USB vendor id.\n"
             "  -b, --base <base_addr>                   Specify a custom kernel base\n"
@@ -627,7 +605,7 @@
     }
 }
 
-static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) {
+static int unzip_to_file(ZipArchiveHandle zip, const char* entry_name) {
     unique_fd fd(make_temporary_fd());
     if (fd == -1) {
         fprintf(stderr, "failed to create temporary file for '%s': %s\n",
@@ -1081,9 +1059,9 @@
     flash_buf(pname, &buf);
 }
 
-static void do_update_signature(ZipArchiveHandle zip, char* fn) {
+static void do_update_signature(ZipArchiveHandle zip, const char* filename) {
     int64_t sz;
-    void* data = unzip_file(zip, fn, &sz);
+    void* data = unzip_file(zip, filename, &sz);
     if (data == nullptr) return;
     fb_queue_download("signature", data, sz);
     fb_queue_command("signature", "installing signature");
@@ -1210,7 +1188,7 @@
 
     fb_queue_query_save("product", cur_product, sizeof(cur_product));
 
-    fname = find_item("info", product);
+    fname = find_item_given_name("android-info.txt");
     if (fname.empty()) die("cannot find android-info.txt");
 
     int64_t sz;
@@ -1242,7 +1220,7 @@
             slot = slot_override.c_str();
         }
         if (!slot) continue;
-        fname = find_item_given_name(images[i].img_name, product);
+        fname = find_item_given_name(images[i].img_name);
         fastboot_buffer buf;
         if (!load_buf(transport, fname.c_str(), &buf)) {
             if (images[i].is_optional) continue;
@@ -1509,7 +1487,7 @@
     serial = getenv("ANDROID_SERIAL");
 
     while (1) {
-        int c = getopt_long(argc, argv, "wub:k:n:r:t:s:S:lp:c:i:m:ha::", longopts, &longindex);
+        int c = getopt_long(argc, argv, "wub:k:n:r:t:s:S:lc:i:m:ha::", longopts, &longindex);
         if (c < 0) {
             break;
         }
@@ -1549,9 +1527,6 @@
             page_size = (unsigned)strtoul(optarg, nullptr, 0);
             if (!page_size) die("invalid page size");
             break;
-        case 'p':
-            product = optarg;
-            break;
         case 'r':
             ramdisk_offset = strtoul(optarg, 0, 16);
             break;
@@ -1764,7 +1739,7 @@
                 fname = argv[2];
                 skip(3);
             } else {
-                fname = find_item(pname, product);
+                fname = find_item(pname);
                 skip(2);
             }
             if (fname.empty()) die("cannot determine image filename for '%s'", pname);
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 6e9069e..60ce43e 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1046,8 +1046,7 @@
         }
 
         int fs_stat = 0;
-        int force_check = do_quota_with_shutdown_check(fstab->recs[i].blk_device,
-                                                       fstab->recs[i].fs_type,
+        int force_check = do_quota_with_shutdown_check(n_blk_device, fstab->recs[i].fs_type,
                                                        &fstab->recs[i], &fs_stat);
 
         if ((fstab->recs[i].fs_mgr_flags & MF_CHECK) || force_check) {
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index 94cea57..31babfe 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -483,13 +483,34 @@
     // Only allow two verify results:
     //   - AVB_SLOT_VERIFY_RESULT_OK.
     //   - AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION (for UNLOCKED state).
-    if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION) {
-        if (!avb_verifier->IsDeviceUnlocked()) {
-            LERROR << "ERROR_VERIFICATION isn't allowed";
+    //     If the device is UNLOCKED, i.e., |allow_verification_error| is true for
+    //     AvbSlotVerify(), then the following return values are all non-fatal:
+    //       * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION
+    //       * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED
+    //       * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX
+    //     The latter two results were checked by bootloader prior to start fs_mgr so
+    //     we just need to handle the first result here. See *dummy* operations in
+    //     FsManagerAvbOps and the comments in external/avb/libavb/avb_slot_verify.h
+    //     for more details.
+    switch (verify_result) {
+        case AVB_SLOT_VERIFY_RESULT_OK:
+            avb_handle->status_ = kFsManagerAvbHandleSuccess;
+            break;
+        case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+            if (!avb_verifier->IsDeviceUnlocked()) {
+                LERROR << "ERROR_VERIFICATION isn't allowed when the device is LOCKED";
+                return nullptr;
+            }
+            avb_handle->status_ = kFsManagerAvbHandleErrorVerification;
+            break;
+        default:
+            LERROR << "avb_slot_verify failed, result: " << verify_result;
             return nullptr;
-        }
-    } else if (verify_result != AVB_SLOT_VERIFY_RESULT_OK) {
-        LERROR << "avb_slot_verify failed, result: " << verify_result;
+    }
+
+    // Verifies vbmeta images against the digest passed from bootloader.
+    if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) {
+        LERROR << "VerifyVbmetaImages failed";
         return nullptr;
     }
 
@@ -497,30 +518,20 @@
     avb_handle->avb_version_ =
         android::base::StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR);
 
-    // Verifies vbmeta images against the digest passed from bootloader.
-    if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) {
-        LERROR << "VerifyVbmetaImages failed";
-        return nullptr;
-    } else {
-        // Checks whether FLAGS_HASHTREE_DISABLED is set.
-        AvbVBMetaImageHeader vbmeta_header;
-        avb_vbmeta_image_header_to_host_byte_order(
-            (AvbVBMetaImageHeader*)avb_handle->avb_slot_data_->vbmeta_images[0].vbmeta_data,
-            &vbmeta_header);
+    // Checks whether FLAGS_HASHTREE_DISABLED is set.
+    AvbVBMetaImageHeader vbmeta_header;
+    avb_vbmeta_image_header_to_host_byte_order(
+        (AvbVBMetaImageHeader*)avb_handle->avb_slot_data_->vbmeta_images[0].vbmeta_data,
+        &vbmeta_header);
 
-        bool hashtree_disabled =
-            ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
-        if (hashtree_disabled) {
-            avb_handle->status_ = kFsManagerAvbHandleHashtreeDisabled;
-            return avb_handle;
-        }
+    bool hashtree_disabled =
+        ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
+    if (hashtree_disabled) {
+        avb_handle->status_ = kFsManagerAvbHandleHashtreeDisabled;
     }
 
-    if (verify_result == AVB_SLOT_VERIFY_RESULT_OK) {
-        avb_handle->status_ = kFsManagerAvbHandleSuccess;
-        return avb_handle;
-    }
-    return nullptr;
+    LINFO << "Returning avb_handle with status: " << avb_handle->status_;
+    return avb_handle;
 }
 
 bool FsManagerAvbHandle::SetUpAvb(struct fstab_rec* fstab_entry, bool wait_for_verity_dev) {
@@ -528,11 +539,12 @@
     if (!avb_slot_data_ || avb_slot_data_->num_vbmeta_images < 1) {
         return false;
     }
+
+    if (status_ == kFsManagerAvbHandleUninitialized) return false;
     if (status_ == kFsManagerAvbHandleHashtreeDisabled) {
         LINFO << "AVB HASHTREE disabled on:" << fstab_entry->mount_point;
         return true;
     }
-    if (status_ != kFsManagerAvbHandleSuccess) return false;
 
     std::string partition_name(basename(fstab_entry->mount_point));
     if (!avb_validate_utf8((const uint8_t*)partition_name.c_str(), partition_name.length())) {
diff --git a/fs_mgr/include/fs_mgr_avb.h b/fs_mgr/include/fs_mgr_avb.h
index a66ff42..65ff9941 100644
--- a/fs_mgr/include/fs_mgr_avb.h
+++ b/fs_mgr/include/fs_mgr_avb.h
@@ -25,9 +25,10 @@
 #include "fs_mgr.h"
 
 enum FsManagerAvbHandleStatus {
+    kFsManagerAvbHandleUninitialized = -1,
     kFsManagerAvbHandleSuccess = 0,
     kFsManagerAvbHandleHashtreeDisabled = 1,
-    kFsManagerAvbHandleFail = 2,
+    kFsManagerAvbHandleErrorVerification = 2,
 };
 
 class FsManagerAvbHandle;
@@ -88,7 +89,7 @@
     };
 
   protected:
-    FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleFail) {}
+    FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleUninitialized) {}
 
   private:
     AvbSlotVerifyData* avb_slot_data_;
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index aa755ed..d6ead1a 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -95,13 +95,3 @@
 LOCAL_MODULE := grep
 LOCAL_POST_INSTALL_CMD := $(hide) $(foreach t,egrep fgrep,ln -sf grep $(TARGET_OUT)/bin/$(t);)
 include $(BUILD_EXECUTABLE)
-
-
-# We build gzip separately, so it can provide gunzip and zcat too.
-include $(CLEAR_VARS)
-LOCAL_MODULE := gzip
-LOCAL_SRC_FILES := gzip.c
-LOCAL_CFLAGS += -Wall -Werror
-LOCAL_SHARED_LIBRARIES += libz
-LOCAL_POST_INSTALL_CMD := $(hide) $(foreach t,gunzip zcat,ln -sf gzip $(TARGET_OUT)/bin/$(t);)
-include $(BUILD_EXECUTABLE)
diff --git a/toolbox/gzip.c b/toolbox/gzip.c
deleted file mode 100644
index 62c4518..0000000
--- a/toolbox/gzip.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/* gzip.c - gzip/gunzip/zcat tools for gzip data
- *
- * Copyright 2017 The Android Open Source Project
- *
- * GZIP RFC: http://www.ietf.org/rfc/rfc1952.txt
-
-TODO: port to toybox.
-
-*/
-
-#define _GNU_SOURCE
-
-#include <errno.h>
-#include <error.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#include <zlib.h>
-
-// toybox-style flags/globals.
-#define FLAG_c 1
-#define FLAG_d 2
-#define FLAG_f 4
-#define FLAG_k 8
-static struct {
-  int optflags;
-} toys;
-static struct {
-  int level;
-} TT;
-
-static void xstat(const char *path, struct stat *sb)
-{
-  if (stat(path, sb)) error(1, errno, "stat %s", path);
-}
-
-static void fix_time(const char *path, struct stat *sb)
-{
-  struct timespec times[] = { sb->st_atim, sb->st_mtim };
-
-  if (utimensat(AT_FDCWD, path, times, 0)) error(1, errno, "utimes");
-}
-
-static FILE *xfdopen(const char *name, int flags, mode_t open_mode,
-    const char *mode)
-{
-  FILE *fp;
-  int fd;
-
-  if (!strcmp(name, "-")) fd = dup((*mode == 'r') ? 0 : 1);
-  else fd = open(name, flags, open_mode);
-
-  if (fd == -1) error(1, errno, "open %s (%s)", name, mode);
-  fp = fdopen(fd, mode);
-  if (fp == NULL) error(1, errno, "fopen %s (%s)", name, mode);
-  return fp;
-}
-
-static gzFile xgzopen(const char *name, int flags, mode_t open_mode,
-    const char *mode)
-{
-  gzFile f;
-  int fd;
-
-  if (!strcmp(name, "-")) fd = dup((*mode == 'r') ? 0 : 1);
-  else fd = open(name, flags, open_mode);
-
-  if (fd == -1) error(1, errno, "open %s (%s)", name, mode);
-  f = gzdopen(fd, mode);
-  if (f == NULL) error(1, errno, "gzdopen %s (%s)", name, mode);
-  return f;
-}
-
-static void gzfatal(gzFile f, char *what)
-{
-  int err;
-  const char *msg = gzerror(f, &err);
-
-  error(1, (err == Z_ERRNO) ? errno : 0, "%s: %s", what, msg);
-}
-
-static void gunzip(char *arg)
-{
-  struct stat sb;
-  char buf[BUFSIZ];
-  int len, both_files;
-  char *in_name, *out_name;
-  gzFile in;
-  FILE *out;
-
-  // "gunzip x.gz" will decompress "x.gz" to "x".
-  len = strlen(arg);
-  if (len > 3 && !strcmp(arg+len-3, ".gz")) {
-    in_name = strdup(arg);
-    out_name = strdup(arg);
-    out_name[len-3] = '\0';
-  } else if (!strcmp(arg, "-")) {
-    // "-" means stdin; assume output to stdout.
-    // TODO: require -f to read compressed data from tty?
-    in_name = strdup("-");
-    out_name = strdup("-");
-  } else error(1, 0, "unknown suffix");
-
-  if (toys.optflags&FLAG_c) {
-    free(out_name);
-    out_name = strdup("-");
-  }
-
-  both_files = strcmp(in_name, "-") && strcmp(out_name, "-");
-  if (both_files) xstat(in_name, &sb);
-
-  in = xgzopen(in_name, O_RDONLY, 0, "r");
-  out = xfdopen(out_name, O_CREAT|O_WRONLY|((toys.optflags&FLAG_f)?0:O_EXCL),
-      both_files?sb.st_mode:0666, "w");
-
-  while ((len = gzread(in, buf, sizeof(buf))) > 0) {
-    if (fwrite(buf, 1, len, out) != (size_t) len) error(1, errno, "fwrite");
-  }
-  if (len < 0) gzfatal(in, "gzread");
-  if (fclose(out)) error(1, errno, "fclose");
-  if (gzclose(in) != Z_OK) error(1, 0, "gzclose");
-
-  if (both_files) fix_time(out_name, &sb);
-  if (!(toys.optflags&(FLAG_c|FLAG_k))) unlink(in_name);
-  free(in_name);
-  free(out_name);
-}
-
-static void gzip(char *in_name)
-{
-  char buf[BUFSIZ];
-  size_t len;
-  char *out_name;
-  FILE *in;
-  gzFile out;
-  struct stat sb;
-  int both_files;
-
-  if (toys.optflags&FLAG_c) {
-    out_name = strdup("-");
-  } else {
-    if (asprintf(&out_name, "%s.gz", in_name) == -1) {
-      error(1, errno, "asprintf");
-    }
-  }
-
-  both_files = strcmp(in_name, "-") && strcmp(out_name, "-");
-  if (both_files) xstat(in_name, &sb);
-
-  snprintf(buf, sizeof(buf), "w%d", TT.level);
-  in = xfdopen(in_name, O_RDONLY, 0, "r");
-  out = xgzopen(out_name, O_CREAT|O_WRONLY|((toys.optflags&FLAG_f)?0:O_EXCL),
-      both_files?sb.st_mode:0, buf);
-
-  while ((len = fread(buf, 1, sizeof(buf), in)) > 0) {
-    if (gzwrite(out, buf, len) != (int) len) gzfatal(out, "gzwrite");
-  }
-  if (ferror(in)) error(1, errno, "fread");
-  if (fclose(in)) error(1, errno, "fclose");
-  if (gzclose(out) != Z_OK) error(1, 0, "gzclose");
-
-  if (both_files) fix_time(out_name, &sb);
-  if (!(toys.optflags&(FLAG_c|FLAG_k))) unlink(in_name);
-  free(out_name);
-}
-
-static void do_file(char *arg)
-{
-  if (toys.optflags&FLAG_d) gunzip(arg);
-  else gzip(arg);
-}
-
-static void usage()
-{
-  char *cmd = basename(getprogname());
-
-  printf("usage: %s [-c] [-d] [-f] [-#] [FILE...]\n", cmd);
-  printf("\n");
-  if (!strcmp(cmd, "zcat")) {
-    printf("Decompress files to stdout. Like `gzip -dc`.\n");
-    printf("\n");
-    printf("-c\tOutput to stdout\n");
-    printf("-f\tForce: allow read from tty\n");
-  } else if (!strcmp(cmd, "gunzip")) {
-    printf("Decompress files. With no files, decompresses stdin to stdout.\n");
-    printf("On success, the input files are removed and replaced by new\n");
-    printf("files without the .gz suffix.\n");
-    printf("\n");
-    printf("-c\tOutput to stdout\n");
-    printf("-f\tForce: allow read from tty\n");
-    printf("-k\tKeep input files (don't remove)\n");
-  } else { // gzip
-    printf("Compress files. With no files, compresses stdin to stdout.\n");
-    printf("On success, the input files are removed and replaced by new\n");
-    printf("files with the .gz suffix.\n");
-    printf("\n");
-    printf("-c\tOutput to stdout\n");
-    printf("-d\tDecompress (act as gunzip)\n");
-    printf("-f\tForce: allow overwrite of output file\n");
-    printf("-k\tKeep input files (don't remove)\n");
-    printf("-#\tCompression level 1-9 (1:fastest, 6:default, 9:best)\n");
-  }
-  printf("\n");
-}
-
-int main(int argc, char *argv[])
-{
-  char *cmd = basename(argv[0]);
-  int opt_ch;
-
-  toys.optflags = 0;
-  TT.level = 6;
-
-  if (!strcmp(cmd, "gunzip")) {
-    // gunzip == gzip -d
-    toys.optflags = FLAG_d;
-  } else if (!strcmp(cmd, "zcat")) {
-    // zcat == gzip -dc
-    toys.optflags = (FLAG_c|FLAG_d);
-  }
-
-  while ((opt_ch = getopt(argc, argv, "cdfhk123456789")) != -1) {
-    switch (opt_ch) {
-    case 'c': toys.optflags |= FLAG_c; break;
-    case 'd': toys.optflags |= FLAG_d; break;
-    case 'f': toys.optflags |= FLAG_f; break;
-    case 'k': toys.optflags |= FLAG_k; break;
-
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
-    case '8':
-    case '9':
-      TT.level = opt_ch - '0';
-      break;
-
-    default:
-      usage();
-      return 1;
-    }
-  }
-
-  if (optind == argc) {
-    // With no arguments, we go from stdin to stdout.
-    toys.optflags |= FLAG_c;
-    do_file("-");
-    return 0;
-  }
-
-  // Otherwise process each file in turn.
-  while (optind < argc) do_file(argv[optind++]);
-  return 0;
-}
diff --git a/trusty/Android.bp b/trusty/Android.bp
index 1b2e2c7..9681488 100644
--- a/trusty/Android.bp
+++ b/trusty/Android.bp
@@ -1,3 +1,4 @@
 subdirs = [
     "libtrusty",
+    "storage/*",
 ]
diff --git a/trusty/storage/interface/Android.bp b/trusty/storage/interface/Android.bp
new file mode 100644
index 0000000..a551c37
--- /dev/null
+++ b/trusty/storage/interface/Android.bp
@@ -0,0 +1,20 @@
+//
+// Copyright (C) 2015 The Android Open-Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+    name: "libtrustystorageinterface",
+    export_include_dirs: ["include"],
+}
diff --git a/trusty/storage/interface/Android.mk b/trusty/storage/interface/Android.mk
deleted file mode 100644
index 15cb6f3..0000000
--- a/trusty/storage/interface/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Copyright (C) 2015 The Android Open-Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libtrustystorageinterface
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/trusty/storage/lib/Android.bp b/trusty/storage/lib/Android.bp
new file mode 100644
index 0000000..5eb3f07
--- /dev/null
+++ b/trusty/storage/lib/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2015 The Android Open-Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+    name: "libtrustystorage",
+
+    srcs: ["storage.c"],
+
+    export_include_dirs: ["include"],
+
+    static_libs: [
+        "liblog",
+        "libtrusty",
+        "libtrustystorageinterface",
+    ],
+
+    cflags: [
+        "-fvisibility=hidden",
+        "-Wall",
+        "-Werror",
+    ]
+}
diff --git a/trusty/storage/lib/Android.mk b/trusty/storage/lib/Android.mk
deleted file mode 100644
index 7e0fc9d..0000000
--- a/trusty/storage/lib/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright (C) 2015 The Android Open-Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libtrustystorage
-
-LOCAL_SRC_FILES := \
-	storage.c \
-
-LOCAL_CLFAGS = -fvisibility=hidden -Wall -Werror
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-
-LOCAL_STATIC_LIBRARIES := \
-	liblog \
-	libtrusty \
-	libtrustystorageinterface
-
-include $(BUILD_STATIC_LIBRARY)
-
diff --git a/trusty/storage/proxy/Android.bp b/trusty/storage/proxy/Android.bp
new file mode 100644
index 0000000..eb34df0
--- /dev/null
+++ b/trusty/storage/proxy/Android.bp
@@ -0,0 +1,38 @@
+//
+// 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.
+//
+
+cc_binary {
+    name: "storageproxyd",
+
+    srcs: [
+        "ipc.c",
+        "rpmb.c",
+        "storage.c",
+        "proxy.c",
+    ],
+
+    shared_libs: ["liblog"],
+
+    static_libs: [
+        "libtrustystorageinterface",
+        "libtrusty",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ]
+}
diff --git a/trusty/storage/proxy/Android.mk b/trusty/storage/proxy/Android.mk
deleted file mode 100644
index 745e302..0000000
--- a/trusty/storage/proxy/Android.mk
+++ /dev/null
@@ -1,41 +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)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := storageproxyd
-
-LOCAL_C_INCLUDES += bionic/libc/kernel/uapi
-
-LOCAL_SRC_FILES := \
-	ipc.c \
-	rpmb.c \
-	storage.c \
-	proxy.c
-
-LOCAL_CLFAGS = -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES := \
-	liblog \
-
-LOCAL_STATIC_LIBRARIES := \
-	libtrustystorageinterface \
-	libtrusty
-
-include $(BUILD_EXECUTABLE)
-
diff --git a/trusty/storage/proxy/proxy.c b/trusty/storage/proxy/proxy.c
index d645ac0..27e5891 100644
--- a/trusty/storage/proxy/proxy.c
+++ b/trusty/storage/proxy/proxy.c
@@ -229,7 +229,6 @@
 int main(int argc, char *argv[])
 {
     int rc;
-    uint retry_cnt;
 
     /* drop privileges */
     if (drop_privs() < 0)
diff --git a/trusty/storage/tests/Android.bp b/trusty/storage/tests/Android.bp
new file mode 100644
index 0000000..3eff3f2
--- /dev/null
+++ b/trusty/storage/tests/Android.bp
@@ -0,0 +1,36 @@
+//
+// 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.
+//
+
+cc_test {
+    name: "secure-storage-unit-test",
+
+    cflags: [
+        "-g",
+        "-Wall",
+        "-Werror",
+        "-std=gnu++11",
+        "-Wno-missing-field-initializers",
+    ],
+
+    static_libs: [
+        "libtrustystorageinterface",
+        "libtrustystorage",
+        "libtrusty",
+        "liblog",
+    ],
+
+    srcs: ["main.cpp"],
+}
diff --git a/trusty/storage/tests/Android.mk b/trusty/storage/tests/Android.mk
deleted file mode 100644
index 71c904d..0000000
--- a/trusty/storage/tests/Android.mk
+++ /dev/null
@@ -1,29 +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)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := secure-storage-unit-test
-LOCAL_CFLAGS += -g -Wall -Werror -std=gnu++11 -Wno-missing-field-initializers
-LOCAL_STATIC_LIBRARIES := \
-	libtrustystorageinterface \
-	libtrustystorage \
-	libtrusty \
-	liblog
-LOCAL_SRC_FILES := main.cpp
-include $(BUILD_NATIVE_TEST)
-