本文转载自:http://blog.csdn.net/happylifer/article/details/7682563

最近因为需要,看了下adb的源代码,感觉这个作者很牛,设计的很好,于是稍微做了点笔记,方便以后再次需要修改adb时能迅速的回忆起来。

ADB结构及代码分析

一、概述

Android的整个ADB由3个部分组成,ADB Client、ADB Server、ADB Daemon(ADBD)。其中ADB Server是作为一个后台服务在运行的,当输入ADB指令时(比如adb devices),实际上就是在运行一个adb client,adb client会去连接adb server(127.0.0.1:5037),加入连不上,则认为ADB Server没有启动起来,会自动去fork出一个子进程,并让子进程重新执行adb  fork-server server,从而让ADB Server运行起来,而父进程则会重新尝试连接ADB Server。因此ADB Client和ADB Server其实就是同一个程序,只不过是各自用到了ADB的部分功能而已。

二、ADB Client功能概述

ADB Client的作用是连接ADB Server,并将用户输入的指令转发给ADB Server,并等待ADBD或者是ADB Server的应答。对于很多指令,ADB Client都是将指令发送至ADB Server后,就结束了,但是对于一些指令(比如adb  push  LOCAL_PATH  REMOTE_PATH), ADB Server只是充当了一个数据转发的功能,即是ADB Client和ADBD通过ADB Server这座桥梁,在不断的进行交互。后面将对adb push 这条指令做一个详细的代码分析

三、ADB Server功能概述

ADB Server是通过adb_main(int is_daemon, int server_port),即adb_main(1,5037)运行起来的。作为一个开在本机的socket服务器,ADB Server等待接收来自ADB Client的请求,并做相应的处理。

ADB Server在启动的时候,会调用函数  void init_transport_registration(void)  初始化一个socketpair,用来注册transport。以实际的usb外设为例:ADB Server会在一个线程中循环检测/dev/bus/usb下是否有新的usb设备插入,如果新插入的外设的vid,pid在预设的表中,并且存在一个接口是用于anroid调试的( 通过函数 is_adb_interface判断 ),则会利用socketpair,注册这个usb设备。所谓的注册usb设备,就是把读写这个usb设备的文件描述符fd,相关的操作函数(remote_write等)、usb设备的识别号等保存在一个atransport结构体里,同时atransport里会保存一个socketpair,将来usb设备的读写数据就都是通过socketpair来传送的。

注册完atransport后,会开启2个线程,input_thread和output_thread, 在input_thread里,会读取从socketpair发过来的数据,并写往usb设备;在output_thread里,将从usb设备读到的数据写入到socketpair的其中一个socket里,参考注册时的代码可知:

t->transport_socket = s[0];

t->fd = s[1];

D("transport: %p install %d\n", t, t->transport_socket );

fdevent_install(&(t->transport_fde),

t->transport_socket,

transport_socket_events,

t);

fdevent_set(&(t->transport_fde), FDE_READ);

从usb读取到的数据将在transport_socket_events中进行接收并处理。

数据从ADB Server发往usb外设的流程

ADB Server  ---->  write_packet(t->transport_socket, &p)  ---->  input_thread里的

read_packet(t->fd, &p)  ---->  input_thread里的t->write_to_remote(p, t)  ----> usb设备

数据从usb外设到ADB Server的流程

Usb设备---->  t->read_from_remote(p, t)  ---->  write_packet(t->fd, &p) (即会从

t->transport_fde读到数据)  ----> 在transport_socket_events中处理usb设备发送过来的

数据帧

四、ADBD功能概述

程序初始化,会开启一个线程,循环的处理usb设备的打开操作,以保证usb设备始终是打开的。Usb设备打开后,会采用与ADB Server相同的处理机制,注册一个atransport进行usb数据的传输与转发。(本来就是出自同一份代码)

里面的init_jdwp搞不是很懂,就知道是开启了一个服务端,等待上层的应用连接,除了保存一个ID外,没有看到具体的功用。

