上篇回归博客里已经说到,完成周更计划,可是上一周周末我就水了,十分抱歉,临近毕业事物繁杂,这里补上一篇adb相关知识。
adb是什么?:adb的全称为Android Debug Bridge,就是起到调试桥的作用。
通过adb我们可以在Eclipse中方面通过DDMS来调试Android程序,说白了就是debug工具。
adb的工作方式比较特殊,采用监听Socket TCP 5554等端口的方式让IDE和Qemu通讯,默认情况下adb会daemon相关的网络端口,所以当我们运行Eclipse时adb进程就会自动运行。
adb有什么用?:借助adb工具,我们可以管理设备或手机模拟器的状态。还可以进行很多手机操作,如安装软件、系统升级、运行shell命令等等。其实简而言说,adb就是连接Android手机与PC端的桥梁,可以让用户在电脑上对手机进行全面的操作
下面以几张图来进行分析:
该图表示,ADB的CS模型
该图表示,ADB内部实现流程机制
1:PC端adb server发送cmd到小机端
2:adbd(adb daemon)的output thread从/dev/android_usb读取到cmd并解析
(adbd和内核usb driver通过/dev/android_usb进行数据交互)
3:output_thread将解析的cmd写到socketpair的A端
4:fdevent_loop通过select socketpair的B端,得知A端有数据写入,B端可读,然后读取cmd,
进行处理(handle_packet)
5:处理完后将结果写到socketpair的B端
6:Input_thread阻塞式读取socketpair的A端
7:Input_thread读取到数据后,写入/dev/android_usb
8:由usb driver将response发给pc端
output_thread负责读取/dev/android_usb,Input_thread负责写入
来看看整体流程
源码路径:~/system/core/adb/adb.c
adb_main
==>init_transport_registration 注册transport登记接口,回调函数transport_registration_func
等待register_transport发送数据过来.
==>local_init 对于pc上的host程序,执行client_socket_thread线程==>local_connect
优先扫描fd = socket_loopback_client(port, SOCK_STREAM);
本地port是否能打开,如果不能打开,那么尝试获取const char *host = getenv("ADBHOST");
环境变量,而我们恰恰定义了该环境变量export ADBHOST=192.168.100.2,
所以尝试打开手机端server监听的相应端口[我们定义的是#define ADB_LOCAL_TRANSPORT_PORT 5555,
这由运行在手机上的server_socket_thread线程创建],
fd = socket_network_client(host, port, SOCK_STREAM);打开成功后
调用register_socket_transport==>register_transport将该transport交由
上面的transport_registration_func函数继续处理,transport_registration_func函数将
该transport挂接到transport_list链表上,然后创建一对socketpair[这样就可以对其中
一个fd实行双向读写操作了,pipe只能单向操作,一个fd只读,另一个只写],
一端给t->transport_socket = s[0];另一端给t->fd = s[1];之后将t->transport_socket
添加到FDE_READ读epoll中,t->fd发过来的数据由transport_socket_events回调函数
调用handle_packet函数做进一步处理,之后创建2个线程input_thread和output_thread,
input_thread通过read_packet(t->fd, &p);接收host通过t->transport_socket发送的数据,
然后执行t->write_to_remote(p, t);将数据转发给手机上的server[192.168.100.2:5555]
output_thread通过t->read_from_remote(p, t);接收手机server[192.168.100.2:5555]
发送过来的数据,然后执行write_packet(t->fd, &p);转发给正在监听t->transport_socket
端口的回调函数transport_socket_events==>handle_packet,这样在该transport上进行数据
收发所需要的环境都已经建立完毕了[luther.gliethttp]
==>install_listener("tcp:5037", "*smartsocket*", NULL);
这是运行在pc上的host程序所创建的一个监听端口5037[#define ADB_PORT 5037],
他将监听所有adb shell等本地命令数据[姑且把pc上执行adb shell等命令的操作为client端],
如果该本地命令host可以执行,那么直接返回结果给client端,
否则通过transport端口将该命令数据转发到手机上,由手机上的server进行处理[luther.gliethttp]
具体由l->fd = local_name_to_fd(local_name);语句
执行socket_loopback_server(port, SOCK_STREAM);创建[luther.gliethttp]
5037端口监听到的数据交由ss_listener_event_func回调函数做进一步处理,
如果是非"*smartsocket*"的listener那么执行listener_event_func回调函数[luther.gliethttp]
ss_listener_event_func==>
fd = adb_socket_accept(_fd, &addr, &alen);
s = create_local_socket(fd);设置该adb shell命令在host上连接处理函数local_socket_event_func
connect_to_smartsocket(s);
void connect_to_smartsocket(asocket *s)
{
D("Connecting to smart socket \n");
asocket *ss = create_smart_socket(smart_socket_action);
//将本地client命令,比如adb shell的peer设置为smartsocket
s->peer = ss;
ss->peer = s;
s->ready(s); // 调用local_socket_ready==>fdevent_add(&s->fde, FDE_READ);
// 这样host将等待本地client命令发送数据过来,
// 然后执行local_socket_event_func==>s->peer->enqueue(s->peer, p);
// 即上面create_smart_socket创建的smartsocket==>smart_socket_enqueue
// 处理来自client命令的数据[比如:adb shell命令发送过来的数据]
}
==>对于host来说fprintf(stderr, "OK\n");// 将OK传递给执行adb start-server的parent程序,因为parent正执
// 行adb_read(fd[0], temp, 3);等待管道数据[luther.gleithttp]
==>start_logging(); // 打开log文件,然后dup2到stdout和stderr,
==>fdevent_loop==>fdevent_process // 进入event loop循环等待所有
static void fdevent_process()
{
struct epoll_event events[256];
fdevent *fde;
int