博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
adb流水账
阅读量:4207 次
发布时间:2019-05-26

本文共 6407 字,大约阅读时间需要 21 分钟。

基于29版的adb代码,相同颜色段落有对应关系

------------------------------

adb devices命令

-------------------------------

adb devices 命令呼叫host端的adb程序,参数时devices 》进入adb.c的main函数 》adb_commandline函数 》向adb_query 传递host:devices,adb_query函数处理完后,adb程序(client)就退出了 》adb_connect调用成功的话,会分两次返回数据,把数据输出到stdout 》adb_connect会先获取host:version,获取失败的情况下(adb server还未运行) 》 启动launch_server(5037),等待一段时间后,再次调用adb_connect 》launch_server(5037)创建一个pipe,fd[0]留给父进程,子进程会把stderr重定向到fd[1] 》进行fork 》 子进程把stderr重定向到fd[1],然后执行execl(path,“adb”,“fork-server”,“server”,NULL)去创建adb server 》 父进程会阻塞在pipe的fd[0]这里,直到读取到server端的回覆,如果回覆是“OK”的话,调用setsid()使得server进程正式独立,父进程从launch_server函数返回(等待一段时间后,再次调用adb_connect)》子进程创建adb server,会先携带“fork-server”,“server”参数进入adb.c main函数 》adb_commandline 》is_server=1,is_deamon=1,__adb_server_port=5037 》adb_main(1,5037) HOST=1 》init_transport_registration 》usb_vendors_init,usb_init 》local_init 》install_listener 》init_jdwp 》向stderr输出“OK” 通知父进程server启动完毕 》 start_logging 》进入 fdevent_loop 循环,server就创建成功,然后可以响应client端adb_connect的呼叫;

adb server进程:

init_transport_registration 》adb_socketpair创建socket,transport_registration_send,transport_registration_recv就是这个socket的两端  》fdevent_install给transport_registration_fde赋值,把transport_registration_fde与 transport_registration_recv端口联系起来,设置transport_registration_func为处理函数 》把transport_registration_fde注册进fd_table中 》把transport_registration_fde放进集合read_fds中(为select函数做准备); 

usb_vendors_init 》 初始化vendorIds,并加入adb_usb.ini指定的客户id;

usb_init 》 创建线程,线程处理函数device_poll_thread 》会进入一个无限循环,每隔一段时间调用 find_usb_device + kick_disconnected_devices 》find_usb_device("/dev/bus/usb", register_device) 搜索所有usb设备,通过与vendorIds比较确定是否为adb设备 》 对于adb设备调用 register_device进行注册 》 把adb 设备注册进handle_list列表 》 register_usb_transport 》 分配一个atransport结构体,把adb设备对应的usb_handle和atransport关联起来,并设置相关的处理函数(remote_xxxx),设置类型为kTransportUsb,HOST=1 》register_transport 》构造一个tmsg,其包含这个atransport和一个action(这里为1,表示添加)》把这个tmsg写入 transport_registration_send;kick_disconnected_devices 函数的目的是去看看搜索到的所有adb设备是否还正常,不正常的话从transport_list剔除;

local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT) 》 local_init(5555)》从端口5555到5585进行扫描,由于HOST=1,创建client_socket_thread线程 》local_connect 》local_connect_arbitrary_ports 》socket_loopback_client 》如果返回>0,register_socket_transport 》构造kTransportLocal类型的atransport,并把atransport注册到local_transports中 》register_transport 》t 》同样构造一个tmsg,其包含这个atransport和一个action(这里为1,表示添加)》把这个tmsg写入 transport_registration_send

install_listener("tcp:5037", "*smartsocket*", NULL) 》 构造一个alistener 》local_name_to_fd("tcp:5037"),调用socket_loopback_server(5037, SOCK_STREAM) 连接到5037端口,alistener->fd赋值为socket_loopback_server的返回文件描述符 》fdevent_install 把alistener->fde注册进入fd_table,设置ss_listener_event_func()为处理函数 》 把alistener->fde放进集合read_fds中(为select函数做准备)》把alistener放进listener_list列表中,这样select函数调用后就会开始监听client向5037发送的请求;

/* A listener is an entity which binds to a local port

** and, upon receiving a connection on that port, creates
** an asocket to connect the new local connection to a
** specific remote service.
**
** TODO: some listeners read from the new connection to
** determine what exact service to connect to on the far
** side.
*/
struct alistener
{
    alistener *next;
    alistener *prev;
    fdevent fde;
    int fd;
    const char *local_name;
    const char *connect_to;
    atransport *transport;
    adisconnect  disconnect;
};

start_logging 》 将stdin重定向到/dev/null,将stdout、stderr重定向到/tmp/adb.log,然后输出adb starting到stderr;

fdevent_loop 》 fdevent_subproc_setup,创建一个socket,SHELL_EXIT_NOTIFY_FD为其中一端;创建一个fdevent,这个fdevent与socket的另外一端连接上,处理函数为fdevent_subproc_event_func,注册进入fd_table,fdevent_install然后放进集合read_fds中(为select函数做准备);》进入一个无限循环中,不断的fdevent_process + fdevent_call_fdfunc; 》函数fdevent_process,取出read_fds,write_fds,error_fds 》开始select函数,select(select_n, &rfd, &wfd, &efd, NULL),阻塞方式等待文件描述符的变化 》从fd_table找到需要处理的fde,将state设置为FDE_PENDING 》fdevent_plist_enqueue将待处理的fde放进list_pending 》fdevent_plist_dequeue从list_pending中取出一个fdevent 》fdevent_call_fdfunc(fde),调用fdevent设置的func函数处理,fde->func(fde->fd, events, fde->arg)