五、实例分析

以adb  push  local-file  remote-file为例,3个程序的交互如下:

ADB Client

ADB Server

ADBD

步骤计数

发送adb_connect("sync:")

   

1

 

1、收到"sync:",知道要与设备进行数据传输了

2、将adb server与adb client连接的asocket里保存的peer清空。等收到usb外设应答时,会生成一个连接到usb外设的peer

3、向usb设备发送数据帧:command=A_OPEN ,data="sync:"

4、取消与adb client连接的fd的FD_READ,暂停从adb client接收数据

5、由于取消了FD_READ,Adb client发过来的ID_STAT指令暂时未被adb server从缓冲区读出来

 

2

   

1、收到A_OPEN,开启一个线程用于接收数据,由于adb server此时暂停从adb client接收数据,因此线程阻塞在read操作上

2、主线程创建一个asocket,并在asocket->peer中保存了usb外设与adb server的通信方法

3、Send_ready(local_id,remote_id),向adb server发送A_OKAY应答,回应刚才的A_OPEN请求,并且数据帧中的arg0=local_id, arg1=remote_id

(注:每一个id都是一个asocket的表示,通过id可以从asocket链表中找到相应的asocket地址)

3

 

1、收到adbd返回的A_OKAY

2、根据arg1,得到asocket的id,并找到相应的asocket,此asocket保存着adb server与adb client通信的socket

3、发现此asocket的peer是空的,重新生成一个可与usb外设通信的asocket(参见第二步的第二点)

4、调用asocket中的ready函数,设置FD_READ标志,adb server可以继续从adb client接收数据

 

4

发送ID_STAT请求,远程文件的完整路径将被发往adbd

   

5

 

将ID_STAT打包成A_WRTE消息,发往adbd

 

6

   

1、收到A_WRTE消息,数据通过函数local_socket_enque处理,即数据发往socketpair中的另一端。

2、socketpair是收到"sync:"请求时生成的。因此数据最终将被接收文件数据的线程读取到

3、解析ID_STAT数据包,并对传送过来的文件的完整路径进行分析,返回分析结果。返回的数据是包含在A_WRTE数据包里的

7

 

1、收到A_WRTE数据包

2、通过arg0参数,找到对应的asocket,并将adbd的应答通过asocket发给adb client

 

8

1、读取到ID_STAT,解析adbd返回的远程文件的mode,并形成完整的远程文件路径,即adb push A B中的B

2、调用sunc_send开始发送数据

3、发送ID_SEND数据包,将远程文件路径B,文件属性发送给adbd

   

9

 

收到adb client的数据包,封装成一个A_WRTE数据包,发往adbd

 

10

   

1、收到A_WRTE,根据arg1,找到asocket,并调用local_socket_enqueue将数据写入到socketpair

2、函数file_sync_service读取到数据,并对数据做处理

11

循环发送ID_DATA数据包

   

12

 

收到ID_DATA包,调用remote_socket_enque封装成A_WRTE包,发往adbd

 

13

   

1、收到A_WRTE包,将数据写入socketpair,发到数据接收线程

2、返回A_OKAY应答

14

收到A_OKAY后,继续发送ID_DATA

   

15

 

。。。。。。

 

16

   

。。。。。。

17

发送完毕后,发送ID_DONE

   

18

 

转发ID_DONE

 

19

   

返回ID_OKAY

20

结束任务,断开与adb server的socket连接

     
 

1、断开与adb client的连接

2、等待adb client的再次连接

   

