2009-03-04 04:32:55 +01:00
|
|
|
/*
|
|
|
|
* Copyright (C) 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
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2015-09-23 00:52:57 +02:00
|
|
|
#define TRACE_TAG TRANSPORT
|
2015-02-25 00:51:19 +01:00
|
|
|
|
2015-03-19 23:21:08 +01:00
|
|
|
#include "sysdeps.h"
|
2015-02-25 00:51:19 +01:00
|
|
|
#include "transport.h"
|
|
|
|
|
2015-02-21 02:24:58 +01:00
|
|
|
#include <ctype.h>
|
2015-02-25 00:51:19 +01:00
|
|
|
#include <errno.h>
|
2017-08-17 01:57:01 +02:00
|
|
|
#include <inttypes.h>
|
2009-03-04 04:32:55 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2015-02-25 00:51:19 +01:00
|
|
|
#include <unistd.h>
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2015-11-08 03:51:54 +01:00
|
|
|
#include <algorithm>
|
2015-05-19 01:46:31 +02:00
|
|
|
#include <list>
|
2016-09-21 21:37:10 +02:00
|
|
|
#include <mutex>
|
2017-04-13 02:00:49 +02:00
|
|
|
#include <thread>
|
2015-05-19 01:46:31 +02:00
|
|
|
|
2015-12-05 07:00:26 +01:00
|
|
|
#include <android-base/logging.h>
|
2016-03-01 17:58:26 +01:00
|
|
|
#include <android-base/parsenetaddress.h>
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
#include <android-base/quick_exit.h>
|
2015-12-05 07:00:26 +01:00
|
|
|
#include <android-base/stringprintf.h>
|
|
|
|
#include <android-base/strings.h>
|
2017-08-17 01:57:01 +02:00
|
|
|
#include <android-base/thread_annotations.h>
|
2015-05-01 02:32:03 +02:00
|
|
|
|
2009-03-04 04:32:55 +01:00
|
|
|
#include "adb.h"
|
2016-06-30 02:42:01 +02:00
|
|
|
#include "adb_auth.h"
|
2018-01-29 05:32:46 +01:00
|
|
|
#include "adb_io.h"
|
2016-11-29 18:40:29 +01:00
|
|
|
#include "adb_trace.h"
|
2015-05-01 02:32:03 +02:00
|
|
|
#include "adb_utils.h"
|
2015-12-12 04:07:01 +01:00
|
|
|
#include "diagnose_usb.h"
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
#include "fdevent.h"
|
2009-03-04 04:32:55 +01:00
|
|
|
|
|
|
|
static void transport_unref(atransport *t);
|
|
|
|
|
2017-08-17 01:57:01 +02:00
|
|
|
// TODO: unordered_map<TransportId, atransport*>
|
2015-11-12 02:56:12 +01:00
|
|
|
static auto& transport_list = *new std::list<atransport*>();
|
|
|
|
static auto& pending_list = *new std::list<atransport*>();
|
2013-03-30 02:22:36 +01:00
|
|
|
|
2017-08-17 22:50:51 +02:00
|
|
|
static auto& transport_lock = *new std::recursive_mutex();
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2015-11-10 01:03:25 +01:00
|
|
|
const char* const kFeatureShell2 = "shell_v2";
|
|
|
|
const char* const kFeatureCmd = "cmd";
|
2016-12-06 02:11:34 +01:00
|
|
|
const char* const kFeatureStat2 = "stat_v2";
|
2017-02-23 02:07:01 +01:00
|
|
|
const char* const kFeatureLibusb = "libusb";
|
2017-05-23 23:30:00 +02:00
|
|
|
const char* const kFeaturePushSync = "push_sync";
|
2015-11-10 01:03:25 +01:00
|
|
|
|
2017-08-17 01:57:01 +02:00
|
|
|
TransportId NextTransportId() {
|
|
|
|
static std::atomic<TransportId> next(1);
|
|
|
|
return next++;
|
|
|
|
}
|
|
|
|
|
2018-01-29 05:32:46 +01:00
|
|
|
bool FdConnection::Read(apacket* packet) {
|
|
|
|
if (!ReadFdExactly(fd_.get(), &packet->msg, sizeof(amessage))) {
|
|
|
|
D("remote local: read terminated (message)");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ReadFdExactly(fd_.get(), &packet->data, packet->msg.data_length)) {
|
|
|
|
D("remote local: terminated (data)");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FdConnection::Write(apacket* packet) {
|
|
|
|
uint32_t length = packet->msg.data_length;
|
|
|
|
|
|
|
|
if (!WriteFdExactly(fd_.get(), &packet->msg, sizeof(amessage) + length)) {
|
|
|
|
D("remote local: write terminated");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FdConnection::Close() {
|
|
|
|
adb_shutdown(fd_.get());
|
|
|
|
fd_.reset();
|
|
|
|
}
|
|
|
|
|
2015-09-23 00:52:57 +02:00
|
|
|
static std::string dump_packet(const char* name, const char* func, apacket* p) {
|
2016-11-22 23:32:34 +01:00
|
|
|
unsigned command = p->msg.command;
|
|
|
|
int len = p->msg.data_length;
|
|
|
|
char cmd[9];
|
|
|
|
char arg0[12], arg1[12];
|
|
|
|
int n;
|
2011-01-06 14:11:07 +01:00
|
|
|
|
|
|
|
for (n = 0; n < 4; n++) {
|
2016-11-22 23:32:34 +01:00
|
|
|
int b = (command >> (n * 8)) & 255;
|
|
|
|
if (b < 32 || b >= 127) break;
|
2011-01-06 14:11:07 +01:00
|
|
|
cmd[n] = (char)b;
|
|
|
|
}
|
|
|
|
if (n == 4) {
|
|
|
|
cmd[4] = 0;
|
|
|
|
} else {
|
|
|
|
/* There is some non-ASCII name in the command, so dump
|
|
|
|
* the hexadecimal value instead */
|
|
|
|
snprintf(cmd, sizeof cmd, "%08x", command);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->msg.arg0 < 256U)
|
|
|
|
snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
|
|
|
|
else
|
|
|
|
snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
|
|
|
|
|
|
|
|
if (p->msg.arg1 < 256U)
|
|
|
|
snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
|
|
|
|
else
|
|
|
|
snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
std::string result = android::base::StringPrintf("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ", name,
|
|
|
|
func, cmd, arg0, arg1, len);
|
2015-09-23 00:52:57 +02:00
|
|
|
result += dump_hex(p->data, len);
|
|
|
|
return result;
|
2011-01-06 14:11:07 +01:00
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
static int read_packet(int fd, const char* name, apacket** ppacket) {
|
2016-11-29 18:40:29 +01:00
|
|
|
ATRACE_NAME("read_packet");
|
2015-07-31 04:58:10 +02:00
|
|
|
char buff[8];
|
2011-01-06 14:11:07 +01:00
|
|
|
if (!name) {
|
|
|
|
snprintf(buff, sizeof buff, "fd=%d", fd);
|
|
|
|
name = buff;
|
|
|
|
}
|
2016-11-22 23:32:34 +01:00
|
|
|
char* p = reinterpret_cast<char*>(ppacket); /* really read a packet address */
|
2015-07-31 04:58:10 +02:00
|
|
|
int len = sizeof(apacket*);
|
2016-11-22 23:32:34 +01:00
|
|
|
while (len > 0) {
|
2015-07-31 04:58:10 +02:00
|
|
|
int r = adb_read(fd, p, len);
|
2016-11-22 23:32:34 +01:00
|
|
|
if (r > 0) {
|
2009-03-04 04:32:55 +01:00
|
|
|
len -= r;
|
2015-07-31 04:58:10 +02:00
|
|
|
p += r;
|
2009-03-04 04:32:55 +01:00
|
|
|
} else {
|
2015-09-03 02:44:28 +02:00
|
|
|
D("%s: read_packet (fd=%d), error ret=%d: %s", name, fd, r, strerror(errno));
|
2009-03-04 04:32:55 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-23 00:52:57 +02:00
|
|
|
VLOG(TRANSPORT) << dump_packet(name, "from remote", *ppacket);
|
2009-03-04 04:32:55 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
static int write_packet(int fd, const char* name, apacket** ppacket) {
|
2016-11-29 18:40:29 +01:00
|
|
|
ATRACE_NAME("write_packet");
|
2011-01-06 14:11:07 +01:00
|
|
|
char buff[8];
|
|
|
|
if (!name) {
|
|
|
|
snprintf(buff, sizeof buff, "fd=%d", fd);
|
|
|
|
name = buff;
|
|
|
|
}
|
2015-09-23 00:52:57 +02:00
|
|
|
VLOG(TRANSPORT) << dump_packet(name, "to remote", *ppacket);
|
2016-11-22 23:32:34 +01:00
|
|
|
char* p = reinterpret_cast<char*>(ppacket); /* we really write the packet address */
|
2015-07-31 04:58:10 +02:00
|
|
|
int len = sizeof(apacket*);
|
2016-11-22 23:32:34 +01:00
|
|
|
while (len > 0) {
|
2015-07-31 04:58:10 +02:00
|
|
|
int r = adb_write(fd, p, len);
|
2016-11-22 23:32:34 +01:00
|
|
|
if (r > 0) {
|
2009-03-04 04:32:55 +01:00
|
|
|
len -= r;
|
|
|
|
p += r;
|
|
|
|
} else {
|
2015-09-03 02:44:28 +02:00
|
|
|
D("%s: write_packet (fd=%d) error ret=%d: %s", name, fd, r, strerror(errno));
|
2009-03-04 04:32:55 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
static void transport_socket_events(int fd, unsigned events, void* _t) {
|
|
|
|
atransport* t = reinterpret_cast<atransport*>(_t);
|
2015-09-03 02:44:28 +02:00
|
|
|
D("transport_socket_events(fd=%d, events=%04x,...)", fd, events);
|
2016-11-22 23:32:34 +01:00
|
|
|
if (events & FDE_READ) {
|
|
|
|
apacket* p = 0;
|
|
|
|
if (read_packet(fd, t->serial, &p)) {
|
2015-09-03 02:44:28 +02:00
|
|
|
D("%s: failed to read packet from transport socket on fd %d", t->serial, fd);
|
2009-03-04 04:32:55 +01:00
|
|
|
} else {
|
2016-11-22 23:32:34 +01:00
|
|
|
handle_packet(p, (atransport*)_t);
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-06 22:31:44 +02:00
|
|
|
void send_packet(apacket* p, atransport* t) {
|
2009-03-04 04:32:55 +01:00
|
|
|
p->msg.magic = p->msg.command ^ 0xffffffff;
|
2017-12-07 20:40:00 +01:00
|
|
|
// compute a checksum for connection/auth packets for compatibility reasons
|
|
|
|
if (t->get_protocol_version() >= A_VERSION_SKIP_CHECKSUM) {
|
|
|
|
p->msg.data_check = 0;
|
|
|
|
} else {
|
|
|
|
p->msg.data_check = calculate_apacket_checksum(p);
|
|
|
|
}
|
2009-03-04 04:32:55 +01:00
|
|
|
|
|
|
|
print_packet("send", p);
|
|
|
|
|
|
|
|
if (t == NULL) {
|
2016-10-06 22:31:44 +02:00
|
|
|
fatal("Transport is null");
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
|
2016-10-06 22:31:44 +02:00
|
|
|
if (write_packet(t->transport_socket, t->serial, &p)) {
|
2009-03-04 04:32:55 +01:00
|
|
|
fatal_errno("cannot enqueue packet on transport socket");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-31 20:50:24 +02:00
|
|
|
// The transport is opened by transport_register_func before
|
|
|
|
// the read_transport and write_transport threads are started.
|
|
|
|
//
|
|
|
|
// The read_transport thread issues a SYNC(1, token) message to let
|
|
|
|
// the write_transport thread know to start things up. In the event
|
|
|
|
// of transport IO failure, the read_transport thread will post a
|
|
|
|
// SYNC(0,0) message to ensure shutdown.
|
|
|
|
//
|
|
|
|
// The transport will not actually be closed until both threads exit, but the threads
|
|
|
|
// will kick the transport on their way out to disconnect the underlying device.
|
|
|
|
//
|
|
|
|
// read_transport thread reads data from a transport (representing a usb/tcp connection),
|
|
|
|
// and makes the main thread call handle_packet().
|
2016-02-12 23:31:15 +01:00
|
|
|
static void read_transport_thread(void* _t) {
|
2016-11-22 23:32:34 +01:00
|
|
|
atransport* t = reinterpret_cast<atransport*>(_t);
|
|
|
|
apacket* p;
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
adb_thread_setname(
|
|
|
|
android::base::StringPrintf("<-%s", (t->serial != nullptr ? t->serial : "transport")));
|
|
|
|
D("%s: starting read_transport thread on fd %d, SYNC online (%d)", t->serial, t->fd,
|
|
|
|
t->sync_token + 1);
|
2009-03-04 04:32:55 +01:00
|
|
|
p = get_apacket();
|
|
|
|
p->msg.command = A_SYNC;
|
|
|
|
p->msg.arg0 = 1;
|
|
|
|
p->msg.arg1 = ++(t->sync_token);
|
|
|
|
p->msg.magic = A_SYNC ^ 0xffffffff;
|
2016-11-22 23:32:34 +01:00
|
|
|
if (write_packet(t->fd, t->serial, &p)) {
|
2009-03-04 04:32:55 +01:00
|
|
|
put_apacket(p);
|
2015-09-03 02:44:28 +02:00
|
|
|
D("%s: failed to write SYNC packet", t->serial);
|
2009-03-04 04:32:55 +01:00
|
|
|
goto oops;
|
|
|
|
}
|
|
|
|
|
2015-09-03 02:44:28 +02:00
|
|
|
D("%s: data pump started", t->serial);
|
2016-11-22 23:32:34 +01:00
|
|
|
for (;;) {
|
2016-11-29 18:40:29 +01:00
|
|
|
ATRACE_NAME("read_transport loop");
|
2009-03-04 04:32:55 +01:00
|
|
|
p = get_apacket();
|
|
|
|
|
2016-11-29 18:40:29 +01:00
|
|
|
{
|
|
|
|
ATRACE_NAME("read_transport read_remote");
|
2018-01-29 05:32:46 +01:00
|
|
|
if (!t->connection->Read(p)) {
|
2016-11-29 18:40:29 +01:00
|
|
|
D("%s: remote read failed for transport", t->serial);
|
2009-03-04 04:32:55 +01:00
|
|
|
put_apacket(p);
|
2016-11-29 18:40:29 +01:00
|
|
|
break;
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
2018-01-29 05:32:46 +01:00
|
|
|
|
|
|
|
if (!check_header(p, t)) {
|
|
|
|
D("%s: remote read: bad header", t->serial);
|
|
|
|
put_apacket(p);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
#if ADB_HOST
|
|
|
|
if (p->msg.command == 0) {
|
2018-01-30 03:09:20 +01:00
|
|
|
put_apacket(p);
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
2016-11-29 18:40:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
D("%s: received remote packet, sending to transport", t->serial);
|
|
|
|
if (write_packet(t->fd, t->serial, &p)) {
|
2009-03-04 04:32:55 +01:00
|
|
|
put_apacket(p);
|
2016-11-29 18:40:29 +01:00
|
|
|
D("%s: failed to write apacket to transport", t->serial);
|
|
|
|
goto oops;
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-03 02:44:28 +02:00
|
|
|
D("%s: SYNC offline for transport", t->serial);
|
2009-03-04 04:32:55 +01:00
|
|
|
p = get_apacket();
|
|
|
|
p->msg.command = A_SYNC;
|
|
|
|
p->msg.arg0 = 0;
|
|
|
|
p->msg.arg1 = 0;
|
|
|
|
p->msg.magic = A_SYNC ^ 0xffffffff;
|
2016-11-22 23:32:34 +01:00
|
|
|
if (write_packet(t->fd, t->serial, &p)) {
|
2009-03-04 04:32:55 +01:00
|
|
|
put_apacket(p);
|
2015-09-03 02:44:28 +02:00
|
|
|
D("%s: failed to write SYNC apacket to transport", t->serial);
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
oops:
|
2015-09-03 02:44:28 +02:00
|
|
|
D("%s: read_transport thread is exiting", t->serial);
|
2009-03-04 04:32:55 +01:00
|
|
|
kick_transport(t);
|
|
|
|
transport_unref(t);
|
|
|
|
}
|
|
|
|
|
2015-08-31 20:50:24 +02:00
|
|
|
// write_transport thread gets packets sent by the main thread (through send_packet()),
|
|
|
|
// and writes to a transport (representing a usb/tcp connection).
|
2016-02-12 23:31:15 +01:00
|
|
|
static void write_transport_thread(void* _t) {
|
2016-11-22 23:32:34 +01:00
|
|
|
atransport* t = reinterpret_cast<atransport*>(_t);
|
|
|
|
apacket* p;
|
2009-03-04 04:32:55 +01:00
|
|
|
int active = 0;
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
adb_thread_setname(
|
|
|
|
android::base::StringPrintf("->%s", (t->serial != nullptr ? t->serial : "transport")));
|
|
|
|
D("%s: starting write_transport thread, reading from fd %d", t->serial, t->fd);
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
for (;;) {
|
2016-11-29 18:40:29 +01:00
|
|
|
ATRACE_NAME("write_transport loop");
|
2016-11-22 23:32:34 +01:00
|
|
|
if (read_packet(t->fd, t->serial, &p)) {
|
|
|
|
D("%s: failed to read apacket from transport on fd %d", t->serial, t->fd);
|
2009-03-04 04:32:55 +01:00
|
|
|
break;
|
|
|
|
}
|
2016-11-29 18:40:29 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
if (p->msg.command == A_SYNC) {
|
|
|
|
if (p->msg.arg0 == 0) {
|
2015-09-03 02:44:28 +02:00
|
|
|
D("%s: transport SYNC offline", t->serial);
|
2009-03-04 04:32:55 +01:00
|
|
|
put_apacket(p);
|
|
|
|
break;
|
|
|
|
} else {
|
2016-11-22 23:32:34 +01:00
|
|
|
if (p->msg.arg1 == t->sync_token) {
|
2015-09-03 02:44:28 +02:00
|
|
|
D("%s: transport SYNC online", t->serial);
|
2009-03-04 04:32:55 +01:00
|
|
|
active = 1;
|
|
|
|
} else {
|
2016-11-22 23:32:34 +01:00
|
|
|
D("%s: transport ignoring SYNC %d != %d", t->serial, p->msg.arg1, t->sync_token);
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2016-11-22 23:32:34 +01:00
|
|
|
if (active) {
|
2015-09-03 02:44:28 +02:00
|
|
|
D("%s: transport got packet, sending to remote", t->serial);
|
2016-11-29 18:40:29 +01:00
|
|
|
ATRACE_NAME("write_transport write_remote");
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
if (t->Write(p) != 0) {
|
|
|
|
D("%s: remote write failed for transport", t->serial);
|
|
|
|
put_apacket(p);
|
|
|
|
break;
|
|
|
|
}
|
2009-03-04 04:32:55 +01:00
|
|
|
} else {
|
2015-09-03 02:44:28 +02:00
|
|
|
D("%s: transport ignoring packet while offline", t->serial);
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
put_apacket(p);
|
|
|
|
}
|
|
|
|
|
2015-09-03 02:44:28 +02:00
|
|
|
D("%s: write_transport thread is exiting, fd %d", t->serial, t->fd);
|
2009-03-04 04:32:55 +01:00
|
|
|
kick_transport(t);
|
|
|
|
transport_unref(t);
|
|
|
|
}
|
|
|
|
|
2015-08-27 21:03:11 +02:00
|
|
|
void kick_transport(atransport* t) {
|
2017-08-17 22:50:51 +02:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
2016-04-05 22:50:44 +02:00
|
|
|
// As kick_transport() can be called from threads without guarantee that t is valid,
|
|
|
|
// check if the transport is in transport_list first.
|
2017-08-17 01:57:01 +02:00
|
|
|
//
|
|
|
|
// TODO(jmgao): WTF? Is this actually true?
|
2016-04-05 22:50:44 +02:00
|
|
|
if (std::find(transport_list.begin(), transport_list.end(), t) != transport_list.end()) {
|
2016-04-18 20:22:34 +02:00
|
|
|
t->Kick();
|
2016-04-05 22:50:44 +02:00
|
|
|
}
|
2015-08-27 21:03:11 +02:00
|
|
|
}
|
2009-03-04 04:32:55 +01:00
|
|
|
|
|
|
|
static int transport_registration_send = -1;
|
|
|
|
static int transport_registration_recv = -1;
|
|
|
|
static fdevent transport_registration_fde;
|
|
|
|
|
|
|
|
#if ADB_HOST
|
|
|
|
|
|
|
|
/* this adds support required by the 'track-devices' service.
|
|
|
|
* this is used to send the content of "list_transport" to any
|
|
|
|
* number of client connections that want it through a single
|
|
|
|
* live TCP connection
|
|
|
|
*/
|
|
|
|
struct device_tracker {
|
2016-11-22 23:32:34 +01:00
|
|
|
asocket socket;
|
2017-08-15 03:57:54 +02:00
|
|
|
bool update_needed;
|
|
|
|
bool long_output;
|
2016-11-22 23:32:34 +01:00
|
|
|
device_tracker* next;
|
2009-03-04 04:32:55 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/* linked list of all device trackers */
|
2016-11-22 23:32:34 +01:00
|
|
|
static device_tracker* device_tracker_list;
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
static void device_tracker_remove(device_tracker* tracker) {
|
|
|
|
device_tracker** pnode = &device_tracker_list;
|
|
|
|
device_tracker* node = *pnode;
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2017-08-17 22:50:51 +02:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
2009-03-04 04:32:55 +01:00
|
|
|
while (node) {
|
|
|
|
if (node == tracker) {
|
|
|
|
*pnode = node->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pnode = &node->next;
|
2016-11-22 23:32:34 +01:00
|
|
|
node = *pnode;
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
static void device_tracker_close(asocket* socket) {
|
|
|
|
device_tracker* tracker = (device_tracker*)socket;
|
|
|
|
asocket* peer = socket->peer;
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
D("device tracker %p removed", tracker);
|
2009-03-04 04:32:55 +01:00
|
|
|
if (peer) {
|
|
|
|
peer->peer = NULL;
|
|
|
|
peer->close(peer);
|
|
|
|
}
|
|
|
|
device_tracker_remove(tracker);
|
|
|
|
free(tracker);
|
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
static int device_tracker_enqueue(asocket* socket, apacket* p) {
|
2009-03-04 04:32:55 +01:00
|
|
|
/* you can't read from a device tracker, close immediately */
|
|
|
|
put_apacket(p);
|
|
|
|
device_tracker_close(socket);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-05-01 02:32:03 +02:00
|
|
|
static int device_tracker_send(device_tracker* tracker, const std::string& string) {
|
|
|
|
apacket* p = get_apacket();
|
|
|
|
asocket* peer = tracker->socket.peer;
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2015-05-01 02:32:03 +02:00
|
|
|
snprintf(reinterpret_cast<char*>(p->data), 5, "%04x", static_cast<int>(string.size()));
|
|
|
|
memcpy(&p->data[4], string.data(), string.size());
|
|
|
|
p->len = 4 + string.size();
|
|
|
|
return peer->enqueue(peer, p);
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
|
2015-05-01 02:32:03 +02:00
|
|
|
static void device_tracker_ready(asocket* socket) {
|
|
|
|
device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2015-05-01 02:32:03 +02:00
|
|
|
// We want to send the device list when the tracker connects
|
|
|
|
// for the first time, even if no update occurred.
|
2017-08-15 03:57:54 +02:00
|
|
|
if (tracker->update_needed) {
|
|
|
|
tracker->update_needed = false;
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2017-08-15 03:57:54 +02:00
|
|
|
std::string transports = list_transports(tracker->long_output);
|
2015-05-01 02:32:03 +02:00
|
|
|
device_tracker_send(tracker, transports);
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-15 03:57:54 +02:00
|
|
|
asocket* create_device_tracker(bool long_output) {
|
2015-04-22 04:39:52 +02:00
|
|
|
device_tracker* tracker = reinterpret_cast<device_tracker*>(calloc(1, sizeof(*tracker)));
|
|
|
|
if (tracker == nullptr) fatal("cannot allocate device tracker");
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
D("device tracker %p created", tracker);
|
2009-03-04 04:32:55 +01:00
|
|
|
|
|
|
|
tracker->socket.enqueue = device_tracker_enqueue;
|
2016-11-22 23:32:34 +01:00
|
|
|
tracker->socket.ready = device_tracker_ready;
|
|
|
|
tracker->socket.close = device_tracker_close;
|
2017-08-15 03:57:54 +02:00
|
|
|
tracker->update_needed = true;
|
|
|
|
tracker->long_output = long_output;
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
tracker->next = device_tracker_list;
|
2009-03-04 04:32:55 +01:00
|
|
|
device_tracker_list = tracker;
|
|
|
|
|
|
|
|
return &tracker->socket;
|
|
|
|
}
|
|
|
|
|
2017-05-04 07:37:10 +02:00
|
|
|
// Check if all of the USB transports are connected.
|
|
|
|
bool iterate_transports(std::function<bool(const atransport*)> fn) {
|
2017-08-17 22:50:51 +02:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
2017-05-04 07:37:10 +02:00
|
|
|
for (const auto& t : transport_list) {
|
|
|
|
if (!fn(t)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (const auto& t : pending_list) {
|
|
|
|
if (!fn(t)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-05-01 02:32:03 +02:00
|
|
|
// Call this function each time the transport list has changed.
|
|
|
|
void update_transports() {
|
2017-05-04 07:37:10 +02:00
|
|
|
update_transport_status();
|
|
|
|
|
|
|
|
// Notify `adb track-devices` clients.
|
2015-05-01 02:32:03 +02:00
|
|
|
std::string transports = list_transports(false);
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2015-05-01 02:32:03 +02:00
|
|
|
device_tracker* tracker = device_tracker_list;
|
|
|
|
while (tracker != nullptr) {
|
|
|
|
device_tracker* next = tracker->next;
|
|
|
|
// This may destroy the tracker if the connection is closed.
|
|
|
|
device_tracker_send(tracker, transports);
|
2009-03-04 04:32:55 +01:00
|
|
|
tracker = next;
|
|
|
|
}
|
|
|
|
}
|
2015-05-01 02:32:03 +02:00
|
|
|
|
2009-03-04 04:32:55 +01:00
|
|
|
#else
|
2015-05-01 02:32:03 +02:00
|
|
|
|
|
|
|
void update_transports() {
|
|
|
|
// Nothing to do on the device side.
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
2015-05-01 02:32:03 +02:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
#endif // ADB_HOST
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
struct tmsg {
|
|
|
|
atransport* transport;
|
|
|
|
int action;
|
2009-03-04 04:32:55 +01:00
|
|
|
};
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
static int transport_read_action(int fd, struct tmsg* m) {
|
|
|
|
char* p = (char*)m;
|
|
|
|
int len = sizeof(*m);
|
|
|
|
int r;
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
while (len > 0) {
|
2009-03-04 04:32:55 +01:00
|
|
|
r = adb_read(fd, p, len);
|
2016-11-22 23:32:34 +01:00
|
|
|
if (r > 0) {
|
2009-03-04 04:32:55 +01:00
|
|
|
len -= r;
|
2016-11-22 23:32:34 +01:00
|
|
|
p += r;
|
2009-03-04 04:32:55 +01:00
|
|
|
} else {
|
2015-09-03 02:44:28 +02:00
|
|
|
D("transport_read_action: on fd %d: %s", fd, strerror(errno));
|
2009-03-04 04:32:55 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
static int transport_write_action(int fd, struct tmsg* m) {
|
|
|
|
char* p = (char*)m;
|
|
|
|
int len = sizeof(*m);
|
|
|
|
int r;
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
while (len > 0) {
|
2009-03-04 04:32:55 +01:00
|
|
|
r = adb_write(fd, p, len);
|
2016-11-22 23:32:34 +01:00
|
|
|
if (r > 0) {
|
2009-03-04 04:32:55 +01:00
|
|
|
len -= r;
|
2016-11-22 23:32:34 +01:00
|
|
|
p += r;
|
2009-03-04 04:32:55 +01:00
|
|
|
} else {
|
2015-09-03 02:44:28 +02:00
|
|
|
D("transport_write_action: on fd %d: %s", fd, strerror(errno));
|
2009-03-04 04:32:55 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
static void transport_registration_func(int _fd, unsigned ev, void* data) {
|
2009-03-04 04:32:55 +01:00
|
|
|
tmsg m;
|
|
|
|
int s[2];
|
2016-11-22 23:32:34 +01:00
|
|
|
atransport* t;
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
if (!(ev & FDE_READ)) {
|
2009-03-04 04:32:55 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
if (transport_read_action(_fd, &m)) {
|
2009-03-04 04:32:55 +01:00
|
|
|
fatal_errno("cannot read transport registration socket");
|
|
|
|
}
|
|
|
|
|
|
|
|
t = m.transport;
|
|
|
|
|
2015-05-18 22:06:53 +02:00
|
|
|
if (m.action == 0) {
|
2015-09-03 02:44:28 +02:00
|
|
|
D("transport: %s removing and free'ing %d", t->serial, t->transport_socket);
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
/* IMPORTANT: the remove closes one half of the
|
|
|
|
** socket pair. The close closes the other half.
|
|
|
|
*/
|
2009-03-04 04:32:55 +01:00
|
|
|
fdevent_remove(&(t->transport_fde));
|
|
|
|
adb_close(t->fd);
|
|
|
|
|
2016-09-21 21:37:10 +02:00
|
|
|
{
|
2017-08-17 22:50:51 +02:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
2016-09-21 21:37:10 +02:00
|
|
|
transport_list.remove(t);
|
|
|
|
}
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
if (t->product) free(t->product);
|
|
|
|
if (t->serial) free(t->serial);
|
|
|
|
if (t->model) free(t->model);
|
|
|
|
if (t->device) free(t->device);
|
|
|
|
if (t->devpath) free(t->devpath);
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2015-05-19 01:46:31 +02:00
|
|
|
delete t;
|
2009-03-04 04:32:55 +01:00
|
|
|
|
|
|
|
update_transports();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-08-08 18:37:44 +02:00
|
|
|
/* don't create transport threads for inaccessible devices */
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
if (t->GetConnectionState() != kCsNoPerm) {
|
2009-03-04 04:32:55 +01:00
|
|
|
/* initial references are the two threads */
|
2009-08-08 18:37:44 +02:00
|
|
|
t->ref_count = 2;
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2015-05-19 01:46:31 +02:00
|
|
|
if (adb_socketpair(s)) {
|
2009-08-08 18:37:44 +02:00
|
|
|
fatal_errno("cannot open transport socketpair");
|
|
|
|
}
|
|
|
|
|
2015-09-03 02:44:28 +02:00
|
|
|
D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]);
|
2009-08-08 18:37:44 +02:00
|
|
|
|
|
|
|
t->transport_socket = s[0];
|
|
|
|
t->fd = s[1];
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
fdevent_install(&(t->transport_fde), t->transport_socket, transport_socket_events, t);
|
2009-08-08 18:37:44 +02:00
|
|
|
|
|
|
|
fdevent_set(&(t->transport_fde), FDE_READ);
|
|
|
|
|
2017-04-13 02:00:49 +02:00
|
|
|
std::thread(write_transport_thread, t).detach();
|
|
|
|
std::thread(read_transport_thread, t).detach();
|
2009-08-08 18:37:44 +02:00
|
|
|
}
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-09-21 21:37:10 +02:00
|
|
|
{
|
2017-08-17 22:50:51 +02:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
2016-09-21 21:37:10 +02:00
|
|
|
pending_list.remove(t);
|
|
|
|
transport_list.push_front(t);
|
|
|
|
}
|
2009-03-04 04:32:55 +01:00
|
|
|
|
|
|
|
update_transports();
|
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
void init_transport_registration(void) {
|
2009-03-04 04:32:55 +01:00
|
|
|
int s[2];
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
if (adb_socketpair(s)) {
|
2009-03-04 04:32:55 +01:00
|
|
|
fatal_errno("cannot open transport registration socketpair");
|
|
|
|
}
|
2015-09-03 02:44:28 +02:00
|
|
|
D("socketpair: (%d,%d)", s[0], s[1]);
|
2009-03-04 04:32:55 +01:00
|
|
|
|
|
|
|
transport_registration_send = s[0];
|
|
|
|
transport_registration_recv = s[1];
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
fdevent_install(&transport_registration_fde, transport_registration_recv,
|
|
|
|
transport_registration_func, 0);
|
2009-03-04 04:32:55 +01:00
|
|
|
|
|
|
|
fdevent_set(&transport_registration_fde, FDE_READ);
|
2017-05-09 22:43:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void kick_all_transports() {
|
|
|
|
// To avoid only writing part of a packet to a transport after exit, kick all transports.
|
2017-08-17 22:50:51 +02:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
2017-05-09 22:43:35 +02:00
|
|
|
for (auto t : transport_list) {
|
|
|
|
t->Kick();
|
|
|
|
}
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* the fdevent select pump is single threaded */
|
2016-11-22 23:32:34 +01:00
|
|
|
static void register_transport(atransport* transport) {
|
2009-03-04 04:32:55 +01:00
|
|
|
tmsg m;
|
|
|
|
m.transport = transport;
|
|
|
|
m.action = 1;
|
2015-09-03 02:44:28 +02:00
|
|
|
D("transport: %s registered", transport->serial);
|
2016-11-22 23:32:34 +01:00
|
|
|
if (transport_write_action(transport_registration_send, &m)) {
|
2009-03-04 04:32:55 +01:00
|
|
|
fatal_errno("cannot write transport registration socket\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
static void remove_transport(atransport* transport) {
|
2009-03-04 04:32:55 +01:00
|
|
|
tmsg m;
|
|
|
|
m.transport = transport;
|
|
|
|
m.action = 0;
|
2015-09-03 02:44:28 +02:00
|
|
|
D("transport: %s removed", transport->serial);
|
2016-11-22 23:32:34 +01:00
|
|
|
if (transport_write_action(transport_registration_send, &m)) {
|
2009-03-04 04:32:55 +01:00
|
|
|
fatal_errno("cannot write transport registration socket\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-27 21:03:11 +02:00
|
|
|
static void transport_unref(atransport* t) {
|
|
|
|
CHECK(t != nullptr);
|
2016-09-21 21:37:10 +02:00
|
|
|
|
2017-09-13 22:40:57 +02:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
|
|
|
CHECK_GT(t->ref_count, 0u);
|
|
|
|
t->ref_count--;
|
|
|
|
if (t->ref_count == 0) {
|
2015-09-03 02:44:28 +02:00
|
|
|
D("transport: %s unref (kicking and closing)", t->serial);
|
2018-01-29 05:32:46 +01:00
|
|
|
t->connection->Close();
|
2010-05-24 16:44:35 +02:00
|
|
|
remove_transport(t);
|
2011-01-06 14:11:07 +01:00
|
|
|
} else {
|
2017-09-13 22:40:57 +02:00
|
|
|
D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
static int qual_match(const char* to_test, const char* prefix, const char* qual,
|
|
|
|
bool sanitize_qual) {
|
|
|
|
if (!to_test || !*to_test) /* Return true if both the qual and to_test are null strings. */
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
return !qual || !*qual;
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
if (!qual) return 0;
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
|
|
|
|
if (prefix) {
|
|
|
|
while (*prefix) {
|
2016-11-22 23:32:34 +01:00
|
|
|
if (*prefix++ != *to_test++) return 0;
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while (*qual) {
|
|
|
|
char ch = *qual++;
|
2016-11-22 23:32:34 +01:00
|
|
|
if (sanitize_qual && !isalnum(ch)) ch = '_';
|
|
|
|
if (ch != *to_test++) return 0;
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Everything matched so far. Return true if *to_test is a NUL. */
|
|
|
|
return !*to_test;
|
|
|
|
}
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2017-08-17 01:57:01 +02:00
|
|
|
atransport* acquire_one_transport(TransportType type, const char* serial, TransportId transport_id,
|
|
|
|
bool* is_ambiguous, std::string* error_out,
|
|
|
|
bool accept_any_state) {
|
2015-10-07 23:55:10 +02:00
|
|
|
atransport* result = nullptr;
|
|
|
|
|
2017-08-17 01:57:01 +02:00
|
|
|
if (transport_id != 0) {
|
|
|
|
*error_out =
|
|
|
|
android::base::StringPrintf("no device with transport id '%" PRIu64 "'", transport_id);
|
|
|
|
} else if (serial) {
|
2015-10-07 23:55:10 +02:00
|
|
|
*error_out = android::base::StringPrintf("device '%s' not found", serial);
|
|
|
|
} else if (type == kTransportLocal) {
|
|
|
|
*error_out = "no emulators found";
|
|
|
|
} else if (type == kTransportAny) {
|
|
|
|
*error_out = "no devices/emulators found";
|
|
|
|
} else {
|
|
|
|
*error_out = "no devices found";
|
|
|
|
}
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2017-08-17 22:50:51 +02:00
|
|
|
std::unique_lock<std::recursive_mutex> lock(transport_lock);
|
2015-10-07 23:55:10 +02:00
|
|
|
for (const auto& t : transport_list) {
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
if (t->GetConnectionState() == kCsNoPerm) {
|
2015-12-12 04:07:01 +01:00
|
|
|
#if ADB_HOST
|
2015-12-03 00:14:31 +01:00
|
|
|
*error_out = UsbNoPermissionsLongHelpText();
|
2015-12-12 04:07:01 +01:00
|
|
|
#endif
|
2009-08-08 19:53:16 +02:00
|
|
|
continue;
|
|
|
|
}
|
2009-08-08 18:37:44 +02:00
|
|
|
|
2017-08-17 01:57:01 +02:00
|
|
|
if (transport_id) {
|
|
|
|
if (t->id == transport_id) {
|
|
|
|
result = t;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (serial) {
|
2016-03-01 17:58:26 +01:00
|
|
|
if (t->MatchesTarget(serial)) {
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
if (result) {
|
2015-06-23 22:00:32 +02:00
|
|
|
*error_out = "more than one device";
|
2015-10-07 23:55:10 +02:00
|
|
|
if (is_ambiguous) *is_ambiguous = true;
|
|
|
|
result = nullptr;
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
break;
|
|
|
|
}
|
2012-04-20 20:21:14 +02:00
|
|
|
result = t;
|
|
|
|
}
|
2009-03-04 04:32:55 +01:00
|
|
|
} else {
|
2015-05-05 22:10:43 +02:00
|
|
|
if (type == kTransportUsb && t->type == kTransportUsb) {
|
2009-03-04 04:32:55 +01:00
|
|
|
if (result) {
|
2015-06-23 22:00:32 +02:00
|
|
|
*error_out = "more than one device";
|
2015-10-07 23:55:10 +02:00
|
|
|
if (is_ambiguous) *is_ambiguous = true;
|
|
|
|
result = nullptr;
|
2009-03-04 04:32:55 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
result = t;
|
2015-05-05 22:10:43 +02:00
|
|
|
} else if (type == kTransportLocal && t->type == kTransportLocal) {
|
2009-03-04 04:32:55 +01:00
|
|
|
if (result) {
|
2015-06-23 22:00:32 +02:00
|
|
|
*error_out = "more than one emulator";
|
2015-10-07 23:55:10 +02:00
|
|
|
if (is_ambiguous) *is_ambiguous = true;
|
|
|
|
result = nullptr;
|
2009-03-04 04:32:55 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
result = t;
|
2015-05-05 22:10:43 +02:00
|
|
|
} else if (type == kTransportAny) {
|
2009-03-04 04:32:55 +01:00
|
|
|
if (result) {
|
2015-06-23 22:00:32 +02:00
|
|
|
*error_out = "more than one device/emulator";
|
2015-10-07 23:55:10 +02:00
|
|
|
if (is_ambiguous) *is_ambiguous = true;
|
|
|
|
result = nullptr;
|
2009-03-04 04:32:55 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
result = t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-09-21 21:37:10 +02:00
|
|
|
lock.unlock();
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2015-10-07 23:55:10 +02:00
|
|
|
// Don't return unauthorized devices; the caller can't do anything with them.
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
if (result && result->GetConnectionState() == kCsUnauthorized && !accept_any_state) {
|
2015-10-07 23:55:10 +02:00
|
|
|
*error_out = "device unauthorized.\n";
|
|
|
|
char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
|
|
|
|
*error_out += "This adb server's $ADB_VENDOR_KEYS is ";
|
|
|
|
*error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
|
|
|
|
*error_out += "\n";
|
|
|
|
*error_out += "Try 'adb kill-server' if that seems wrong.\n";
|
|
|
|
*error_out += "Otherwise check for a confirmation dialog on your device.";
|
|
|
|
result = nullptr;
|
|
|
|
}
|
2015-04-17 07:54:44 +02:00
|
|
|
|
2015-10-07 23:55:10 +02:00
|
|
|
// Don't return offline devices; the caller can't do anything with them.
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
if (result && result->GetConnectionState() == kCsOffline && !accept_any_state) {
|
2015-10-07 23:55:10 +02:00
|
|
|
*error_out = "device offline";
|
|
|
|
result = nullptr;
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (result) {
|
2015-06-23 22:00:32 +02:00
|
|
|
*error_out = "success";
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
int atransport::Write(apacket* p) {
|
2018-01-29 05:32:46 +01:00
|
|
|
return this->connection->Write(p) ? 0 : -1;
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
}
|
|
|
|
|
2016-04-18 20:22:34 +02:00
|
|
|
void atransport::Kick() {
|
|
|
|
if (!kicked_) {
|
2018-01-29 05:32:46 +01:00
|
|
|
D("kicking transport %s", this->serial);
|
2016-04-18 20:22:34 +02:00
|
|
|
kicked_ = true;
|
2018-01-29 05:32:46 +01:00
|
|
|
this->connection->Close();
|
2016-04-18 20:22:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
ConnectionState atransport::GetConnectionState() const {
|
|
|
|
return connection_state_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void atransport::SetConnectionState(ConnectionState state) {
|
|
|
|
check_main_thread();
|
|
|
|
connection_state_ = state;
|
|
|
|
}
|
|
|
|
|
2015-12-03 00:14:31 +01:00
|
|
|
const std::string atransport::connection_state_name() const {
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
ConnectionState state = GetConnectionState();
|
|
|
|
switch (state) {
|
2016-11-22 23:32:34 +01:00
|
|
|
case kCsOffline:
|
|
|
|
return "offline";
|
|
|
|
case kCsBootloader:
|
|
|
|
return "bootloader";
|
|
|
|
case kCsDevice:
|
|
|
|
return "device";
|
|
|
|
case kCsHost:
|
|
|
|
return "host";
|
|
|
|
case kCsRecovery:
|
|
|
|
return "recovery";
|
|
|
|
case kCsNoPerm:
|
|
|
|
return UsbNoPermissionsShortHelpText();
|
|
|
|
case kCsSideload:
|
|
|
|
return "sideload";
|
|
|
|
case kCsUnauthorized:
|
|
|
|
return "unauthorized";
|
|
|
|
default:
|
|
|
|
return "unknown";
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-13 20:12:28 +02:00
|
|
|
void atransport::update_version(int version, size_t payload) {
|
|
|
|
protocol_version = std::min(version, A_VERSION);
|
|
|
|
max_payload = std::min(payload, MAX_PAYLOAD);
|
|
|
|
}
|
|
|
|
|
|
|
|
int atransport::get_protocol_version() const {
|
|
|
|
return protocol_version;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t atransport::get_max_payload() const {
|
|
|
|
return max_payload;
|
|
|
|
}
|
|
|
|
|
2015-09-22 19:43:08 +02:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
constexpr char kFeatureStringDelimiter = ',';
|
|
|
|
|
|
|
|
} // namespace
|
2015-05-18 22:06:53 +02:00
|
|
|
|
|
|
|
const FeatureSet& supported_features() {
|
2015-09-22 19:43:08 +02:00
|
|
|
// Local static allocation to avoid global non-POD variables.
|
|
|
|
static const FeatureSet* features = new FeatureSet{
|
2016-11-22 23:32:34 +01:00
|
|
|
kFeatureShell2, kFeatureCmd, kFeatureStat2,
|
2015-09-25 17:37:13 +02:00
|
|
|
// Increment ADB_SERVER_VERSION whenever the feature list changes to
|
|
|
|
// make sure that the adb client and server features stay in sync
|
|
|
|
// (http://b/24370690).
|
2015-09-22 19:43:08 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
return *features;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string FeatureSetToString(const FeatureSet& features) {
|
|
|
|
return android::base::Join(features, kFeatureStringDelimiter);
|
|
|
|
}
|
|
|
|
|
|
|
|
FeatureSet StringToFeatureSet(const std::string& features_string) {
|
2015-09-25 22:04:21 +02:00
|
|
|
if (features_string.empty()) {
|
|
|
|
return FeatureSet();
|
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
auto names = android::base::Split(features_string, {kFeatureStringDelimiter});
|
2015-09-22 19:43:08 +02:00
|
|
|
return FeatureSet(names.begin(), names.end());
|
2015-05-18 22:06:53 +02:00
|
|
|
}
|
|
|
|
|
2015-09-30 22:35:42 +02:00
|
|
|
bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature) {
|
2016-11-22 23:32:34 +01:00
|
|
|
return feature_set.count(feature) > 0 && supported_features().count(feature) > 0;
|
2015-09-30 22:35:42 +02:00
|
|
|
}
|
|
|
|
|
2015-05-18 22:06:53 +02:00
|
|
|
bool atransport::has_feature(const std::string& feature) const {
|
|
|
|
return features_.count(feature) > 0;
|
|
|
|
}
|
|
|
|
|
2015-09-22 19:43:08 +02:00
|
|
|
void atransport::SetFeatures(const std::string& features_string) {
|
|
|
|
features_ = StringToFeatureSet(features_string);
|
2015-05-18 22:06:53 +02:00
|
|
|
}
|
|
|
|
|
2015-08-29 00:09:44 +02:00
|
|
|
void atransport::AddDisconnect(adisconnect* disconnect) {
|
|
|
|
disconnects_.push_back(disconnect);
|
|
|
|
}
|
|
|
|
|
|
|
|
void atransport::RemoveDisconnect(adisconnect* disconnect) {
|
|
|
|
disconnects_.remove(disconnect);
|
|
|
|
}
|
|
|
|
|
|
|
|
void atransport::RunDisconnects() {
|
2015-10-08 00:59:35 +02:00
|
|
|
for (const auto& disconnect : disconnects_) {
|
2015-08-29 00:09:44 +02:00
|
|
|
disconnect->func(disconnect->opaque, this);
|
|
|
|
}
|
|
|
|
disconnects_.clear();
|
|
|
|
}
|
|
|
|
|
2016-03-01 17:58:26 +01:00
|
|
|
bool atransport::MatchesTarget(const std::string& target) const {
|
|
|
|
if (serial) {
|
|
|
|
if (target == serial) {
|
|
|
|
return true;
|
|
|
|
} else if (type == kTransportLocal) {
|
|
|
|
// Local transports can match [tcp:|udp:]<hostname>[:port].
|
|
|
|
const char* local_target_ptr = target.c_str();
|
|
|
|
|
|
|
|
// For fastboot compatibility, ignore protocol prefixes.
|
|
|
|
if (android::base::StartsWith(target, "tcp:") ||
|
2016-11-22 23:32:34 +01:00
|
|
|
android::base::StartsWith(target, "udp:")) {
|
2016-03-01 17:58:26 +01:00
|
|
|
local_target_ptr += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse our |serial| and the given |target| to check if the hostnames and ports match.
|
|
|
|
std::string serial_host, error;
|
|
|
|
int serial_port = -1;
|
2016-11-22 23:32:34 +01:00
|
|
|
if (android::base::ParseNetAddress(serial, &serial_host, &serial_port, nullptr, &error)) {
|
2016-03-01 17:58:26 +01:00
|
|
|
// |target| may omit the port to default to ours.
|
|
|
|
std::string target_host;
|
|
|
|
int target_port = serial_port;
|
|
|
|
if (android::base::ParseNetAddress(local_target_ptr, &target_host, &target_port,
|
|
|
|
nullptr, &error) &&
|
2016-11-22 23:32:34 +01:00
|
|
|
serial_host == target_host && serial_port == target_port) {
|
2016-03-01 17:58:26 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (devpath && target == devpath) ||
|
|
|
|
qual_match(target.c_str(), "product:", product, false) ||
|
|
|
|
qual_match(target.c_str(), "model:", model, true) ||
|
|
|
|
qual_match(target.c_str(), "device:", device, false);
|
|
|
|
}
|
|
|
|
|
2015-05-01 02:32:03 +02:00
|
|
|
#if ADB_HOST
|
|
|
|
|
2017-08-17 01:57:01 +02:00
|
|
|
// We use newline as our delimiter, make sure to never output it.
|
|
|
|
static std::string sanitize(std::string str, bool alphanumeric) {
|
|
|
|
auto pred = alphanumeric ? [](const char c) { return !isalnum(c); }
|
|
|
|
: [](const char c) { return c == '\n'; };
|
|
|
|
std::replace_if(str.begin(), str.end(), pred, '_');
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
static void append_transport_info(std::string* result, const char* key, const char* value,
|
2017-08-17 01:57:01 +02:00
|
|
|
bool alphanumeric) {
|
2015-05-01 02:32:03 +02:00
|
|
|
if (value == nullptr || *value == '\0') {
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
return;
|
2015-05-01 02:32:03 +02:00
|
|
|
}
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
|
2015-05-01 02:32:03 +02:00
|
|
|
*result += ' ';
|
|
|
|
*result += key;
|
2017-08-17 01:57:01 +02:00
|
|
|
*result += sanitize(value, alphanumeric);
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
static void append_transport(const atransport* t, std::string* result, bool long_listing) {
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
const char* serial = t->serial;
|
2015-05-01 02:32:03 +02:00
|
|
|
if (!serial || !serial[0]) {
|
2015-05-07 01:48:52 +02:00
|
|
|
serial = "(no serial number)";
|
2015-05-01 02:32:03 +02:00
|
|
|
}
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
|
|
|
|
if (!long_listing) {
|
2015-05-01 02:32:03 +02:00
|
|
|
*result += serial;
|
|
|
|
*result += '\t';
|
|
|
|
*result += t->connection_state_name();
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
} else {
|
2016-11-22 23:32:34 +01:00
|
|
|
android::base::StringAppendF(result, "%-22s %s", serial, t->connection_state_name().c_str());
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
|
2015-05-01 02:32:03 +02:00
|
|
|
append_transport_info(result, "", t->devpath, false);
|
|
|
|
append_transport_info(result, "product:", t->product, false);
|
|
|
|
append_transport_info(result, "model:", t->model, true);
|
|
|
|
append_transport_info(result, "device:", t->device, false);
|
2017-08-17 01:57:01 +02:00
|
|
|
|
|
|
|
// Put id at the end, so that anyone parsing the output here can always find it by scanning
|
|
|
|
// backwards from newlines, even with hypothetical devices named 'transport_id:1'.
|
|
|
|
*result += " transport_id:";
|
|
|
|
*result += std::to_string(t->id);
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
}
|
2015-05-01 02:32:03 +02:00
|
|
|
*result += '\n';
|
adb: Generalizing -s to take qualifiers.
Prior to this change, -s could take either a serial number or a
device path (e.g. "-s 01498B1F02015015" or "-s usb:1-4.2"). This
change extends -s to also allow product, model or device names
(e.g. "-s product:mysid"). These new qualifiers will only be
available on devices that are running an adb daemon that provides
properties in the connect message per Change-Id:
I09200decde4facb8fc9b4056fdae910155f2bcb9
The product, model and device are derived from the
ro.product.name, ro.product.model and ro.product.device
properties respectively. They are prefixed with "product:",
"model:" or "device:" as appropriate. In addition, any
non-alphanumerics in the model are changed to underscores.
If the -s parameter matches multiple devices, the result will be
the same as when multiple devices are connected but no -d, -e or
-s option is specified. In general, this means the user will get
"error: more than one device". However for get-state,
get-devpath and get-serialno, they will get "unknown".
The format of "devices -l" was changed to list all of the
qualifiers that are available. The following example output
(with the last digits of the serial numbers replaced with X's) is
with a Galaxy Prime with an older adb daemon and another Galaxy
Prime and Galaxy S both with the enhanced adb daemons:
List of devices attached
016B75D60A0060XX device usb:2-5 product:mysid model:Galaxy_Nexus device:toro
3731B535FAC200XX device usb:1-4.2 product:soju model:Nexus_S device:crespo
01498B1F020150XX device usb:1-4.1
Note that the serial number and state are now column oriented
instead of tab delimited. After the serial number and state, all
qualifiers are listed with each preceded by a space. The output
of the original devices command (without -l) is unchanged.
Change-Id: Iceeb2789874effc25a630d514a375d6f1889dc56
Signed-off-by: Scott Anderson <saa@android.com>
2012-05-31 03:11:27 +02:00
|
|
|
}
|
|
|
|
|
2015-05-01 02:32:03 +02:00
|
|
|
std::string list_transports(bool long_listing) {
|
2017-08-17 22:50:51 +02:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
2017-12-17 11:56:07 +01:00
|
|
|
|
|
|
|
auto sorted_transport_list = transport_list;
|
|
|
|
sorted_transport_list.sort([](atransport*& x, atransport*& y) {
|
|
|
|
if (x->type != y->type) {
|
|
|
|
return x->type < y->type;
|
|
|
|
}
|
|
|
|
return strcmp(x->serial, y->serial) < 0;
|
|
|
|
});
|
|
|
|
|
|
|
|
std::string result;
|
|
|
|
for (const auto& t : sorted_transport_list) {
|
2015-05-01 02:32:03 +02:00
|
|
|
append_transport(t, &result, long_listing);
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
2015-05-01 02:32:03 +02:00
|
|
|
return result;
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
|
2016-10-27 23:01:08 +02:00
|
|
|
void close_usb_devices(std::function<bool(const atransport*)> predicate) {
|
2017-08-17 22:50:51 +02:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
2016-10-27 23:01:08 +02:00
|
|
|
for (auto& t : transport_list) {
|
|
|
|
if (predicate(t)) {
|
|
|
|
t->Kick();
|
|
|
|
}
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
}
|
2016-10-27 23:01:08 +02:00
|
|
|
|
|
|
|
/* hack for osx */
|
|
|
|
void close_usb_devices() {
|
|
|
|
close_usb_devices([](const atransport*) { return true; });
|
|
|
|
}
|
2016-11-22 23:32:34 +01:00
|
|
|
#endif // ADB_HOST
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
int register_socket_transport(int s, const char* serial, int port, int local) {
|
2015-05-19 01:46:31 +02:00
|
|
|
atransport* t = new atransport();
|
2011-01-06 14:11:07 +01:00
|
|
|
|
|
|
|
if (!serial) {
|
2015-05-19 01:46:31 +02:00
|
|
|
char buf[32];
|
|
|
|
snprintf(buf, sizeof(buf), "T-%p", t);
|
|
|
|
serial = buf;
|
2011-01-06 14:11:07 +01:00
|
|
|
}
|
2015-05-19 01:46:31 +02:00
|
|
|
|
2015-09-03 02:44:28 +02:00
|
|
|
D("transport: %s init'ing for socket %d, on port %d", serial, s, port);
|
2013-03-30 02:22:36 +01:00
|
|
|
if (init_socket_transport(t, s, port, local) < 0) {
|
2015-05-19 01:46:31 +02:00
|
|
|
delete t;
|
2013-03-30 02:22:36 +01:00
|
|
|
return -1;
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
2013-03-30 02:22:36 +01:00
|
|
|
|
2017-08-17 22:50:51 +02:00
|
|
|
std::unique_lock<std::recursive_mutex> lock(transport_lock);
|
2015-10-08 00:59:35 +02:00
|
|
|
for (const auto& transport : pending_list) {
|
2015-05-19 01:46:31 +02:00
|
|
|
if (transport->serial && strcmp(serial, transport->serial) == 0) {
|
2016-04-30 01:53:52 +02:00
|
|
|
VLOG(TRANSPORT) << "socket transport " << transport->serial
|
2016-11-22 23:32:34 +01:00
|
|
|
<< " is already in pending_list and fails to register";
|
2015-05-19 01:46:31 +02:00
|
|
|
delete t;
|
2013-03-30 02:22:36 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
2013-03-30 02:22:36 +01:00
|
|
|
|
2015-10-08 00:59:35 +02:00
|
|
|
for (const auto& transport : transport_list) {
|
2015-05-19 01:46:31 +02:00
|
|
|
if (transport->serial && strcmp(serial, transport->serial) == 0) {
|
2016-04-30 01:53:52 +02:00
|
|
|
VLOG(TRANSPORT) << "socket transport " << transport->serial
|
2016-11-22 23:32:34 +01:00
|
|
|
<< " is already in transport_list and fails to register";
|
2015-05-19 01:46:31 +02:00
|
|
|
delete t;
|
2013-03-30 02:22:36 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-19 01:46:31 +02:00
|
|
|
pending_list.push_front(t);
|
2013-03-30 02:22:36 +01:00
|
|
|
t->serial = strdup(serial);
|
2016-09-21 21:37:10 +02:00
|
|
|
|
|
|
|
lock.unlock();
|
2013-03-30 02:22:36 +01:00
|
|
|
|
2009-03-04 04:32:55 +01:00
|
|
|
register_transport(t);
|
2013-03-30 02:22:36 +01:00
|
|
|
return 0;
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
|
2009-10-12 05:04:18 +02:00
|
|
|
#if ADB_HOST
|
2016-11-22 23:32:34 +01:00
|
|
|
atransport* find_transport(const char* serial) {
|
2015-05-19 01:46:31 +02:00
|
|
|
atransport* result = nullptr;
|
2009-10-12 05:04:18 +02:00
|
|
|
|
2017-08-17 22:50:51 +02:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
2015-08-27 21:03:11 +02:00
|
|
|
for (auto& t : transport_list) {
|
2015-05-19 01:46:31 +02:00
|
|
|
if (t->serial && strcmp(serial, t->serial) == 0) {
|
|
|
|
result = t;
|
2009-10-12 05:04:18 +02:00
|
|
|
break;
|
|
|
|
}
|
2015-05-19 01:46:31 +02:00
|
|
|
}
|
2009-10-12 05:04:18 +02:00
|
|
|
|
2015-05-19 01:46:31 +02:00
|
|
|
return result;
|
2009-10-12 05:04:18 +02:00
|
|
|
}
|
|
|
|
|
2015-08-27 21:03:11 +02:00
|
|
|
void kick_all_tcp_devices() {
|
2017-08-17 22:50:51 +02:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
2015-08-27 21:03:11 +02:00
|
|
|
for (auto& t : transport_list) {
|
2016-04-30 01:53:52 +02:00
|
|
|
if (t->IsTcpDevice()) {
|
2015-08-31 20:50:24 +02:00
|
|
|
// Kicking breaks the read_transport thread of this transport out of any read, then
|
|
|
|
// the read_transport thread will notify the main thread to make this transport
|
|
|
|
// offline. Then the main thread will notify the write_transport thread to exit.
|
2015-08-27 21:03:11 +02:00
|
|
|
// Finally, this transport will be closed and freed in the main thread.
|
2016-04-18 20:22:34 +02:00
|
|
|
t->Kick();
|
2010-05-24 16:44:35 +02:00
|
|
|
}
|
2015-05-19 01:46:31 +02:00
|
|
|
}
|
2010-05-24 16:44:35 +02:00
|
|
|
}
|
|
|
|
|
2009-10-12 05:04:18 +02:00
|
|
|
#endif
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
void register_usb_transport(usb_handle* usb, const char* serial, const char* devpath,
|
|
|
|
unsigned writeable) {
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
atransport* t = new atransport((writeable ? kCsOffline : kCsNoPerm));
|
2015-05-19 01:46:31 +02:00
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb, serial ? serial : "");
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
init_usb_transport(t, usb);
|
2016-11-22 23:32:34 +01:00
|
|
|
if (serial) {
|
2009-03-04 04:32:55 +01:00
|
|
|
t->serial = strdup(serial);
|
|
|
|
}
|
2015-05-19 01:46:31 +02:00
|
|
|
|
|
|
|
if (devpath) {
|
2012-04-20 20:21:14 +02:00
|
|
|
t->devpath = strdup(devpath);
|
|
|
|
}
|
2013-03-30 02:22:36 +01:00
|
|
|
|
2016-09-21 21:37:10 +02:00
|
|
|
{
|
2017-08-17 22:50:51 +02:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
2016-09-21 21:37:10 +02:00
|
|
|
pending_list.push_front(t);
|
|
|
|
}
|
2013-03-30 02:22:36 +01:00
|
|
|
|
2009-03-04 04:32:55 +01:00
|
|
|
register_transport(t);
|
|
|
|
}
|
|
|
|
|
2015-05-19 01:43:57 +02:00
|
|
|
// This should only be used for transports with connection_state == kCsNoPerm.
|
2016-11-22 23:32:34 +01:00
|
|
|
void unregister_usb_transport(usb_handle* usb) {
|
2017-08-17 22:50:51 +02:00
|
|
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
2018-01-29 05:32:46 +01:00
|
|
|
transport_list.remove_if([usb](atransport* t) {
|
|
|
|
if (auto connection = dynamic_cast<UsbConnection*>(t->connection.get())) {
|
|
|
|
return connection->handle_ == usb && t->GetConnectionState() == kCsNoPerm;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
2009-08-08 18:37:44 +02:00
|
|
|
}
|
2009-03-04 04:32:55 +01:00
|
|
|
|
2017-05-17 00:02:45 +02:00
|
|
|
bool check_header(apacket* p, atransport* t) {
|
2016-11-22 23:32:34 +01:00
|
|
|
if (p->msg.magic != (p->msg.command ^ 0xffffffff)) {
|
adb: fix two device offline problems.
When device goes offline, user usually has to manually replug the
usb device. This patch tries to solve two offline situations, all
because when adb on host is killed, the adbd on device is not notified.
1. When adb server is killed while pushing a large file to device,
the device is still reading the unfinished large message. So the
device thinks of the CNXN message as part of the previous unfinished
message, so it doesn't reply and the device is in offline state.
The solution is to add a write_msg_lock in atransport struct. And it
kicks the transport only after sending a whole message. By kicking
all transports before exit, we ensure that we don't write part of
a message to any device. So next time we start adb server, the device
should be waiting for a new message.
2. When adb server is killed while pulling a large file from device,
the device is still trying to send the unfinished large message. So
adb on host usually reads data with EOVERFLOW error. This is because
adb on host is reading less than one packet sent from device.
The solution is to use buffered read on host. The max packet size
of bulk transactions in USB 3.0 is 1024 bytes. By preparing an at least
1024 bytes buffer when reading, EOVERFLOW no longer occurs. And teach
adb host to ignore wrong messages.
To be safe, this patch doesn't change any logic on device.
Bug: http://b/32952319
Test: run python -m unittest -q test_device.DeviceOfflineTest
Test: on linux/mac/windows with bullhead, ryu.
Change-Id: Ib149d30028a62a6f03857b8a95ab5a1d6e9b9c4e
2017-03-11 01:01:01 +01:00
|
|
|
VLOG(RWX) << "check_header(): invalid magic command = " << std::hex << p->msg.command
|
|
|
|
<< ", magic = " << p->msg.magic;
|
2017-05-17 00:02:45 +02:00
|
|
|
return false;
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
|
2016-11-22 23:32:34 +01:00
|
|
|
if (p->msg.data_length > t->get_max_payload()) {
|
|
|
|
VLOG(RWX) << "check_header(): " << p->msg.data_length
|
|
|
|
<< " atransport::max_payload = " << t->get_max_payload();
|
2017-05-17 00:02:45 +02:00
|
|
|
return false;
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
|
2017-05-17 00:02:45 +02:00
|
|
|
return true;
|
2009-03-04 04:32:55 +01:00
|
|
|
}
|
|
|
|
|
2016-10-06 04:02:29 +02:00
|
|
|
#if ADB_HOST
|
2016-08-19 07:00:12 +02:00
|
|
|
std::shared_ptr<RSA> atransport::NextKey() {
|
2016-06-30 02:42:01 +02:00
|
|
|
if (keys_.empty()) keys_ = adb_auth_get_private_keys();
|
|
|
|
|
2016-08-19 07:00:12 +02:00
|
|
|
std::shared_ptr<RSA> result = keys_[0];
|
2016-06-30 02:42:01 +02:00
|
|
|
keys_.pop_front();
|
|
|
|
return result;
|
|
|
|
}
|
2016-10-06 04:02:29 +02:00
|
|
|
#endif
|