2010年写的,可能与最新的adb源码有些出入,敬请读者注意不一致之处!
Adb对传输层的抽象
adb对实际的设备和模拟器分别使用了两种不同的数据传输协议:
USB for device
与实际的设备通讯是基于USB数据传输方式,device端在启动时加载了一个USB设备驱动模块(which driver?),创建了与之对应的设备文件/dev/android_adb,对这个设备文件的读操作就是从USB的endpoint中读取数据,写操作则是将数据写到USB的endpoint上。PC端的adb server则是基于libusb实现USB的endpoint的读写操作。
当device启动adb daemon,会初始化usb的传输模块。而PC端启动adb server时,会创建一个线程专门负责扫描usb端口是否有device连接。
TCP for emulator
和模拟器的通讯是基于网络套接字的方式通讯的,adb daemon会监听5555端口,adb server则会尝试连接这个端口并请求服务。
adb定义了两个数据类型对传输方式做了一层抽象:strcut asocket 和struct atransport.struct asocket
一个远程连接实际上是由两个连接点组成,那么一个asocket对象表示一个远程连接中一个连接点,它包含了对端连接点的信息和一组可供对端调用的方法。当对端有数据需要发送过来时,asocket对象提供enqueue方法对接受到的数据包进行处理。
struct atransport
提供了一组IO操作方法。
init_transport_registration函数
在初始化transport注册系统时,创建一对sockpair(transport_registration_send, transport_registration_recv)用于异步处理注册事件,并在transport_registration_recv上安装一个异步事件回调函数transport_registration_func.当向adb系统中注册/删除一个transport时,会调用transport_write_action将一个tmsg写入到transport_registration_send端,那么transport_registration_recv端上的回调函数transport_registration_func就会被触发。
transport_registration_func的主要工作是异步处理transport的注册和删除操作:
删除一个transport:删除与该transport相关的异步IO,更新adb系统中transport列表,运行disconnect操作,最后释放memory。如果是host端,还要更新device tracker???注册一个新的transport: 为这个新的transport对象创建一对socketpair用来做线程间通信,安装异步IO事件,然后创建output thread和input thread用于做异步IO。根据adb的文档说明,output线程和input线程的引人主要是为了解决USB endpoint不支持非阻塞读写,所以就专门为usb读操作开一个output线程,为usb写操作创建一个input线程。所以,数据流方向是远程连接->output线程->主线程->input线程->远程连接。刚开始时,output线程会发一个SYNC消息给input线程,启动这个transport。
usb_vendors_init函数
初始化usb vendor的信息,有一些是内置的ID号,如Google, HTC,SAMSUNG等厂家的ID,其他的可以从$HOME/.android/adb_usb.ini文件中读取。
usb_init函数
PC host端和android device端有不同的实现:
device端(usb_linux_client.c)
usb_init首先试着以RDWR的方式打开/dev/android_adb_enable设备文件告诉kernel要开始启用adb的USB调试功能了。一旦kernel成功启用了adb的usb功能,就会一个新的线程usb_open_thread每隔1000ms扫描一次,判断adb是否就绪了。在Android中,当device通过usb线连接到host端,kernel就会加载相应的usb驱动(???)并创建设备文件/dev/android_adb,反复读取这个文件就可以判断device是否连接到pc端了。如果返回的fd大于0,那么说明已经连接好了,这个时候调用register_usb_transport将usbtransport注册到adb系统中,等候在transport_registration_recv的异步IO事件发生了。如上所述,init_registration_func中的output线程会首先发送A_SYNC消息启动device和host的握手协商过程。整个adb系统将会按照既定的协议运作起来。host端也是这样一个过程。此时,host端会首先调用send_connect给device端发送A_CNNX消息告诉自己能够接受多大的payload,device收到这个消息后,也会调用send_connect给host端发送A_CNNX消息告诉自己能够接受多大的payload,,一来一回,完成了传输的握手协议了。