ADB结构及代码分析【转】的更多相关文章

  1. android adb 流程原理代码分析(一)

    由于要用到adb的知识,但是对adb啥也不了解,看了下android的代码,adb的源码在system/core/adb下面,然后网上搜下了资料,发现很多大神的源码分析,瞬间信心爆棚,把大神写的博客都 ...

  2. Uboot优美代码赏析1:目录结构和malkefile分析

    Uboot优美代码赏析1:目录结构和malkefile分析 关于Uboot自己选的版本是目前最新的2011.06,官方网址为:http://www.denx.de/wiki/U-Boot/WebHom ...

  3. [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(5)(IEnumerable<>补充)

    Asp.net 5的依赖注入注入系列可以参考链接: [Asp.net 5] DependencyInjection项目代码分析-目录 我们在之前讲微软的实现时,对于OpenIEnumerableSer ...

  4. 常用 Java 静态代码分析工具的分析与比较

    常用 Java 静态代码分析工具的分析与比较 简介: 本文首先介绍了静态代码分析的基 本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBu ...

  5. [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(3)

    这个系列已经写了5篇,链接地址如下: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Auto ...

  6. EF自动生成的模型edmx代码分析

    edmx代码分析 本文分析Entity Framework从数据库自动生成的模型文件代码(扩展名为edmx). 1. 概述 本文使用的数据库结构尽量简单,只有2个表,一个用户表和一个分公司表(相当于部 ...

  7. wifi display代码 分析

    转自:http://blog.csdn.net/lilian0118/article/details/23168531 这一章中我们来看Wifi Display连接过程的建立,包含P2P的部分和RTS ...

  8. JQuery data API实现代码分析

    JQuery data 接口是什么? .data() Store arbitrary data associated with the matched elements or return the v ...

  9. lighttpd与fastcgi+cgilua原理、代码分析与安装

    原理 http://www.cnblogs.com/skynet/p/4173450.html 快速通用网关接口(Fast Common Gateway Interface/FastCGI)是通用网关 ...

随机推荐

  1. __getattr__ 与 __getattribute__的区别

    原文博客地址 http://www.cnblogs.com/bettermanlu/archive/2011/06/22/2087642.html

  2. MySql将查询结果插入到另外一张表

    今天遇到一个业务需求是这样的:对在职员工超过55岁提醒.我想的思路是查询员工表,然后将超过55岁的人的信息存到另一个表,并且以消息的形式给用户提示,用户处理掉之后此消息失效(在数据库做标记). 不管是 ...

  3. thinkphp框架做项目的前期配置

    ThinkPHP 目录结构说明 ThinkPHP.php:框架的公共入口文件 App:项目放置目录 Common:包含框架的一些公共文件.系统定义.系统函数和惯例配置等 Lang:系统语言文件目录 L ...

  4. 测试开发系列之Python开发mock接口(二)

    上一篇咱们已经把开发前的环境准备好了,还需要再做一点准备,你的账户信息是存在哪的呢,当然是存在数据库里的,咱们在去支付,扣钱的时候,肯定是从数据库里面操作的,去更新账户表里面的数据,所以咱们先要把数据 ...

  5. asp.net core系列 65 正反案例介绍SOLID原则

    一.概述 SOLID五大原则使我们能够管理解决大多数软件设计问题.由Robert C. Martin在20世纪90年代编写了这些原则.这些原则为我们提供了从紧耦合的代码和少量封装转变为适当松耦合和封装 ...

  6. 第1章 SpringBoot 简介

    一.什么是Spring Boot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发 ...

  7. Qt5官方demo解析集30——Extending QML - Binding Example

    本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集29--Extendin ...

  8. CNN网络--AlexNet

    ImageNet Classification with Deep Convolutional Neural Networks 从AlexNet剖析-卷积网络CNN的一般结构 AlexNet是Hint ...

  9. iOS --- 总结Objective-C中经常使用的宏定义(持续更新中)

    将iOS开发中经常使用的宏定义整理例如以下,仅包括Objective-C. 而对于Swift,不能使用宏,则能够定义全局函数或者extension.请參考博客iOS - 总结Swift中经常使用的全局 ...

  10. Solidworks 不能生成实体,因为这将导致厚度为零的零件怎么办

    如下图所示,我认为我长出一块东西根本不会对其他零件有什么影响.   去掉合并结果之后就好了.   钣金要比方钢高出1mm,这样焊接上去才方便.