Merge "adb: reunregress waiting for device on start-server." am: 72076d1aa7
am: 08a70ac6e5
Change-Id: Ie379f49929c8b11544328694fd1a438e63da453d
This commit is contained in:
commit
986ba5bbbb
3 changed files with 66 additions and 20 deletions
|
|
@ -1257,6 +1257,10 @@ void update_transport_status() {
|
||||||
void adb_notify_device_scan_complete() {
|
void adb_notify_device_scan_complete() {
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(init_mutex);
|
std::lock_guard<std::mutex> lock(init_mutex);
|
||||||
|
if (device_scan_complete) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
device_scan_complete = true;
|
device_scan_complete = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,10 @@
|
||||||
#ifndef _ADB_UTILS_H_
|
#ifndef _ADB_UTILS_H_
|
||||||
#define _ADB_UTILS_H_
|
#define _ADB_UTILS_H_
|
||||||
|
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <android-base/macros.h>
|
#include <android-base/macros.h>
|
||||||
|
|
||||||
|
|
@ -53,4 +56,32 @@ extern int adb_close(int fd);
|
||||||
bool forward_targets_are_valid(const std::string& source, const std::string& dest,
|
bool forward_targets_are_valid(const std::string& source, const std::string& dest,
|
||||||
std::string* error);
|
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
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
#include <android-base/strings.h>
|
#include <android-base/strings.h>
|
||||||
|
|
||||||
#include "adb.h"
|
#include "adb.h"
|
||||||
|
#include "adb_utils.h"
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
|
|
@ -387,10 +388,9 @@ static std::atomic<int> connecting_devices(0);
|
||||||
static void device_connected(libusb_device* device) {
|
static void device_connected(libusb_device* device) {
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
// Android's host linux libusb uses netlink instead of udev for device hotplug notification,
|
// 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
|
// which means we can get hotplug notifications before udev has updated ownership/perms on
|
||||||
// device. Since we're not going to be able to link against the system's libudev any time soon,
|
// the device. Since we're not going to be able to link against the system's libudev any
|
||||||
// hack around this by checking for accessibility in a loop.
|
// time soon, hack around this by checking for accessibility in a loop.
|
||||||
++connecting_devices;
|
|
||||||
auto thread = std::thread([device]() {
|
auto thread = std::thread([device]() {
|
||||||
std::string device_path = get_device_dev_path(device);
|
std::string device_path = get_device_dev_path(device);
|
||||||
auto start = std::chrono::steady_clock::now();
|
auto start = std::chrono::steady_clock::now();
|
||||||
|
|
@ -402,7 +402,9 @@ static void device_connected(libusb_device* device) {
|
||||||
}
|
}
|
||||||
|
|
||||||
process_device(device);
|
process_device(device);
|
||||||
--connecting_devices;
|
if (--connecting_devices == 0) {
|
||||||
|
adb_notify_device_scan_complete();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
thread.detach();
|
thread.detach();
|
||||||
#else
|
#else
|
||||||
|
|
@ -425,17 +427,33 @@ static void device_disconnected(libusb_device* device) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
static int hotplug_callback(libusb_context*, libusb_device* device, libusb_hotplug_event event,
|
||||||
void*) {
|
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.
|
// function so that the usb_handle mutex is always taken before the libusb mutex.
|
||||||
fdevent_run_on_main_thread([device, event]() {
|
static std::once_flag once;
|
||||||
if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
|
std::call_once(once, []() { std::thread(hotplug_thread).detach(); });
|
||||||
device_connected(device);
|
|
||||||
} else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
|
if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
|
||||||
device_disconnected(device);
|
++connecting_devices;
|
||||||
}
|
}
|
||||||
});
|
hotplug_queue.Push({event, device});
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -457,13 +475,6 @@ void usb_init() {
|
||||||
LOG(FATAL) << "failed to register libusb hotplug callback";
|
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.
|
// Spawn a thread for libusb_handle_events.
|
||||||
std::thread([]() {
|
std::thread([]() {
|
||||||
adb_thread_setname("libusb");
|
adb_thread_setname("libusb");
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue