android adbd socket,android6.0 adbd深入分析(四)adbd usb线拔掉再连接的过程

这篇博客我们主要分析下adbd在usb线拔掉,然后再连接的代码流程。

一、log打印流程

我们先来看下自己调试的代码打印:

由于显示的问题,我把log的时间去除了,只显示了pid 和tid

//拔去usb线

185 188 I adbd : output_thread:(null): remote read failed for transport

185 188 I adbd : output_thread:(null) SYNC offline for transport

185 185 I adbd : handle_packet: A_SYNC

185 185 I adbd : handle_packet: A_SYNC CS_OFFLINE

185 187 I adbd : input_thread:(null): transport SYNC offline

185 187 I adbd : input_thread:(null): transport input thread is exiting, fd 13

185 186 I usb_adb_open_thread: adbd usb_thread - opening device

185 186 I usb_adb_open_thread: adbd opening device succeeded

185 185 I adbd : handle_packet: A_SYNC

185 185 I adbd : handle_packet: A_SYNC send_packet

185 2164 I adbd : input_thread:(null): transport SYNC online

//插上usb线

185 2165 I adbd : output_thread: read_from_remote after

185 185 I adbd : handle_packet: A_CNXN

185 185 I adbd : handle_packet: A_CNXN handle_online

185 185 I adbd : handle_packet: A_CNXN send_connect

185 2165 I adbd : output_thread: read_from_remote after

185 185 I adbd : adb command: 'shell:dumpsys iphonesubinfo'

185 2165 I adbd : output_thread: read_from_remote after

185 2165 I adbd : output_thread: read_from_remote after

185 185 I adbd : adb command: 'shell:dumpsys battery'

185 2165 I adbd : output_thread: read_from_remote after

185 2165 I adbd : output_thread: read_from_remote after

185 2165 I adbd : output_thread: read_from_remote after

185 185 I adbd : handle_packet: A_CNXN

185 185 I adbd : handle_packet: A_CNXN handle_offline

185 185 I adbd : handle_packet: A_CNXN handle_online

185 185 I adbd : handle_packet: A_CNXN send_connect

二、拔usb线流程

2.1 output_thread读取adb驱动的数据出错

我们按照log看,首先就是output_thread读取adb驱动的数据出错了

static void *output_thread(void *_t)

{

atransport *t = reinterpret_cast(_t);

apacket *p;

D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",

t->serial, t->fd, t->sync_token + 1);

p = get_apacket();

p->msg.command = A_SYNC;

p->msg.arg0 = 1;

p->msg.arg1 = ++(t->sync_token);

p->msg.magic = A_SYNC ^ 0xffffffff;

if(write_packet(t->fd, t->serial, &p)) {

put_apacket(p);

D("%s: failed to write SYNC packet\n", t->serial);

goto oops;

}

D("%s: data pump started\n", t->serial);

for(;;) {

p = get_apacket();

if(t->read_from_remote(p, t) == 0){

D("%s: received remote packet, sending to transport\n",

t->serial);

if(write_packet(t->fd, t->serial, &p)){

put_apacket(p);

D("%s: failed to write apacket to transport\n", t->serial);

LOG("%s:%s: failed to write apacket to transport\n", __FUNCTION__, t->serial);

goto oops;

}

} else {

D("%s: remote read failed for transport\n", t->serial);

LOG("%s:%s: remote read failed for transport\n", __FUNCTION__, t->serial);//读取adb驱动数据失败

put_apacket(p);

break;

}

}

D("%s: SYNC offline for transport\n", t->serial);

LOG("%s:%s SYNC offline for transport\n", __FUNCTION__, t->serial);//线程退出

p = get_apacket();

p->msg.command = A_SYNC;

p->msg.arg0 = 0;

p->msg.arg1 = 0;

p->msg.magic = A_SYNC ^ 0xffffffff;

if(write_packet(t->fd, t->serial, &p)) {//往sockpair另一侧写信息

put_apacket(p);

D("%s: failed to write SYNC apacket to transport", t->serial);

}output_thread读取adb驱动的数据出错了,然后退出线程并发送sockpair的另一侧数据

另一侧的socketpair关联的函数是transport_socket_events函数

fdevent_install(&(t->transport_fde),

t->transport_socket,

transport_socket_events,

t);

transport_socket_events函数,接着调用了handle_packet函数

static void transport_socket_events(int fd, unsigned events, void *_t)

{

atransport *t = reinterpret_cast(_t);

D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events);

