本文目录 27 个章节
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
架构

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提供一些服务。

通信机制与workflow
- 在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。
- 在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上与之相连的端口号随机。

通过以下命令,可以看到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
- Client 调用某个 adb 命令
- adb 进程 fork 出一个子进程作为 Server
- Server 查找当前连接的 emulator/device
- Server 接收到来自 Client 请求
- Server 处理请求,将本地处理不了的请求发给
- emulator/device
- 位于 emulator/device 的 adbd拿到请求后交给对应的java虚拟机进程。
- adbd 将结果发回给 Server
- 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每个命令都包含两个部分:
- 命令的长度(Length),由四位的十六进制表示
- 实际的命令(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了。

USB Vendor ID

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原理探究/>
【自动化测试】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 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提供一些服务。

通信机制与workflow
在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。
在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上与之相连的端口号随机。

通过以下命令,可以看到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
- Client 调用某个 adb 命令
- adb 进程 fork 出一个子进程作为 Server
- Server 查找当前连接的 emulator/device
- Server 接收到来自 Client 请求
- Server 处理请求,将本地处理不了的请求发给
- emulator/device
- 位于 emulator/device 的 adbd拿到请求后交给对应的java虚拟机进程。
- adbd 将结果发回给 Server
- 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每个命令都包含两个部分:
- 命令的长度(Length),由四位的十六进制表示
- 实际的命令(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 文件中
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了。

USB Vendor ID

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