Adb源代码学习笔记

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注册系统时,创建一对sockpairtransport_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 threadinput thread用于做异步IO。根据adb的文档说明,output线程和input线程的引人主要是为了解决USB endpoint不支持非阻塞读写,所以就专门为usb读操作开一个output线程,为usb写操作创建一个input线程。所以,数据流方向是远程连接->output线程->主线程->input线程->远程连接。刚开始时,output线程会发一个SYNC消息给input线程,启动这个transport

usb_vendors_init函数

初始化usb vendor的信息,有一些是内置的ID号,如Google HTCSAMSUNG等厂家的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要开始启用adbUSB调试功能了。一旦kernel成功启用了adbusb功能,就会一个新的线程usb_open_thread每隔1000ms扫描一次,判断adb是否就绪了。在Android中,当device通过usb线连接到host端,kernel就会加载相应的usb驱动(???)并创建设备文件/dev/android_adb,反复读取这个文件就可以判断device是否连接到pc端了。如果返回的fd大于0,那么说明已经连接好了,这个时候调用register_usb_transportusbtransport注册到adb系统中,等候在transport_registration_recv的异步IO事件发生了。如上所述,init_registration_func中的output线程会首先发送A_SYNC消息启动devicehost的握手协商过程。整个adb系统将会按照既定的协议运作起来。host端也是这样一个过程。此时,host端会首先调用send_connectdevice端发送A_CNNX消息告诉自己能够接受多大的payloaddevice收到这个消息后,也会调用send_connecthost端发送A_CNNX消息告诉自己能够接受多大的payload,,一来一回,完成了传输的握手协议了。

host端的usb_init

支持FreeBSDMAC OSXWindows平台。大致流程与device端的相仿,都创建一个专门扫描usb端口的线程判断是否有device连接,如果有,就调用register_usb_transport函数启动整个adb系统。linux是通过libusb来读取usb endpoint中的信息,windows平台上是通过Android系统提供的API来读取的。


你可能感兴趣的:(Adb源代码学习笔记)