---
title: "ADB工作原理"
author: "Perrin Yong"
author_profile: https://www.pystone.net/profile/
published_by: "Perrin Yong"
canonical: https://www.pystone.net/notes/adb-working-principles/
type: note
content_role: unspecified
visibility: public
id_stability: rename-stable
source_path: "10-计算机、信息技术与工程/04-应用开发与云端工程/Android开发/ADB工作原理.md"
content_hash: d43e9c74babc8a1a819ec454b48cb39381662054de99fd8c20fd5df51f597913
knowledge_version: 224c990773de.5fa8af6e39fa
site_commit: 224c990773de166d23a886306577dd90379529ce
notes_commit: 5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a
---
# ADB工作原理
## adb原理

ADB - Android Debug Bridge

ADB源码：

<http://androidxref.com/8.1.0_r33/xref/system/core/adb/adb.cpp>


<https://android.googlesource.com/platform/system/adb>


<https://github.com/aosp-mirror/platform_system_core.git>


### 架构

![assets/0021 - 【自动化测试】ADB原理__1621006571443.png](/media/b8cd112701af284343e4.png)


**ADB Client** : 运行在PC HOST端，用来发送adb命令。**本质上就是Shell**，用来发送命令给Server。发送命令时，首先检测PC上有没有启动Server，如果没有Server，则自动启动一个Server，然后将命令发送到Server，并不关心命令发送过去以后会怎样。


**ADB Server** :

运行在PC HOST端，用来管理Client端和手机的Deamon之间的通信。

检测USB接口何时连接或者移除设备。ADB Server维护着一个“已连接的设备的链表”，并且为每一个设备标记了一个状态：offline，bootloader，recovery或者online。Server一直在做一些循环和等待，以协调client和Server还有daemon之间的通信。


> offline说明Server发现了一个设备，但是不能成功连接到Daemon。


**Daemon（adbd守护进程）**:

运行在调试设备中（手机或者模拟器），连接到adb server（通过usb或tcp-ip）,接受并执行adb命令, 为client提供一些服务。


![assets/0021 - 【自动化测试】ADB原理__1620997882024.png](/media/0524f567931ca6432d9f.png)


### 通信机制与workflow

1. 在PC HOST端，adb会fork出一个守护进程（不是adbd），即ADB Server，而父进程（ADB Client）继续处理Client请求，所有的Client通过TCP端口号5037进行与Server通信，而Server创建 local socket 与 remote socket，前者用于和Client通信，后者用与远端进行通信，emulator通过TCP，real device则通过usb。
2. 在emulator/device端，adbd也创建 local socket 和 remote socket，前者与通过 jdwp 与Java虚拟机进程通信，后者通过 TCP/USB 与 PC HOST通信。
 - Client和Server虽然是同一个执行程序，但在命令行输入一条adb命令后，实际上完成了一次通信。adb server启动后，会在**5037**端口侦听从client发起的TCP连接
 - Server与模拟器或者手机设备的端口5555~5585建立TCP连接，PC上与之相连的端口号随机。

![assets/0021 - 【自动化测试】ADB原理__1621006667165.png](/media/4fe8d91d51316c90d25c.png)


通过以下命令，可以看到server的启动日志：


```
$ adb
kill
-
server
 && adb devices

* daemon
not
 running.
starting
 it
now

on
 port
5037
 *

* daemon started successfully *
```


通过以下命令，可以看到TCP的5037端口，在侦听连接：


```
$ netstat -l | grep
5037


Proto Recv-Q Send-Q Local Address Foreign Address State

tcp
0

0

127.0
.0
.1
:
5037

0.0
.0
.0
:* LISTEN
```


1. Client 调用某个 adb 命令
2. adb 进程 fork 出一个子进程作为 Server
3. Server 查找当前连接的 emulator/device
4. Server 接收到来自 Client 请求
5. Server 处理请求，将本地处理不了的请求发给
6. emulator/device
7. 位于 emulator/device 的 adbd拿到请求后交给对应的java虚拟机进程。
8. adbd 将结果发回给 Server
9. Server 将结果发回给 Client


### ADB Protocol 通信协议

#### Client 和 Server 间的通信

Client发送的指令分为三种


- 不需要经过Server处理就能成功的，如adb version,adb help。
- 需要和Server通讯，但不需要和Demon通讯的指令，如adb devices.
- 需要Daemon进行处理的命令。

Client 和 Server 间传输的命令定义: <http://androidxref.com/8.1.0_r33/xref/system/core/adb/SERVICES.TXT>


Client每个命令都包含两个部分:


1. 命令的长度(Length)，由四位的十六进制表示
2. 实际的命令(Payload)，通过ASCII编码


```
000
Chost:
version
```


000C：表示”host:version”这条命令的长度为12个字节；

host前缀：是为了区分其他类型的命令(后面还会看到shell前缀的命令)；


Server收到Client的请求后，返回的数据遵循如下格式：


