ADB(Android Debug Bridge)(4)

 这篇博客梳理Device端adbd是如何运作的,最好有前面的文章,1、Android开发工具——ADB(Android Debug Bridge) <一>概览,2、Android开发工具——ADB(Android Debug Bridge) <二>HOST端,3、Android开发工具——ADB(Android Debug Bridge) <三>DalvikVM之jdwp线程

在adbd起来时,也会监听TCP:5037端口(好像没有使用),扫描当前USB设备,注册好usb transport,等待远端的连接,同时启动jdwp服务,与虚拟机的jdwp线程进行握手通信。

  先看HOST和DEVICE的连接过程。

  HOST首先发出connect请求,数据包内容如下

 

apacket *cp = get_apacket();   cp->msg.command = A_CNXN;   cp->msg.arg0 = A_VERSION;   cp->msg.arg1 = MAX_PAYLOAD;   snprintf((char*) cp->data, sizeof cp->data, "%s::",           HOST ? "host" : adb_device_banner);  

         DEVICE端收到以后,解析后设置transport的状态为HOST,然后给host回一个同样的connect请求,只不过data由"host::"变成了"device::",

HOST收到DEVICE的connect请求后,解析,

if(!strcmp(type, "device")) {       D("setting connection_state to CS_DEVICE\n");       t->connection_state = CS_DEVICE;       update_transports();       return;   }  

          update_transports供client发送adb track-devices命令时有用。

因此到此时为止,HOST和DEVICE已经处于online状态,准备好其它的通信了。

这里以adb jdwp命令为例说明,jdwp是获取当前device中注册了jdwp传输的进程列表。看看jdwp是怎么从HOST到DEVICE端的。

if (!strcmp(argv[0], "jdwp")) {       int  fd = adb_connect("jdwp");       if (fd >= 0) {           read_and_dump(fd);           adb_close(fd);           return 0;       } else {           fprintf(stderr, "error: %s\n", adb_error());           return -1;       }   }  

这是调用adb_connect,然后直接从里面读取结果,在发送“jdwp”之前,先调用

int fd = _adb_connect("host:version");  

校验,adb版本。_adb_connect中,如果碰到“host”打头的请求,则切换transport。

if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd)) {       return -1;   }  

在switch_socket_transport中,如果刚开始在adb命令中未指定serial 和transport type, 则,将“host:transport-any‘发往5037端口

 

if(writex(fd, tmp, 4) || writex(fd, service, len)) {       strcpy(__adb_error, "write failure during connection");       adb_close(fd);       return -1;   }  

等待返回一个“OKAY”

if(adb_status(fd)) {       adb_close(fd);       return -1;   }  

在里面判断返回结果是否为“OK”

 

int adb_status(int fd)   {       unsigned char buf[5];       unsigned len;          if(!memcmp(buf, "OKAY", 4)) {           return 0;       }   }  

TCP:5037的另一端,也就是service,它的读写处理函数是local_socket_event_func,将"host:transport-any"读取出来,调用s->peer->enqueue(s->peer, p);也就是smart_socket_enqueue进行处理,

smart_socket_enqueue->handle_host_request->acquire_one_transport处理host:transport-any"请求。

在acquire_one_transport中,会查询当前的transport_list,取出符合用户要求的transport,如果有多个,则返回错误。然后,将该transport赋给当前的socket。往TCP:5037回一个“OKAY”

 

