这篇博客我们主要分析下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<atransport*>(_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<atransport*>(_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<atransport*>(_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<usb_handle*>(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<atransport*>(_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<atransport*>(_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<atransport*>(_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<const char*>(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<std::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<std::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<const char*>(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<const char*>(p->data), t); LOG("%s: A_CNXN parse_banner after: connection_state:%d\n", __FUNCTION__, t->connection_state); ......
至于最后为什么会连接两次,不是很明白,这应该是协议规定的。