注册atransport的数据通过tmsg写入 transport_registration_send,transport_registration_recv端会收到对应的数据,调用transport_registration_func来处理 》 从transport_registration_recv端取出tmsg得到atransport 》创建一个socket,把t->transport_socket,t->fd分别设置为这个socket的两端 》fevent_install将t->transport_fde与t->transport_socket关联起来,并放入fd_table中,处理函数是transport_socket_events 》把t->transport_fde放进集合read_fds中(为select函数做准备)》创建input_thread和output_thread线程 》把atransport放进transport_list列表中 》 update_transports通知列表更新;
input_thread线程进入无限循环,不断read_packet(t->fd, t->serial, &p),output_thread线程进入无限循环,不断write_packet(t->fd, t->serial, &p)
?? 不明白input_thread,output_thread的作用??
在这里创建套接字对,一个是fd,负责从远端读入,或者写入远端。transport_socket负责跟本地(emulator或者device)交互,同时启动两个线程output_thread,调用read_from_remote从远端读入,还有input_thread,调用write_to_remote写入远端。
adb client进程:
开始向server发送请求,adb_commandline函数中调用adb_query,开始adb_connect函数 》_adb_connect("host:version")先去获取版本,在_adb_connect中调用socket_loopback_client(5037, SOCK_STREAM) 连接5037,之前adb server已经开始监听5037端口,client和service之间就可以开始通信了》版本信息正确的话,_adb_connect("host:devices") ,读取出回覆内容
在server进程:
触发处理函数ss_listener_event_func() 》accept 5037后,create_local_socket + connect_to_smartsocket 》构造一个asocket s关联上5037的fd,把asocket s插入local_socket_list,这个asocket s负责与client通信 》fdevent_install(&s->fde, fd, local_socket_event_func, s),回调处理函数是local_socket_event_func》将fde添加进入fd_table,在select函数后就等待回调函数的触发(也就是由local_socket_event_func来读取“host:version" 和“host:devices”请求)》connect_to_smartsocket又会创建一个asocket ss(smart socket),与之前的那个asocket s相互关联,将peer都指向对方 》 fdevent_add(&s->fde, FDE_READ) 让之前的的那个ascoket s的fd 5037进入read_fds,开始等待5037端口有可读数据 》client的数据“host:version" 和“host:devices”请求写入5037,触发local_socket_event_func 》跳过FDE_WRITE处理部分,进入到FDE_READ的处理,创建一个apacket来接收数据 》 r = s->peer->enqueue(s->peer, p),s就是第一个asocket,所以s->peer->enqueue实际是ss->enqueue函数,就是smart_socket_enqueue(ss,请求数据)》smart_socket_enqueue开始解析client的数据“host:version" 和“host:devices”(实际是调用两次),对于server能立即处理的请求(“host:version" 和“host:devices”都是) handle_host_request(service, ttype, serial, s->peer->fd, s)就直接处理 》比如"host:version",就将ADB_SERVER_VERSION按照协议格式化后,写入s->peer->fd(ss->fd) 》“host:version”的话,先调用list_transports(buffer, sizeof(buffer))取出transport_list中的相关数据,然后按照协议格式化后,写入写入s->peer->fd(这里的s实际上就是ss这个asocket,所以s->peer->fd 就是5037 ) 》这样就完成"host:version"和"host:devices"请求了;
对于更为复杂的请求,server进程会向设备(adbd)通信后实现:
smart_socket_enqueue 》 create_host_service_socket 》host_service_to_socket创建另外一个service socket作为local service的对段,而smart socket就没什么事了,可以关闭了;

 

转载地址:http://gtlli.baihongyu.com/

你可能感兴趣的文章
Launch Sublime Text 3 from the command line
查看>>
【数据库之mysql】mysql的安装(一)
查看>>
【数据库之mysql】 mysql 入门教程(二)
查看>>
【HTML5/CSS/JS】A list of Font Awesome icons and their CSS content values(一)
查看>>
【HTML5/CSS/JS】<br>与<p>标签区别(二)
查看>>
【HTML5/CSS/JS】开发跨平台应用工具的选择(三)
查看>>
【心灵鸡汤】Give it five minutes不要让一个好主意随风而去
查看>>
【React Native】Invariant Violation: Application AwesomeProject has not been registered
查看>>
【ReactNative】真机上无法调试 could not connect to development server
查看>>
【XCode 4.6】常用快捷键 特别是格式化代码ctrl+i
查看>>
【iOS游戏开发】icon那点事 之 实际应用(二)
查看>>
【iOS游戏开发】icon那点事 之 图标设计(三)
查看>>
【IOS游戏开发】之测试发布(Distribution)
查看>>
【IOS游戏开发】之IPA破解原理
查看>>
【一天一道LeetCode】#45. Jump Game II
查看>>
【一天一道LeetCode】#46. Permutations
查看>>
【一天一道LeetCode】#47. Permutations II
查看>>
【一天一道LeetCode】#48. Rotate Image
查看>>
【一天一道LeetCode】#56. Merge Intervals
查看>>
【一天一道LeetCode】#57. Insert Interval
查看>>