transport = acquire_one_transport(CS_ANY, type, serial, &error_string);      if (transport) {       s->transport = transport;       adb_write(reply_fd, "OKAY", 4);   else {       sendfailmsg(reply_fd, error_string);   }  

由此可知,切换transport后,才将"host:version"请求发送到TCP:5037端口,同样经过smart_socket_enqueue->handle_host_request函数,执行下面语句

 

// returns our value for ADB_SERVER_VERSION    if (!strcmp(service, "version")) {       char version[12];       snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);       snprintf(buf, sizeof buf, "OKAY%04x%s", (unsigned)strlen(version), version);       writex(reply_fd, buf, strlen(buf));       return 0;   }  

返回结果的先导也有一个OKAY。TCP:5037的另一端,也就是service,它的读写处理函数是local_socket_event_func,讲"host:version"结果

再来看“jdwp”请求,smart_socket_enqueue->handle_host_request,handle_host_request发现处理不了,所以回到smart_socket_enqueue继续执行下面语句,

 

s->peer->ready = local_socket_ready_notify;   s->peer->close = local_socket_close_notify;   s->peer->peer = 0;       /* give him our transport and upref it */   s->peer->transport = s->transport;      connect_to_remote(s->peer, (char*) (p->data + 4));   s->peer = 0;   s->close(s);  

这段语句,将smart soeckt关闭,然后将transport交给local socket,这样,connect_to_remote的参数就是local socket, “jdwp”,在connect_to_remote

 

p->msg.command = A_OPEN;   p->msg.arg0 = s->id;   p->msg.data_length = len;   strcpy((char*) p->data, destination);   send_packet(p, s->transport);  


把A_OPEN命令发给DEVICE端,id是socket的唯一标识,在初始化local socket的时候就确定,便于远端回复数据过来时,在socket list中能查找到该socket进行处理

 

void install_local_socket(asocket *s)   {       adb_mutex_lock(&socket_list_lock);          s->id = local_socket_next_id++;       insert_local_socket(s, &local_socket_list);          adb_mutex_unlock(&socket_list_lock);   }  

在DEVICE端的output_thread线程,读取到消息,写到transport_socket里面去

 

for(;;) {       p = get_apacket();          if(t->read_from_remote(p, t) == 0){           D("from_remote: received remote packet, sending to transport %p\n",             t);           if(write_packet(t->fd, &p)){               put_apacket(p);               D("from_remote: failed to write apacket to transport %p", t);               goto oops;           }       } else {           D("from_remote: remote read failed for transport %p\n", p);           put_apacket(p);           break;       }   }  

transport_socket的处理函数transport_socket_events调用handle_packet进行处理,读取到A_OPEN命令,先调用create_local_service_socket创建local socket,在调用create_remote_socket创建remote socket,

create_local_service_socket->create_jdwp_service_socket,回调:

 

s->socket.ready   = jdwp_socket_ready;   s->socket.enqueue = jdwp_socket_enqueue;   s->socket.close   = jdwp_socket_close;   s->pass           = 0;   


create_remote_socket的回调:这里的id是HOST端的local socket的id。

 

s->id = id;   s->enqueue = remote_socket_enqueue;   s->ready = remote_socket_ready;   s->close = remote_socket_close;   s->transport = t;  


然后调用    

 

                send_ready(s->id, s->peer->id, t);                   s->ready(s);  


 这里的s->id是DEVICE端local socket的id, s->peer->是HOST端的local socket的id。

 

static void send_ready(unsigned local, unsigned remote, atransport *t)   {       D("Calling send_ready \n");       apacket *p = get_apacket();       p->msg.command = A_OKAY;       p->msg.arg0 = local;       p->msg.arg1 = remote;       send_packet(p, t);   }  


这样,表示HOST端发送的A_OPEN命令成功了,DEVICE端的output_thread接收到以后,

 

case A_OKAY: /* READY(local-id, remote-id, "") */       if(t->connection_state != CS_OFFLINE) {           if((s = find_local_socket(p->msg.arg1))) {               if(s->peer == 0) {                   s->peer = create_remote_socket(p->msg.arg0, t);                   s->peer->peer = s;               }               s->ready(s);           }       }       break;  


根据id,找回local socket,同时创建remote socket。

前面看到,DEVICE端创建好local socket和remote socket之后,除了往HOST发一个OKAY,还调用

 

s->ready(s);  


这里的s是local jdwp service socket,来看它的ready函数jdwp_socket_ready

 

apacket*  p = get_apacket();   p->len = jdwp_process_list((char*)p->data, MAX_PAYLOAD);   peer->enqueue(peer, p);   jdwp->pass = 1;  


将jdwp服务中的进程号,写入packet,调用remote socket的enqueue,也就是remote_socket_enqueue

 

static int remote_socket_enqueue(asocket *s, apacket *p)   {       D("Calling remote_socket_enqueue\n");       p->msg.command = A_WRTE;       p->msg.arg0 = s->peer->id;       p->msg.arg1 = s->id;       p->msg.data_length = p->len;       send_packet(p, s->transport);       return 1;   }  


它进程信息,写入transport,HOST的output_thread收到以后

 

case A_WRTE:                                                                     if(t->connection_state != CS_OFFLINE) {                                          if((s = find_local_socket(p->msg.arg1))) {                                       unsigned rid = p->msg.arg0;                                                  p->len = p->msg.data_length;                                                                                                                              if(s->enqueue(s, p) == 0) {                                                      D("Enqueue the socket\n");                                                   send_ready(s->id, rid, t);                                               }                                                                            return;                                                                  }                                                                        }                                                                            break;      

它调用local socket的enqueue函数local_socket_enqueue,在local_socket_enqueue里面,调用

 

int r = adb_write(s->fd, p->ptr, p->len);  

写入端口5037,这样,client就能看到jdwp的进程信息了。就像下面这样。

 

[yinlijun@localhost adb]$ adb jdwp   228   277   111   176   185   188   180   208   212   330   339   351   361   370   378   407   416   427   438   446   455  

因此,流程应该大致如图所示,具体的步骤太复杂,只能粗略表示一下。

ADB(Android Debug Bridge)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wyjxzp.html