- 如果成功，则返回四个字节的字符串”OKAY“
- 如果失败，则返回四个字节的字符串”FAIL“和出错原因
- 如果异常，则返回错误码


#### ADB Daemon 和 ADB Server 间的通信 — transport协议

这个数据通道对client而言，完全是透明的，client不关注这个通道怎么建立以及怎么进行数据传输。


关于 transport 协议的定义在 system/core/adb/protocol.txt 文件中


```
The transport layer deals in
"messages"
, which consist of a
24

byte


header
followed

(optionally)
 by a payload. The header consists of 6


32 bit words which are sent across the wire in little endian format.


struct
 message
{


unsigned
 command;
/* command identifier constant (A_CNXN, ...) */


unsigned
 arg0;
/* first argument */


unsigned
 arg1;
/* second argument */


unsigned
 data_length;
/* length of payload (0 is allowed) */


unsigned
 data_crc32;
/* crc32 of data payload */


unsigned
 magic;
/* command ^ 0xffffffff */


};
```


client与adbd的数据传输是需要用到两个通道的，当与server建立第一个通道的连接后，需要向server发送transport命令，表示接下来，要与adbd进行数据传输。当server返回“OKAY”后，client后续发送的数据，就直接传输到adbd了。


![assets/0021 - 【自动化测试】ADB原理__1621006991650.png](/media/433c64e8c67d40eb5219.png)


### USB Vendor ID

![assets/0021 - 【自动化测试】ADB原理__1621007056515.png](/media/2b9fdd0eb942de0e40bb.png)


### adb forward

设置任意端口转发，将特定主机端口上的请求转发到设备上的其他端口。PC 作为Client客户端 可以任意访问 Phone 上的 Server 服务器


```
adb
forward
 tcp:
6100
 tcp:
7100


adb
forward
 --list

adb
forward
 --
remove
-all

adb
forward
 tcp:
8888
 tcp:
8888
```


该转发可以用于自己写的程序。


## 实践用法

用法大全: <https://github.com/mzlogin/awesome-adb>


### Profiler: Editor-to-Android connection

adb forward tcp:34999 localabstract:Unity-{insert bundle identifier here}


### log抓取

adb logcat -s Unity

adb -s %DeviceName% logcat -s Unity

adb logcat -s Unity ActivityManager PackageManager dalvikvm DEBUG #获取log，-s指定过滤器

adb -s deviceName logcat -s Unity -f c:\unity_log.txt #-f 输出log到指定文件


### 其他常用命令

<https://www.huaweicloud.com/articles/39c8580fd6d8eacb6b0b89082f9d15b4.html>


## Ref

<https://www.zhihu.com/zvideo/1261234074455998464>


<https://www.jianshu.com/p/6769bfc3e2da>


<https://itimetraveler.github.io/2019/06/07/Android ADB原理探究/>


<https://learning.oreilly.com/library/view/unboxing-android-usb/9781430262084/9781430262084_Ch07.xhtml>

## 【自动化测试】ADB原理
@(10. DevOps)

[TOC]


## adb原理
ADB - Android Debug Bridge
ADB源码：
http://androidxref.com/8.1.0_r33/xref/system/core/adb/adb.cpp

https://android.googlesource.com/platform/system/adb

https://github.com/aosp-mirror/platform_system_core.git

### 架构

![ADB 工作原理示意图](/media/b8cd112701af284343e4.png)


**ADB Client** : 运行在PC HOST端，用来发送adb命令。**本质上就是Shell**，用来发送命令给Server。发送命令时，首先检测PC上有没有启动Server，如果没有Server，则自动启动一个Server，然后将命令发送到Server，并不关心命令发送过去以后会怎样。


**ADB Server** :
运行在PC HOST端，用来管理Client端和手机的Deamon之间的通信。
检测USB接口何时连接或者移除设备。ADB Server维护着一个“已连接的设备的链表”，并且为每一个设备标记了一个状态：offline，bootloader，recovery或者online。Server一直在做一些循环和等待，以协调client和Server还有daemon之间的通信。
> offline说明Server发现了一个设备，但是不能成功连接到Daemon。


**Daemon（adbd守护进程）**:
运行在调试设备中（手机或者模拟器），连接到adb server（通过usb或tcp-ip）,接受并执行adb命令, 为client提供一些服务。

![ADB 工作原理示意图](/media/0524f567931ca6432d9f.png)

### 通信机制与workflow
1. 在PC HOST端，adb会fork出一个守护进程（不是adbd），即ADB Server，而父进程（ADB Client）继续处理Client请求，所有的Client通过TCP端口号5037进行与Server通信，而Server创建 local socket 与 remote socket，前者用于和Client通信，后者用与远端进行通信，emulator通过TCP，real device则通过usb。

2. 在emulator/device端，adbd也创建 local socket 和 remote socket，前者与通过 jdwp 与Java虚拟机进程通信，后者通过 TCP/USB 与 PC HOST通信。

