由于要用到adb的知识,但是对adb啥也不了解,看了下android的代码,adb的源码在system/core/adb下面,然后网上搜下了资料,发现很多大神的源码分析,瞬间信心爆棚,把大神写的博客都浏览了一遍,然后手动运行了下adb命令,顺便跟踪了下过程,发现原来还是很好的理解,源码的各种线程创建,函数回调,对于我这种基础不咋好的,,还是看的晕晕呼呼,现在把我自己的理解给大家分享,有理解错误的还请多多指正。
一般直接上代码,可能看官都走了一大半,我们逆向的看,先看结果,再看过程,最后再看代码。从简单的入手。
理解:
(1)adb的本质,就是socket的通信,通过secket传送数据及文件
(2)adb传送是以每个固定格式的包发送的数据,包的格式如下:
#define A_SYNC 0x434e5953
#define A_CNXN 0x4e584e43
#define A_OPEN 0x4e45504f
#define A_OKAY 0x59414b4f
#define A_CLSE 0x45534c43
#define A_WRTE 0x45545257
#define A_AUTH 0x48545541
struct amessage {
unsigned command; /* command identifier constant */
unsigned arg0; /* first argument */
unsigned arg1; /* second argument */
unsigned data_length; /* length of payload (0 is allowed) */
unsigned data_check; /* checksum of data payload */
unsigned magic; /* command ^ 0xffffffff */
};
struct apacket
{
apacket *next;
unsigned len;
unsigned char *ptr;
amessage msg;
unsigned char data[MAX_PAYLOAD];
};
发送的包格式为apacket格式,其中msg为消息部分,data为数据部分。msg的消息类型有很多种,包括A_SYNC, A_CNXN, A_OPEN, A_OKAY等等。
到此,我们对adb的理解就是,一种socket通信,每次发送apacket格式的数据包,好吧,我们在这样的认知下继续学习adb。
(3)adb给我们预留了调试的信息,我们只需要在adb.h中定义指定的宏,即可看到每次数据的传输过程:
#define DEBUG_PACKETS 1
(4)我们使用adb push命令,来跟踪分析下这个apacket数据是怎样传输的:
我们以adb push profile /命令为例,在串口我们可以看见如下详细的传输信息:
status command arg0 arg1 len data
recv: OPEN 00141028 00000000 0006 "sync:."
send: OKAY 0000003e 00141028 0000 ""
recv: WRTE 00141028 0000003e 0009 "STAT..../"
send: OKAY 0000003e 00141028 0000 ""
send: WRTE 0000003e 00141028 0010 "STAT.A......[oHZ"
recv: OKAY 00141028 0000003e 0000 ""
recv: WRTE 00141028 0000003e 0027 "SEND..../profile,33206DATA....2D
send: OKAY 0000003e 00141028 0000 ""
send: WRTE 0000003e 00141028 0008 "OKAY...."
recv: OKAY 00141028 0000003e 0000 ""
recv: WRTE 00141028 0000003e 0008 "QUIT...."
send: OKAY 0000003e 00141028 0000 ""
send: CLSE 00000000 00141028 0000 ""
recv: CLSE 00141028 0000003e 0000 ""
以上recv表示接收的数据包,send表示回传的数据包。后面五个分别为数据包的数据字段值(command arg0 arg1 len data),这样数据我们还是不够直观,我们翻译成更加直接的数据辅以文字解释
这样是不是容易理解多了呢,经过这样的数据发送,我们就通过adb push命令把本地的profile文件推送到远程设备的根目录了。哇..... 原来这么简单,一个profile文件就传输了。流程理解了,我们再来看代码,现在结果你知道了,流程你也懂了,再来看源码,是不是容易理解了呢。
(5)同样,我们看代码也是逆向的看,这样利于我们理解,不会被源码看到晕乎乎,上面流程懂了,知道了每次是以apacket的格式发送的,我们先来研究这个apacket的接收与发送函数。
接收函数handle_packet
void handle_packet(apacket *p, atransport *t)
{
asocket *s;
D(