http://blog.csdn.net/xiaojsj111/article/details/18599653
android adb 概述
android adb的代码分为两部分:
kernel层的代码在如下路径:
drivers/usb/gadget/f_adb.c
drivers/usb/gadget/android.c
他吐给上层应用的是如下的设备节点:/dev/android_adb
应用层的代码在如下路径:
system/core/adb目录
针对device,该目录编译的输出是adbd
控制台上手动启动平板adb的功能的方法如下:
step1:在init.rc中申明adbd服务
step2:init.rc中通过属性变量来触发usb adb功能
step3: init.rc中disable adb
step4:在控制台上执行命令setprop sys.usb.config adb 将使能adb功能
在控制台上执行命令setprop sys.usb.confignone 将关闭adb功能
以上默认是通过usb来实现adb的功能,其实也可以通过网络来实现adb的功能;
方法如下:
device端:
step1: setprop service.adb.tcp.port 5555
step2: setprop sys.usb.confignone
setprop sys.usb.config adb
step3: 通过执行netstat -tna命令确认5555端口被监听。#以上操作如下图
pc端:
step1: adb kill-server
step2: adb connect 10.1.32.4 #这里的地址就是平板的地址
step3: adb devices
step3: adb shell #以上操作如下图
adb 出问题时的调试方法:
方法一:通过bus hound工具来抓pc跟device之间的usb 包的通讯。前提是需要对usb adb的命令包格式很熟悉。
方法二: 由属性变量:persist.adb.trace_mask来控制adb的log输出级别。其输出的log信息将被重定向到/data/adb/目录下的文件中。
具体源代码,请查看:/system/core/adb/adb.c(start_device_log函数), system/core/adb/adb.h(adb_trace_mask,AdbTrace)
方法三:由于方法二有一定的局限性,他是将printf的输出重定向到/data/adb/xxxx.txt文件中,这样很多的后台服务的打印信息是打印不出来的。
因为他的输入,输出被重定向到pty/pts或是pipe或是socket pair上了。
所以我们的方法就是修改/system/core/adb/adb.h文件中的# define D(...) 宏,使其的打印输出到logcat中。方法如下:
上面的__android_log_print函数需要依赖头文件#include <android/log.h>和动态库:liblog ,动态库的链接方法:
LOCAL_STATIC_LIBRARIES += liblog #交叉编译时使用
LOCAL_LDLIBS += -llog #编译主机端的adb时使用
为了查看更多地log,可以将persist.adb.trace_mask设置为0x3ff。
一下将从几个专题来研究devices端的adbd后台的工作内容:
专题一:#######adb 从pc端发送命令到device端的流程:#############
output_thread(system/core/adb/transport.c)
get_apacket(分配一个apacket包所需的内存)
t->read_from_remote(p, t)
write_packet(t->fd, t->serial, &p) //注意该函数,真正只是发送包的开始地址,并不是发送整个包的内容数据
|
|t->fd对应的pipe另一端为: t->transport_socket ,而该句柄的接收处理函数为: transport_socket_events
|\|/
transport_socket_events
read_packet(fd, t->serial, &p)) //fd即为t->transport_socket
handle_packet(p, (atransport *) _t); //该函数根据从pc端发送过来的命令,做相应的处理的。
注意:
read_from_remote/write_to_remote 对应从/dev/android_adb读取和写入数据
专题二:###############adb 从device端发送响应到pc端的流程:#########
send_packet(apacket *p, atransport *t)//函数用来向pc端发送数据(通过usb或以太网)
write_packet(t->transport_socket, t->serial, &p)
|
|t->fd对应的pipe另一端为: t->transport_socket ,该socket对是在 transport_registration_func 函数中申明 |的。\|/
input_thread
read_packet(t->fd, t->serial, &p)
t->write_to_remote(p, t);
|
|
|对应于usb而言
\|/
remote_write //发送命令和数据到pc端
usb_write(t->usb, &p->msg, sizeof(amessage)) // 发送命令
usb_write(t->usb, &p->data, size) //发送数据
专题三:pc跟device之间传输adb数据包的格式
他们之间的数据传输单元称为:struct apacket,具体结构如下:
一个 apacket 包传输分为两个阶段:
第一个阶段是:命令传输阶段(required),存储在 apacket.msg 中
第二个阶段是:数据传输阶段(optional),存储在 apacket.data 中
adb支持的命令如下:
主题四:device端对收到的pc端来的命令或数据的处理函数:handle_packet
上面函数中的remote_socket_enqueue函数,用于向pc端发送命令和数据
上面函数create_local_service_socket的实现如下:
local_socket_event_func函数展开如下:该函数是handle_packet与对应的后台服务之间的一个中转函数, 他的任务包括:
上面函数create_local_service_socket的实现如下:
local_socket_event_func函数展开如下:该函数是handle_packet与对应的后台服务之间的一个中转函数, 他的任务包括:
任务一:将pc端发送过来的命令和数据报(统称为adb package)通过local_socket_enqueue函数放置在structapacket的next队列上,并触发如下函数的 FDE_WRITE 分支的处理,该分支将从 apacket队列上取package,并将它写到管道另一端的后台服务上,作为后台服务的输入。
任务二:在要读出后台服务的输出结果时,通过调用函数local_socket_ready来触发如下函数的FDE_READ分支,该分支将通过管道,读取后台服务的输出数据, 并调用 s->peer->enqueue(即remote_socket_enqueue函数)将后台服务的输出发送到远端,即pc端上。
注意:
system/core/adb/services.c对应各种命令的后台服务
system/core/adb/commandline.c包含各种后台服务的具体实现。
主题五:usb adb的bus hound分析
情景1:adb的链接过程
2.1.0
3.1.0
4.1.0
5.1.0
以上是通用的枚举过程,即取得描述符的内容。
6.1.0 set_config
7.1.0 取得描述符
至此完成设备的枚举,开始adb的连接过程。
8.1.0 发送adb命令:A_CNXN 为out传输
9.1.0 发送adb命令A_CNXN所带的数据 为out传输
10.1.0 由device端发送adb命令A_CNXN到host pc段。IN传输
11.1.0 为adb命令A_CNXN所带的数据,IN传输
12.1.0为adb命令A_OPEN
13.1.0为adb命令A_OPEN所带的数据
14.1.0为以上命令的响应:A_OKAY
15.1.0为adb命令A_WRTE
16.1.0为adb命令A_WRTE所带的数据
17.1.0为以上命令的响应
21.1.0位adb命令A_CLSE,没有数据阶段 IN传输
22.1.0为adb命令A_CLSE,没有数据阶段,关闭时双向的。OUT传输
以上即为adb连接过程的usb封包的分析
以上是通用的枚举过程,即取得描述符的内容。
6.1.0 set_config
7.1.0 取得描述符
至此完成设备的枚举,开始adb的连接过程。
8.1.0 发送adb命令:A_CNXN 为out传输
9.1.0 发送adb命令A_CNXN所带的数据 为out传输
10.1.0 由device端发送adb命令A_CNXN到host pc段。IN传输
11.1.0 为adb命令A_CNXN所带的数据,IN传输
12.1.0为adb命令A_OPEN
13.1.0为adb命令A_OPEN所带的数据
14.1.0为以上命令的响应:A_OKAY
15.1.0为adb命令A_WRTE
16.1.0为adb命令A_WRTE所带的数据
17.1.0为以上命令的响应
21.1.0位adb命令A_CLSE,没有数据阶段 IN传输
22.1.0为adb命令A_CLSE,没有数据阶段,关闭时双向的。OUT传输
以上即为adb连接过程的usb封包的分析
情景2:adb logcat过程
1.1.0对应adb命令A_OPEN
2.1.0对应adb命令A_OPEN所带的数据,这个数据中有如下命令:exec logcat
3.1.0为以上命令的响应,IN传输
4.1.0对应adb命令A_WRTE
5.1.0对应adb命令A_WRTE的数据 IN传输,打开设备节点/dev/log/main
6.1.0为以上命令的响应 OUT传输
7.1.0对应adb命令A_WRTE
8.1.0对应adb命令A_WRTE的数据,即为logcat的输出内容 IN传输
10.1.0为以上命令的响应,OUT传输
再往下,即为上面命令的重复,以不断输出logcat的log信息
情景3:adb pull过程
1.1.0对应adb命令A_OPEN
2.1.0对应adb命令A_OPEN所带的数据,这个数据中有如下命令:sync,
该sync命令在service_to_fd函数中,被file_sync_service函数所处理
3.1.0为以上命令的响应,IN传输
4.1.0对应adb命令A_WRTE
5.1.0对应adb命令A_WRTE的数据 IN传输,数据内容为:STAT,pc用该命令来查询该文件是否存在,已经是有权限
6.1.0为以上命令的响应 OUT传输
13.1.0 对应adb命令A_WRTE OUT传输
14.1.0 对应adb命令A_WRTE的数据,该数据包含一个命令:RECV,表示pc从device段接收文件
15.1.0 为以上命令的响应
16.1.0 对应adb命令A_WRTE OUT传输
17.1.0 对应adb命令A_WRTE的数据,表示要pull的是哪个文件
18.1.0 为以上命令的响应
19.1.0 对应adb命令A_WRTE IN传输
20.1.0 对应adb命令A_WRTE的数据:DATA,表示开始数据传输,并且指定下一个命令需要传输的数据大小
21.1.0 为以上命令的响应
22.1.0 对应adb命令A_WRTE IN传输
23.1.0 对应adb命令A_WRTE的数据: 包含文件的具体内容,长度就是上面命令指定的长度
24.1.0 为以上命令的响应
重复19到24这个过程,直到文件被传输完成。
2.1.0对应adb命令A_OPEN所带的数据,这个数据中有如下命令:sync,
该sync命令在service_to_fd函数中,被file_sync_service函数所处理
3.1.0为以上命令的响应,IN传输
4.1.0对应adb命令A_WRTE
5.1.0对应adb命令A_WRTE的数据 IN传输,数据内容为:STAT,pc用该命令来查询该文件是否存在,已经是有权限
6.1.0为以上命令的响应 OUT传输
13.1.0 对应adb命令A_WRTE OUT传输
14.1.0 对应adb命令A_WRTE的数据,该数据包含一个命令:RECV,表示pc从device段接收文件
15.1.0 为以上命令的响应
16.1.0 对应adb命令A_WRTE OUT传输
17.1.0 对应adb命令A_WRTE的数据,表示要pull的是哪个文件
18.1.0 为以上命令的响应
19.1.0 对应adb命令A_WRTE IN传输
20.1.0 对应adb命令A_WRTE的数据:DATA,表示开始数据传输,并且指定下一个命令需要传输的数据大小
21.1.0 为以上命令的响应
22.1.0 对应adb命令A_WRTE IN传输
23.1.0 对应adb命令A_WRTE的数据: 包含文件的具体内容,长度就是上面命令指定的长度
24.1.0 为以上命令的响应
重复19到24这个过程,直到文件被传输完成。
情景4:adb push过程
2.1.0对应adb命令A_OPEN所带的数据,这个数据中有如下命令:shell:
3.1.0为以上命令的响应,IN传输
4.1.0对应adb命令A_WRTE IN传输
5.1.0对应adb命令A_WRTE的数据 ,数据内容为:#,即为显示在pc上的cmd窗口上的#号。
6.1.0为以上命令的响应 OUT传输
3.1.0为以上命令的响应,IN传输
4.1.0对应adb命令A_WRTE IN传输
5.1.0对应adb命令A_WRTE的数据 ,数据内容为:#,即为显示在pc上的cmd窗口上的#号。
6.1.0为以上命令的响应 OUT传输