adb: reunregress waiting for device on start-server.

Move the invocation of adb_notify_device_scan_complete to
the end of device_connected, where we decrement connecting_devices.
Also, create a dedicated thread for handling hotplug events, instead of
reusing the main thread for this, since the main thread blocks until
device scan is complete.

Test: `adb kill-server; adb devices`
Change-Id: Ia73b1a57538174282a48ef73ab0a3e58152d6f83
diff --git a/adb.cpp b/adb.cpp
index a7706a0..bfb1144 100644
--- a/adb.cpp
+++ b/adb.cpp
@@ -1257,6 +1257,10 @@
 void adb_notify_device_scan_complete() {
     {
         std::lock_guard<std::mutex> lock(init_mutex);
+        if (device_scan_complete) {
+            return;
+        }
+
         device_scan_complete = true;
     }
 
diff --git a/adb_utils.h b/adb_utils.h
index c1d5549..20c63b3 100644
--- a/adb_utils.h
+++ b/adb_utils.h
@@ -17,7 +17,10 @@
 #ifndef _ADB_UTILS_H_
 #define _ADB_UTILS_H_
 
+#include <condition_variable>
+#include <mutex>
 #include <string>
+#include <vector>
 
 #include <android-base/macros.h>
 
@@ -53,4 +56,32 @@
 bool forward_targets_are_valid(const std::string& source, const std::string& dest,
                                std::string* error);
 
+// A thread-safe blocking queue.
+template <typename T>
+class BlockingQueue {
+    std::mutex mutex;
+    std::condition_variable cv;
+    std::vector<T> queue;
+
+  public:
+    void Push(const T& t) {
+        {
+            std::unique_lock<std::mutex> lock(mutex);
+            queue.push_back(t);
+        }
+        cv.notify_one();
+    }
+
+    template <typename Fn>
+    void PopAll(Fn fn) {
+        std::unique_lock<std::mutex> lock(mutex);
+        cv.wait(lock, [this]() { return !queue.empty(); });
+
+        for (const T& t : queue) {
+            fn(t);
+        }
+        queue.clear();
+    }
+};
+
 #endif
diff --git a/client/usb_libusb.cpp b/client/usb_libusb.cpp
index 9477c56..7e77b5e 100644
--- a/client/usb_libusb.cpp
+++ b/client/usb_libusb.cpp
@@ -37,6 +37,7 @@
 #include <android-base/strings.h>
 
 #include "adb.h"
+#include "adb_utils.h"
 #include "transport.h"
 #include "usb.h"
 
@@ -387,10 +388,9 @@
 static void device_connected(libusb_device* device) {
 #if defined(__linux__)
     // Android's host linux libusb uses netlink instead of udev for device hotplug notification,
-    // which means we can get hotplug notifications before udev has updated ownership/perms on the
-    // device. Since we're not going to be able to link against the system's libudev any time soon,
-    // hack around this by checking for accessibility in a loop.
-    ++connecting_devices;
+    // which means we can get hotplug notifications before udev has updated ownership/perms on
+    // the device. Since we're not going to be able to link against the system's libudev any
+    // time soon, hack around this by checking for accessibility in a loop.
     auto thread = std::thread([device]() {
         std::string device_path = get_device_dev_path(device);
         auto start = std::chrono::steady_clock::now();
@@ -402,7 +402,9 @@
         }
 
         process_device(device);
-        --connecting_devices;
+        if (--connecting_devices == 0) {
+            adb_notify_device_scan_complete();
+        }
     });
     thread.detach();
 #else
@@ -425,17 +427,33 @@
     }
 }
 
+static auto& hotplug_queue = *new BlockingQueue<std::pair<libusb_hotplug_event, libusb_device*>>();
+static void hotplug_thread() {
+    adb_thread_setname("libusb hotplug");
+    while (true) {
+        hotplug_queue.PopAll([](std::pair<libusb_hotplug_event, libusb_device*> pair) {
+            libusb_hotplug_event event = pair.first;
+            libusb_device* device = pair.second;
+            if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
+                device_connected(device);
+            } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
+                device_disconnected(device);
+            }
+        });
+    }
+}
+
 static int hotplug_callback(libusb_context*, libusb_device* device, libusb_hotplug_event event,
                             void*) {
-    // We're called with the libusb lock taken. Call these on the main thread outside of this
+    // We're called with the libusb lock taken. Call these on a separate thread outside of this
     // function so that the usb_handle mutex is always taken before the libusb mutex.
-    fdevent_run_on_main_thread([device, event]() {
-        if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
-            device_connected(device);
-        } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
-            device_disconnected(device);
-        }
-    });
+    static std::once_flag once;
+    std::call_once(once, []() { std::thread(hotplug_thread).detach(); });
+
+    if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
+        ++connecting_devices;
+    }
+    hotplug_queue.Push({event, device});
     return 0;
 }
 
@@ -457,13 +475,6 @@
         LOG(FATAL) << "failed to register libusb hotplug callback";
     }
 
-    // Wait for all of the connecting devices to finish.
-    while (connecting_devices != 0) {
-        std::this_thread::sleep_for(10ms);
-    }
-
-    adb_notify_device_scan_complete();
-
     // Spawn a thread for libusb_handle_events.
     std::thread([]() {
         adb_thread_setname("libusb");