* Client和Server虽然是同一个执行程序，但在命令行输入一条adb命令后，实际上完成了一次通信。adb server启动后，会在**5037**端口侦听从client发起的TCP连接
* Server与模拟器或者手机设备的端口5555~5585建立TCP连接，PC上与之相连的端口号随机。

![ADB 工作原理示意图](/media/4fe8d91d51316c90d25c.png)


通过以下命令，可以看到server的启动日志：
```
$ adb kill-server && adb devices
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
```
通过以下命令，可以看到TCP的5037端口，在侦听连接：
```
$ netstat -l | grep 5037
Proto Recv-Q Send-Q    Local Address   Foreign Address     State
tcp        0      0    127.0.0.1:5037  0.0.0.0:*           LISTEN
```
1. Client 调用某个 adb 命令
2. adb 进程 fork 出一个子进程作为 Server
3. Server 查找当前连接的 emulator/device
4. Server 接收到来自 Client 请求
5. Server 处理请求，将本地处理不了的请求发给
6. emulator/device
7. 位于 emulator/device 的 adbd拿到请求后交给对应的java虚拟机进程。
8. adbd 将结果发回给 Server
9. Server 将结果发回给 Client


### ADB Protocol 通信协议
#### Client 和 Server 间的通信
Client发送的指令分为三种
* 不需要经过Server处理就能成功的，如adb version,adb help。
* 需要和Server通讯，但不需要和Demon通讯的指令，如adb devices.
* 需要Daemon进行处理的命令。

Client 和 Server 间传输的命令定义: http://androidxref.com/8.1.0_r33/xref/system/core/adb/SERVICES.TXT

Client每个命令都包含两个部分:
1. 命令的长度(Length)，由四位的十六进制表示
2. 实际的命令(Payload)，通过ASCII编码

```
000Chost:version
```
000C：表示”host:version”这条命令的长度为12个字节；
host前缀：是为了区分其他类型的命令(后面还会看到shell前缀的命令)；

Server收到Client的请求后，返回的数据遵循如下格式：
* 如果成功，则返回四个字节的字符串”OKAY“
* 如果失败，则返回四个字节的字符串”FAIL“和出错原因
* 如果异常，则返回错误码





#### ADB Daemon 和 ADB Server 间的通信 — transport协议
这个数据通道对client而言，完全是透明的，client不关注这个通道怎么建立以及怎么进行数据传输。


关于 transport 协议的定义在 system/core/adb/protocol.txt 文件中
```cpp
The transport layer deals in "messages", which consist of a 24 byte
header followed (optionally) by a payload.  The header consists of 6
32 bit words which are sent across the wire in little endian format.

struct message {
    unsigned command;       /* command identifier constant (A_CNXN, ...) */
    unsigned arg0;          /* first argument                            */
    unsigned arg1;          /* second argument                           */
    unsigned data_length;   /* length of payload (0 is allowed)          */
    unsigned data_crc32;    /* crc32 of data payload                     */
    unsigned magic;         /* command ^ 0xffffffff                      */
};
```

client与adbd的数据传输是需要用到两个通道的，当与server建立第一个通道的连接后，需要向server发送transport命令，表示接下来，要与adbd进行数据传输。当server返回“OKAY”后，client后续发送的数据，就直接传输到adbd了。
![ADB 工作原理示意图](/media/433c64e8c67d40eb5219.png)

### USB Vendor ID
![ADB 工作原理示意图](/media/2b9fdd0eb942de0e40bb.png)

### adb forward
设置任意端口转发，将特定主机端口上的请求转发到设备上的其他端口。PC 作为Client客户端 可以任意访问 Phone 上的 Server 服务器

```
adb forward tcp:6100 tcp:7100
adb forward --list
adb forward --remove-all
adb forward tcp:8888 tcp:8888

```
该转发可以用于自己写的程序。


## 实践用法
用法大全: https://github.com/mzlogin/awesome-adb

### Profiler: Editor-to-Android connection
adb forward tcp:34999 localabstract:Unity-{insert bundle identifier here}

### log抓取
adb logcat -s Unity
adb -s %DeviceName% logcat -s Unity
adb logcat -s Unity ActivityManager PackageManager dalvikvm DEBUG #获取log，-s指定过滤器
adb -s deviceName logcat -s Unity  -f c:\unity_log.txt #-f 输出log到指定文件

### 其他常用命令
https://www.huaweicloud.com/articles/39c8580fd6d8eacb6b0b89082f9d15b4.html
## Ref
https://www.zhihu.com/zvideo/1261234074455998464

https://www.jianshu.com/p/6769bfc3e2da

https://itimetraveler.github.io/2019/06/07/Android ADB原理探究/

https://learning.oreilly.com/library/view/unboxing-android-usb/9781430262084/9781430262084_Ch07.xhtml