if(events & FDE_READ){

apacket *p = 0;

if(read_packet(fd, t->serial, &p)){

D("%s: failed to read packet from transport socket on fd %d\n", t->serial, fd);

} else {

handle_packet(p, (atransport *) _t);

}

}

}

2.2 handle_packet处理offline

handle_packet函数收到A_SYNC命令,然后处理offline

void handle_packet(apacket *p, atransport *t)

{

asocket *s;

D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],

((char*) (&(p->msg.command)))[1],

((char*) (&(p->msg.command)))[2],

((char*) (&(p->msg.command)))[3]);

print_packet("recv", p);

switch(p->msg.command){

case A_SYNC:

LOG("%s: A_SYNC \n", __FUNCTION__);//进入sync

if(p->msg.arg0){

send_packet(p, t);

LOG("%s: A_SYNC send_packet\n", __FUNCTION__);

if(HOST) send_connect(t);

} else {

t->connection_state = CS_OFFLINE;

LOG("%s: A_SYNC CS_OFFLINE\n", __FUNCTION__);//offline处理

handle_offline(t);

send_packet(p, t);

}

return;

hand_packet处理sync消息,我们先来看handle_offline函数,其实就是把状态处理下

void handle_offline(atransport *t)

{

D("adb: offline\n");

//Close the associated usb

t->online = 0;

run_transport_disconnects(t);

}

2.3 Input_thread处理offline

处理offline的我们看send_packet也是往socketpair的另一侧写数据,这样inputThread会有数据接收

static void *input_thread(void *_t)

{

atransport *t = reinterpret_cast(_t);

apacket *p;

int active = 0;

D("%s: starting transport input thread, reading from fd %d\n",

t->serial, t->fd);

for(;;){

if(read_packet(t->fd, t->serial, &p)) {

D("%s: failed to read apacket from transport on fd %d\n",

t->serial, t->fd );

LOG("%s:%s: failed to read apacket from transport on fd %d\n", __FUNCTION__, t->serial, t->fd );

break;

}

if(p->msg.command == A_SYNC){

if(p->msg.arg0 == 0) {

D("%s: transport SYNC offline\n", t->serial);

put_apacket(p);

LOG("%s:%s: transport SYNC offline\n", __FUNCTION__, t->serial);//收到handle_packet发来的offline的消息,跳出循环

break;

} else {

if(p->msg.arg1 == t->sync_token) {

LOG("%s:%s: transport SYNC online\n", __FUNCTION__, t->serial);

active = 1;

} else {

D("%s: transport ignoring SYNC %d != %d\n",

t->serial, p->msg.arg1, t->sync_token);

}

}

} else {

if(active) {

D("%s: transport got packet, sending to remote\n", t->serial);

t->write_to_remote(p, t);

} else {

D("%s: transport ignoring packet while offline\n", t->serial);

}

}

put_apacket(p);

}

// this is necessary to avoid a race condition that occured when a transport closes

// while a client socket is still active.

close_all_sockets(t);

D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd);

LOG("%s:%s: transport input thread is exiting, fd %d\n", __FUNCTION__, t->serial, t->fd);//线程结束

kick_transport(t);//调用了kick_transport函数

transport_unref(t);

return 0;

Input_thread收到handle_packet发来的offline消息,直接退出线程,并且调用了kick_transport函数

void kick_transport(atransport* t)

{

if (t && !t->kicked)

{

int kicked;

adb_mutex_lock(&transport_lock);

kicked = t->kicked;

if (!kicked)

t->kicked = 1;

adb_mutex_unlock(&transport_lock);

if (!kicked)

t->kick(t);

}

}

这里调用了kick其实是remote_kick函数

void init_usb_transport(atransport *t, usb_handle *h, int state)

{

D("transport: usb\n");

t->close = remote_close;

t->kick = remote_kick;

t->read_from_remote = remote_read;

t->write_to_remote = remote_write;

t->sync_token = 1;

t->connection_state = state;

t->type = kTransportUsb;

t->usb = h;

#if ADB_HOST

HOST = 1;

#else

HOST = 0;

#endif

}

remote_kick调用了usb_kick函数

static void remote_kick(atransport *t)

{

usb_kick(t->usb);

}然后才调用了usb_handle的kick函数

void usb_kick(usb_handle *h)

{

h->kick(h);

}

在usb_adb_init初始化的时候kick为usb_adb_kick

static void usb_adb_init()

{

usb_handle* h = reinterpret_cast(calloc(1, sizeof(usb_handle)));

if (h == nullptr) fatal("couldn't allocate usb_handle");

h->write = usb_adb_write;

h->read = usb_adb_read;

h->kick = usb_adb_kick;

我们再来看看这个函数,最终是发送了一个signal

static void usb_adb_kick(usb_handle *h)

{

D("usb_kick\n");

adb_mutex_lock(&h->lock);

adb_close(h->fd);

h->fd = -1;

// notify usb_adb_open_thread that we are disconnected

adb_cond_signal(&h->notify);

adb_mutex_unlock(&h->lock);

}

而就是这个signal导致usb_adb_open_thread等待的状态打破,重新打开了adb驱动,然后重新开启input_thread output_thread

static void *usb_adb_open_thread(void *x)

{

struct usb_handle *usb = (struct usb_handle *)x;

int fd;

while (true) {

// wait until the USB device needs opening

adb_mutex_lock(&usb->lock);

while (usb->fd != -1)

adb_cond_wait(&usb->notify, &usb->lock);// 等待信号

adb_mutex_unlock(&usb->lock);

D("[ usb_thread - opening device ]\n");//重新打开adb驱动

__android_log_print(ANDROID_LOG_INFO, __FUNCTION__,

"adbd usb_thread - opening device\n");

do {

/* XXX use inotify? */

fd = unix_open("/dev/android_adb", O_RDWR);

if (fd < 0) {

// to support older kernels

fd = unix_open("/dev/android", O_RDWR);

}

if (fd < 0) {

adb_sleep_ms(1000);

}

} while (fd < 0);

D("[ opening device succeeded ]\n");

__android_log_print(ANDROID_LOG_INFO, __FUNCTION__,

"adbd opening device succeeded\n");

close_on_exec(fd);

usb->fd = fd;

D("[ usb_thread - registering device ]\n");

register_usb_transport(usb, 0, 0, 1);//注册usb通道,最好开启input_thread和output_thread

}

// never gets here

return 0;

}

2.3 重启开启output_thread input_thread线程

然后在output_thread打开后,先会往handle_packet发送一个A_SYNC命令

static void *output_thread(void *_t)

{

atransport *t = reinterpret_cast(_t);

apacket *p;

D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",

t->serial, t->fd, t->sync_token + 1);

p = get_apacket();

p->msg.command = A_SYNC;

p->msg.arg0 = 1;

p->msg.arg1 = ++(t->sync_token);

p->msg.magic = A_SYNC ^ 0xffffffff;

if(write_packet(t->fd, t->serial, &p)) {

put_apacket(p);

D("%s: failed to write SYNC packet\n", t->serial);

goto oops;

}

然后到handle_packet如何处理这个sync命令的呢

void handle_packet(apacket *p, atransport *t)

{

asocket *s;

D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],

((char*) (&(p->msg.command)))[1],

((char*) (&(p->msg.command)))[2],

((char*) (&(p->msg.command)))[3]);

print_packet("recv", p);

switch(p->msg.command){

case A_SYNC:

LOG("%s: A_SYNC \n", __FUNCTION__);

if(p->msg.arg0){//为1

send_packet(p, t);//就又往input_thread发送包了

LOG("%s: A_SYNC send_packet\n", __FUNCTION__);

if(HOST) send_connect(t);

} else {

t->connection_state = CS_OFFLINE;

LOG("%s: A_SYNC CS_OFFLINE\n", __FUNCTION__);

handle_offline(t);

send_packet(p, t);

}

return;

而input_thread收到这sync命令后的处理如下:

static void *input_thread(void *_t)

{

atransport *t = reinterpret_cast(_t);

apacket *p;

int active = 0;

D("%s: starting transport input thread, reading from fd %d\n",

t->serial, t->fd);

for(;;){

if(read_packet(t->fd, t->serial, &p)) {

D("%s: failed to read apacket from transport on fd %d\n",

t->serial, t->fd );

LOG("%s:%s: failed to read apacket from transport on fd %d\n", __FUNCTION__, t->serial, t->fd );

break;

}

if(p->msg.command == A_SYNC){

if(p->msg.arg0 == 0) {

D("%s: transport SYNC offline\n", t->serial);

put_apacket(p);

LOG("%s:%s: transport SYNC offline\n", __FUNCTION__, t->serial);

break;

} else {

if(p->msg.arg1 == t->sync_token) {//收到sync命令后,将active置为1,代表下次就可以往adb驱动写了

D("%s: transport SYNC online\n", t->serial);

LOG("%s:%s: transport SYNC online\n", __FUNCTION__, t->serial);

active = 1;

} else {

D("%s: transport ignoring SYNC %d != %d\n",

t->serial, p->msg.arg1, t->sync_token);

LOG("%s:%s: transport ignoring SYNC\n", __FUNCTION__, t->serial);

}

}

} else {

if(active) {

D("%s: transport got packet, sending to remote\n", t->serial);

t->write_to_remote(p, t);

} else {

D("%s: transport ignoring packet while offline\n", t->serial);

}

}

put_apacket(p);

}

input_thread收到sync命令后将active置为1,代表下次有数据过来可以往adb驱动里面写了。

但是是不是有个疑问,因为这个时候usb先拔了,而且没有再插上,那为什么这个时候input_thread可以往adb驱动写数据呢?答案在这里:static void *output_thread(void *_t)

{

atransport *t = reinterpret_cast(_t);

apacket *p;

D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",

t->serial, t->fd, t->sync_token + 1);

p = get_apacket();

p->msg.command = A_SYNC;

p->msg.arg0 = 1;

p->msg.arg1 = ++(t->sync_token);

p->msg.magic = A_SYNC ^ 0xffffffff;

if(write_packet(t->fd, t->serial, &p)) {

put_apacket(p);

D("%s: failed to write SYNC packet\n", t->serial);

goto oops;

}

D("%s: data pump started\n", t->serial);

for(;;) {

p = get_apacket();

//在这里修改了代码,本来没有result变量的,这个函数直接在if判断中,这里我们把它分开,并且打log,就是为了验证这个函数是否阻塞

int result = t->read_from_remote(p, t);//没有插上usb线,这个函数一直会阻塞

LOG("%s: read_from_remote after\n", __FUNCTION__);

if(result == 0){

D("%s: received remote packet, sending to transport\n",

t->serial);

if(write_packet(t->fd, t->serial, &p)){

put_apacket(p);

D("%s: failed to write apacket to transport\n", t->serial);

LOG("%s:%s: failed to write apacket to transport\n", __FUNCTION__, t->serial);

goto oops;

}

} else {

D("%s: remote read failed for transport\n", t->serial);

LOG("%s:%s: remote read failed for transport\n", __FUNCTION__, t->serial);

put_apacket(p);

break;

}

}这个时候我们在output_thread里面稍微修改了代码,并且增加了log,发现没有插上usb线的时候,这个时候output_thread在读取adb驱动数据的时候会阻塞,这样也就不会有数据传到input_thread往adb驱动中写了,当然就不会有问题了。

三、插上usb线流程

下面我们再来分析细插上usb线的代码流程:

我们先看log,拔去usb线先打印了read_from_remote after这个log,说明这个时候output_thread从adb驱动读取数据不再阻塞了,然后就把数据发送了handle_packet.

handle_packet这个时候直接收到adb驱动来的 A_CNXN命令:

case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */

/* XXX verify version, etc */

LOG("%s: A_CNXN\n", __FUNCTION__);

if(t->connection_state != CS_OFFLINE) {

t->connection_state = CS_OFFLINE;

handle_offline(t);

LOG("%s: A_CNXN handle_offline\n", __FUNCTION__);

}

parse_banner(reinterpret_cast(p->data), t);

if (HOST || !auth_required) {

handle_online(t);

LOG("%s: A_CNXN handle_online\n", __FUNCTION__);

if (!HOST) {

send_connect(t);

LOG("%s: A_CNXN send_connect\n", __FUNCTION__);

}

} else {

send_auth_request(t);

LOG("%s: A_CNXN send_auth_request\n", __FUNCTION__);

}

break;

由于一开始,transport的connection_state = CS_OFFLINE,所以先处理了handle_online, 然后调用了send_connect函数:

void handle_online(atransport *t)

{

D("adb: online\n");

t->online = 1;

}

send_connect就是往input_thread发送连接信息,最后就是往adb驱动发送, 这样pc就知道和adbd连接上了。

void send_connect(atransport *t)

{

D("Calling send_connect \n");

apacket *cp = get_apacket();

cp->msg.command = A_CNXN;

cp->msg.arg0 = A_VERSION;

cp->msg.arg1 = MAX_PAYLOAD;

cp->msg.data_length = fill_connect_data((char *)cp->data,

sizeof(cp->data));

send_packet(cp, t);

}

还有就是,在parse_banner这个函数中对connection_state做了处理

void parse_banner(const char* banner, atransport* t) {

D("parse_banner: %s\n", banner);

// The format is something like:

// "device::ro.product.name=x;ro.product.model=y;ro.product.device=z;".

std::vector<:string> pieces = android::base::Split(banner, ":");

if (pieces.size() > 2) {

const std::string& props = pieces[2];

for (auto& prop : android::base::Split(props, ";")) {

// The list of properties was traditionally ;-terminated rather than ;-separated.

if (prop.empty()) continue;

std::vector<:string> key_value = android::base::Split(prop, "=");

if (key_value.size() != 2) continue;

const std::string& key = key_value[0];

const std::string& value = key_value[1];

if (key == "ro.product.name") {

qual_overwrite(&t->product, value);

} else if (key == "ro.product.model") {

qual_overwrite(&t->model, value);

} else if (key == "ro.product.device") {

qual_overwrite(&t->device, value);

}

}

}

const std::string& type = pieces[0];

if (type == "bootloader") {

D("setting connection_state to CS_BOOTLOADER\n");

t->connection_state = CS_BOOTLOADER;

update_transports();

} else if (type == "device") {

D("setting connection_state to CS_DEVICE\n");

t->connection_state = CS_DEVICE;

update_transports();

} else if (type == "recovery") {

D("setting connection_state to CS_RECOVERY\n");

t->connection_state = CS_RECOVERY;

update_transports();

} else if (type == "sideload") {

D("setting connection_state to CS_SIDELOAD\n");

t->connection_state = CS_SIDELOAD;

update_transports();

} else {

D("setting connection_state to CS_HOST\n");

t->connection_state = CS_HOST;

}

}

因此我在处理A_CNXN的时候,在parse_banner前后打了log

case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */

/* XXX verify version, etc */

LOG("%s: A_CNXN\n", __FUNCTION__);

if(t->connection_state != CS_OFFLINE) {

t->connection_state = CS_OFFLINE;

handle_offline(t);

LOG("%s: A_CNXN handle_offline\n", __FUNCTION__);

}

LOG("%s: A_CNXN parse_banner before: connection_state:%d\n", __FUNCTION__, t->connection_state);

parse_banner(reinterpret_cast(p->data), t);

LOG("%s: A_CNXN parse_banner after: connection_state:%d\n", __FUNCTION__, t->connection_state);

最后发现当插上usb线的时候,一开始connection_state:0也就是CS_OFFLINE, 后面变成了3也就是CS_HOST

185 185 I adbd : handle_packet: A_CNXN

185 185 I adbd : handle_packet: A_CNXN parse_banner before: connection_state:0

185 185 I adbd : handle_packet: A_CNXN parse_banner after: connection_state:3

185 185 I adbd : handle_packet: A_CNXN handle_online

185 185 I adbd : handle_packet: A_CNXN send_connect

至于后面一些log,shell:dumpsys iphonesubinfo‘  shell:dumpsys battery‘都是一些别的命令

//插上usb线185   185 I adbd    : handle_packet: A_CNXN

185   185 I adbd    : handle_packet: A_CNXN parse_banner before: connection_state:0

185   185 I adbd    : handle_packet: A_CNXN parse_banner after: connection_state:3

185   185 I adbd    : handle_packet: A_CNXN handle_online

185   185 I adbd    : handle_packet: A_CNXN send_connect

185   185 I adbd    : adb command: 'shell:dumpsys iphonesubinfo'

185   185 I adbd    : adb command: 'shell:dumpsys battery'

185   185 I adbd    : handle_packet: A_CNXN

185   185 I adbd    : handle_packet: A_CNXN handle_offline

185   185 I adbd    : handle_packet: A_CNXN parse_banner before: connection_state:0

185   185 I adbd    : handle_packet: A_CNXN parse_banner after: connection_state:3

185   185 I adbd    : handle_packet: A_CNXN handle_online

185   185 I adbd    : handle_packet: A_CNXN send_connect

最后还有一个命令先处理handle_offline,状态先为0,再改为3

case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */

/* XXX verify version, etc */

LOG("%s: A_CNXN\n", __FUNCTION__);

if(t->connection_state != CS_OFFLINE) {

t->connection_state = CS_OFFLINE;// handleoffline了后connection_state = CS_OFFLINE就为0了

handle_offline(t);

LOG("%s: A_CNXN handle_offline\n", __FUNCTION__);

}

LOG("%s: A_CNXN parse_banner before: connection_state:%d\n", __FUNCTION__, t->connection_state);

parse_banner(reinterpret_cast(p->data), t);

LOG("%s: A_CNXN parse_banner after: connection_state:%d\n", __FUNCTION__, t->connection_state);

......

至于最后为什么会连接两次,不是很明白,这应该是协议规定的。



原文:http://blog.csdn.net/kc58236582/article/details/51151123

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值