Merge "adbd: fallback to legacy USB implementation if needed." am: f80c326d2e

am: dc50e92b71

Change-Id: I13f84f80a1f5b9da962e40dcdf33f9d7a95a9c0f
This commit is contained in:
Josh Gao 2019-02-16 20:25:53 -08:00 committed by android-build-merger
commit 8b47738b0a

View file

@ -53,6 +53,9 @@
using android::base::StringPrintf; using android::base::StringPrintf;
// We can't find out whether we have support for AIO on ffs endpoints until we submit a read.
static std::optional<bool> gFfsAioSupported;
static constexpr size_t kUsbReadQueueDepth = 16; static constexpr size_t kUsbReadQueueDepth = 16;
static constexpr size_t kUsbReadSize = 16384; static constexpr size_t kUsbReadSize = 16384;
@ -169,8 +172,13 @@ struct UsbFfsConnection : public Connection {
read_fd_(std::move(read)), read_fd_(std::move(read)),
write_fd_(std::move(write)) { write_fd_(std::move(write)) {
LOG(INFO) << "UsbFfsConnection constructed"; LOG(INFO) << "UsbFfsConnection constructed";
event_fd_.reset(eventfd(0, EFD_CLOEXEC)); worker_event_fd_.reset(eventfd(0, EFD_CLOEXEC));
if (event_fd_ == -1) { if (worker_event_fd_ == -1) {
PLOG(FATAL) << "failed to create eventfd";
}
monitor_event_fd_.reset(eventfd(0, EFD_CLOEXEC));
if (monitor_event_fd_ == -1) {
PLOG(FATAL) << "failed to create eventfd"; PLOG(FATAL) << "failed to create eventfd";
} }
@ -181,6 +189,13 @@ struct UsbFfsConnection : public Connection {
LOG(INFO) << "UsbFfsConnection being destroyed"; LOG(INFO) << "UsbFfsConnection being destroyed";
Stop(); Stop();
monitor_thread_.join(); monitor_thread_.join();
// We need to explicitly close our file descriptors before we notify our destruction,
// because the thread listening on the future will immediately try to reopen the endpoint.
control_fd_.reset();
read_fd_.reset();
write_fd_.reset();
destruction_notifier_.set_value(); destruction_notifier_.set_value();
} }
@ -207,11 +222,18 @@ struct UsbFfsConnection : public Connection {
} }
stopped_ = true; stopped_ = true;
uint64_t notify = 1; uint64_t notify = 1;
ssize_t rc = adb_write(event_fd_.get(), &notify, sizeof(notify)); ssize_t rc = adb_write(worker_event_fd_.get(), &notify, sizeof(notify));
if (rc < 0) { if (rc < 0) {
PLOG(FATAL) << "failed to notify eventfd to stop UsbFfsConnection"; PLOG(FATAL) << "failed to notify worker eventfd to stop UsbFfsConnection";
} }
CHECK_EQ(static_cast<size_t>(rc), sizeof(notify)); CHECK_EQ(static_cast<size_t>(rc), sizeof(notify));
rc = adb_write(monitor_event_fd_.get(), &notify, sizeof(notify));
if (rc < 0) {
PLOG(FATAL) << "failed to notify monitor eventfd to stop UsbFfsConnection";
}
CHECK_EQ(static_cast<size_t>(rc), sizeof(notify));
} }
private: private:
@ -235,22 +257,33 @@ struct UsbFfsConnection : public Connection {
bool started = false; bool started = false;
bool running = true; bool running = true;
while (running) { while (running) {
int timeout = -1;
if (!bound || !started) { if (!bound || !started) {
adb_pollfd pfd = {.fd = control_fd_.get(), .events = POLLIN, .revents = 0}; timeout = 5000 /*ms*/;
int rc = TEMP_FAILURE_RETRY(adb_poll(&pfd, 1, 5000 /*ms*/)); }
if (rc == -1) {
PLOG(FATAL) << "poll on USB control fd failed"; adb_pollfd pfd[2] = {
} else if (rc == 0) { { .fd = control_fd_.get(), .events = POLLIN, .revents = 0 },
// Something in the kernel presumably went wrong. { .fd = monitor_event_fd_.get(), .events = POLLIN, .revents = 0 },
// Close our endpoints, wait for a bit, and then try again. };
aio_context_.reset(); int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, timeout));
read_fd_.reset(); if (rc == -1) {
write_fd_.reset(); PLOG(FATAL) << "poll on USB control fd failed";
control_fd_.reset(); } else if (rc == 0) {
std::this_thread::sleep_for(5s); // Something in the kernel presumably went wrong.
HandleError("didn't receive FUNCTIONFS_ENABLE, retrying"); // Close our endpoints, wait for a bit, and then try again.
return; aio_context_.reset();
} read_fd_.reset();
write_fd_.reset();
control_fd_.reset();
std::this_thread::sleep_for(5s);
HandleError("didn't receive FUNCTIONFS_ENABLE, retrying");
return;
}
if (pfd[1].revents) {
// We were told to die.
break;
} }
struct usb_functionfs_event event; struct usb_functionfs_event event;
@ -313,12 +346,14 @@ struct UsbFfsConnection : public Connection {
adb_thread_setname("UsbFfs-worker"); adb_thread_setname("UsbFfs-worker");
for (size_t i = 0; i < kUsbReadQueueDepth; ++i) { for (size_t i = 0; i < kUsbReadQueueDepth; ++i) {
read_requests_[i] = CreateReadBlock(next_read_id_++); read_requests_[i] = CreateReadBlock(next_read_id_++);
SubmitRead(&read_requests_[i]); if (!SubmitRead(&read_requests_[i])) {
return;
}
} }
while (!stopped_) { while (!stopped_) {
uint64_t dummy; uint64_t dummy;
ssize_t rc = adb_read(event_fd_.get(), &dummy, sizeof(dummy)); ssize_t rc = adb_read(worker_event_fd_.get(), &dummy, sizeof(dummy));
if (rc == -1) { if (rc == -1) {
PLOG(FATAL) << "failed to read from eventfd"; PLOG(FATAL) << "failed to read from eventfd";
} else if (rc == 0) { } else if (rc == 0) {
@ -347,7 +382,7 @@ struct UsbFfsConnection : public Connection {
block.control.aio_fildes = read_fd_.get(); block.control.aio_fildes = read_fd_.get();
block.control.aio_offset = 0; block.control.aio_offset = 0;
block.control.aio_flags = IOCB_FLAG_RESFD; block.control.aio_flags = IOCB_FLAG_RESFD;
block.control.aio_resfd = event_fd_.get(); block.control.aio_resfd = worker_event_fd_.get();
return block; return block;
} }
@ -438,13 +473,22 @@ struct UsbFfsConnection : public Connection {
SubmitRead(block); SubmitRead(block);
} }
void SubmitRead(IoBlock* block) { bool SubmitRead(IoBlock* block) {
block->pending = true; block->pending = true;
struct iocb* iocb = &block->control; struct iocb* iocb = &block->control;
if (io_submit(aio_context_.get(), 1, &iocb) != 1) { if (io_submit(aio_context_.get(), 1, &iocb) != 1) {
if (errno == EINVAL && !gFfsAioSupported.has_value()) {
HandleError("failed to submit first read, AIO on FFS not supported");
gFfsAioSupported = false;
return false;
}
HandleError(StringPrintf("failed to submit read: %s", strerror(errno))); HandleError(StringPrintf("failed to submit read: %s", strerror(errno)));
return; return false;
} }
gFfsAioSupported = true;
return true;
} }
void HandleWrite(TransferId id) { void HandleWrite(TransferId id) {
@ -474,7 +518,7 @@ struct UsbFfsConnection : public Connection {
block->control.aio_nbytes = block->payload.size(); block->control.aio_nbytes = block->payload.size();
block->control.aio_offset = 0; block->control.aio_offset = 0;
block->control.aio_flags = IOCB_FLAG_RESFD; block->control.aio_flags = IOCB_FLAG_RESFD;
block->control.aio_resfd = event_fd_.get(); block->control.aio_resfd = worker_event_fd_.get();
return block; return block;
} }
@ -526,7 +570,8 @@ struct UsbFfsConnection : public Connection {
std::promise<void> destruction_notifier_; std::promise<void> destruction_notifier_;
std::once_flag error_flag_; std::once_flag error_flag_;
unique_fd event_fd_; unique_fd worker_event_fd_;
unique_fd monitor_event_fd_;
ScopedAioContext aio_context_; ScopedAioContext aio_context_;
unique_fd control_fd_; unique_fd control_fd_;
@ -551,10 +596,17 @@ struct UsbFfsConnection : public Connection {
size_t writes_submitted_ GUARDED_BY(write_mutex_) = 0; size_t writes_submitted_ GUARDED_BY(write_mutex_) = 0;
}; };
void usb_init_legacy();
static void usb_ffs_open_thread() { static void usb_ffs_open_thread() {
adb_thread_setname("usb ffs open"); adb_thread_setname("usb ffs open");
while (true) { while (true) {
if (gFfsAioSupported.has_value() && !gFfsAioSupported.value()) {
LOG(INFO) << "failed to use nonblocking ffs, falling back to legacy";
return usb_init_legacy();
}
unique_fd control; unique_fd control;
unique_fd bulk_out; unique_fd bulk_out;
unique_fd bulk_in; unique_fd bulk_in;
@ -575,7 +627,6 @@ static void usb_ffs_open_thread() {
} }
} }
void usb_init_legacy();
void usb_init() { void usb_init() {
if (!android::base::GetBoolProperty("persist.adb.nonblocking_ffs", false)) { if (!android::base::GetBoolProperty("persist.adb.nonblocking_ffs", false)) {
usb_init_legacy(); usb_init_legacy();