第4章2节《MonkeyRunner源码剖析》ADB协议及服务: ADB服务SERVICES.TXT翻译参考(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文“寻求合作伙伴编写《深入理解 MonkeyRunner》书籍“。但因为诸多原因,没有如愿。所以这里把草稿分享出来,所以错误在所难免。有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息。

ADB服务器端在接受到ADB客户端发送过来的命令后会进行相应的处理,如果是主机服务就在ADB服务器内部进行处理,如果是本地服务就会发送给Android目标机器端的adbd守护进程进行处理。

因为ADB相关的源代码不在我们源码分析的范围之内,所以我们很有必要把官方提供的ADB服务器支持的所有服务在这里描述下。虽然本人对自己的英语水平相当有信心,但总担心有词不达意的时候,所以翻译的过程中把英文也保留了下来以供大家参考。

主机服务:

host:version



向ADB服务器请求其内部版本号。作为一个协议中的例外(请查看OVERVIEW.txt来查看ADB具体协议规则),服务器会返回一个代表其内部版本号的4字节的十六进制字符串,而不会像标准协议中会返回OKAY或者FAIL

host:kill



请求ADB服务器立刻退出。当ADB升级完成后,如果ADB客户端检测到之前已经过时的ADB服务器还在运行的时候会发送这个请求。

host:devices host:devices -l



这两个服务请求是类似的,都是请求ADB服务器返回一系列有效的安卓设备以及对应的状态信息,只是devices -l会在状态信息中包含该设备更多的信息,比如产品型号等。在正常返回OKAY之后,会紧跟着一个代表数据长度的4字节长的十六进制数,以及对应的如我们通过命令adb devices -l命令能看到的输出,然后连接请求就会关闭。

host:track-devices



这个服务是以上的host:devices的一个变种,客户端和ADB服务器的连接会一直保持,当有增加/移除设备或者设备状态改变的时候会主动的往连接上的客户端发送新的设备列表信息(4字节16进制长度+内容)。这样做的话就可以允许DDMS这些工具来实时跟踪所有连接上来的设备的状态,而不需要客户端每次都去连接ADB服务器获取对应信息。

host:emulator:



这是一个特殊的请求,当一个新的模拟器启动的时候这个请求将会发送到ADB服务器。对应的是模拟器的控制端口的一个十进制数字,例如本机转发到正在运行的模拟器的adbd的对应的那个TCP转发端口。这个机制让ADB服务器可以清楚知道有哪个模拟器被启动起来了。

host:transport:



请求ADB服务器切换当前连接到指定的设备/模拟器。在OKAY应答之后,客户端的所有请求都会重定向到该设备的adbd这个守护进程。(用来实现ADB命令行客户端的-s选项)

host:transport-usb



请求ADB服务器切换当前连接到通过USB连接到主机的设备。如果多于一个设备通过USB连接到主机,调用将会失败。(用来实现ADB命令行客户端的-d这个方便使用的选项)

host:transport-local



请求ADB服务器切换当前连接到一个通过TCP协议连接上来的模拟器。如果多于一个模拟器在运行的话,调用将会失败。(用来实现-e这个方便使用的选项)

host:transport-any



另外一个host:transport的变种。请求ADB服务器切换当前连接到已经连接上主机的设备或者正在主机中运行的中模拟器。如果有多于一个这类设备存在,调用将会失败。(在-s,-d或-e选项都没有提供的时候使用)

host-serial: serial-number:request



这是一个特殊的请求,前缀”host-serial:serial-number>:”是用来指定客户端请求信息时的目标ADB服务器所在的一个特定设备。request可以是以下描述的任一方法。

host-usb:request

host-serial的一个变种,指定的是一个连接上主机的USB设备。如果没有或者有多于一个这种设备的话调用将会失败。

host-local:request



另一个host-serial的变种,这次指定的是一个在主机运行的模拟器。如果没有或者有多于一个这种设备的话调用将会失败。相当于直接执行” adb get-product”或者“adb get-serilano”等

host:request



当通过ADB服务器向一个相关设备请求信息的时候,’host:’ 在这种情况下也可以指‘任意一个连接上主机的的设备或者正在主机上运行的模拟器’。

(以下”host-prefix:”开始的描述的就是上面4种特殊服务请求的参数)

host-prefix:get-product

XXX

官方就提供了上面的XXX,没有更多的信息。本人在尝试”adb get-product”时发现并没有支持。

host-prefix:get-serialno

返回对应的设备/模拟器的序列号。”host-prefix:”指的是上面4种特殊信息请求命令。注意模拟器的序列号的格式形如”emulator-5554”。类似于命令行执行”adb get-serialno”

host-prefix:get-devpath

返回对应设备/模拟器的设备路径,这里的设备路径指的是”adb device -l”列出的最后一部分,如”device product:OPPO_12025 model:X909 device:X909”。 “host-prefix:”指的是上面三种特殊信息请求命令。类似于命令行执行”adb get-devpath”。

host-prefix:get-state

返回一个代表指定设备状态的字串,”host-prefix:”指的是上面三种特殊信息请求命令。类似于命令行执行”adb get-stat”。

host-prefix:forward:local;remote

请求ADB服务器把本地local指定的连接重定向到指定设备的remote地址。在这里,”host-prefix”可以是以上描述的用来指定目标设备/模拟器的

其中local的格式可以是以下任一种:

  • tcp:port -> 本地主机的port端口的TCP连接
  • local:path -> 基于地址path的本地主机的Unix域套接字连接(UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径)

remote的格式如下:

  • tcp: port ->目标设备的localhost:port
  • local:path -> 目标设备的本地Unix Domain Socket
  • jdwp:pid -> 目标设备中进程号指定的JAVA虚拟机内部的JDWP线程

甚至还支持下面描述的任一个本地服务

host-prefix:forward:norebind:local;remote

类似host-prefix:forward:local;remote ,有一点区别是如果已经存在local的一个转发的话调用会失败。用来实现”adb forward –no-rebind local remote”

host-prefix:killforward:local

移除所有指定的本地重定向连接。用来实现”adb forward –remove local”命令

host-prefix:killforward-all

移除所有的重定向连接。用来实现”adb forward –remove-all”命令

host-prefix:list-forward

列出本机所有存在的转发连接。返回格式如下:

  • hex4: 返回结果长度,由4字节16进制字符组成
  • payload: 一连串以下格式的行:
    • serial ” ” local ” ” remote “\n”:serial代表设备序列号。local代表主机端的的连接点(比如tcp:90000)。remote代表设备端的连接点。

这是用来实现”adb forward –list”命令的。

本地服务:



下面的所有请求是建立在你已经把传输切换到一个真实设备上,或者你使用了以上描述的一个query前缀的服务请求。

shell:command arg1 arg2 …



在设备的shell中运行’command arg1 arg2 …’,并且返回对应输出和错误流。

注意参数必须空格隔开。如果一个参数本身包含空格,那么它必须要用双引号引起来。参数内部不能包含双引号,否则命令执行结果将无法控制。

注意这是”adb shell”的一个非交互式版本

shell:



开启设备的一个交互shell会话。合理的重定向了标准输入/标准输出/标注错误。

注意ADB服务器就是使用这个协议来实现命令行客户端的”adb shell”请求的,但当然它会先包装整理好输入的信息再发送到目标设备(请查看commandline.c的interactive_shell())

remount:



请求adbd去重新把设备只读文件系统挂载成可读写模式的文件系统。这个在执行”adb sync”或者”adb push”请求之前通常是很有必要先执行的。这个请求在一些版本中也许因为不支持而会失败

dev:path



打开一个设备文件并通过客户端连接上该设备来进行读写操作。通常这是用来调试用的,但可能不可以在所有设备上运行,因为它需要特殊的权限才能执行。path指的是从文件系统根开始的全路径。

tcp:port



尝试连接上本机的tcp端口port

tcp:port:server-name



尝试连接上server-name指定的设备的tcp端口port。这对调试只能在设备上显示的网络/代理问题很有用。

local:path



尝试连接上设备上的path地址指定的Unix域套接字

localreserved:path | localabstract: path | localfilesystem: path



local:path的几个变种,用来访问安卓其他命名空间指定的套接字。

log:name



打开/dev/log/name指定的一个系统日记文件,并允许客户端去直接读取日记信息。用来实现”adb logcat”这个命令。日记流对客户端是只读的。

framebuffer:



这个服务是用来把framebuffer的截屏快照发送到客户端的。它需要足够的权限,且工作原理如下: 服务在返回OKAY之后会继续发送16字节的二进制结构数据的以下内容到客户端(小字节序格式)

  • depth: uint32_t: framebuffer 深度
  • size: uint32_t: framebuffer 大小(字节)
  • width: uint32_t: framebuffer宽度(像素)
  • height: uint32_t: framebuffer 高度(像素)

在当前的实现中,宽度永远是16,大小也永远是宽度*高度*2

每次客户端想要一个截屏快照时,它将会通过Socket通道发送一个字节,这会触发本服务去把framebuffer数据按其大小指定的字节数发送给客户端。如果adbd守护进程没有足够的权限打开framebuffer设备,那么连接会立即关闭。

jdwp:pid



连接目标设备中由进程号指定的JAVA虚拟机进程内部的JDWP线程

track-jdwp



这个服务是用来周期性的往客户端发送有启用JDWP的进程的进程号列表。

The format of the returned data is the following:

返回数据格式如下:

  • hex4: 代表返回数据长度的一个4字节16进制字串
  • content: 一系列的ASCLL字串行,每行的格式如下: “\n”

这个服务被DDMS用来知悉有哪些可调式的进程正在真实设备/模拟器上运行。

注意并不存在另外一个服务来只获取一次这个列表。

sync:



开启文件同步服务,用来实现”adb push”和” adb pull” 这两个命令。因为这个服务相当复杂,更详细的信息请查看相关的SYNC.TXT文档。

官方英文版: https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT

——— 未完待续———



作者:天地会珠海分舵

微信公众号:TechGoGoGo

微博:http://weibo.com/techgogogo

CSDN:http://blog.csdn.net/zhubaitian

时间: 2024-08-07 21:18:24

第4章2节《MonkeyRunner源码剖析》ADB协议及服务: ADB服务SERVICES.TXT翻译参考(原创)的相关文章

老李推荐:第6章3节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-命令翻译类

老李推荐:第6章3节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-命令翻译类 每个来自网络的字串命令都需要进行解析执行,只是有些是在解析的过程中直接执行了事,而有些是需要在解析后创建相应的事件类实例并添加到命令队列里面排队执行.负责这部分工作的就是命令翻译类.那么我们往下还是继续在MonkeySourceNetwork这个范畴中MonkeyCommand类是怎么一回事: 图6-3-1 MonkeyCommand族谱 图中间的MonkeyCommand是一个接口,

第5章4节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 命令行参数解析(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. 设置好Monkey的CLASSPATH环境变量以指定"/system/framework /framework/monkey.jar"后,/system/bin/monkey这个shell脚本就会通

第6章3节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-命令翻译类

每个来自网络的字串命令都需要进行解析执行,只是有些是在解析的过程中直接执行了事,而有些是需要在解析后创建相应的事件类实例并添加到命令队列里面排队执行.负责这部分工作的就是命令翻译类.那么我们往下还是继续在MonkeySourceNetwork这个范畴中MonkeyCommand类是怎么一回事: 图6-3-1 MonkeyCommand族谱 图中间的MonkeyCommand是一个接口,主要定义了translateCommand这个方法,它接收的参数是一个字串命令以及参数的列表以及命令队列,所有实

老李推荐: 第8章4节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-启动AndroidDebugBridge 1

老李推荐: 第8章4节<MonkeyRunner源码剖析>MonkeyRunner启动运行过程-启动AndroidDebugBridge 上一节我们看到在启动AndroidDebugBridge的过程中会调用其start方法,而该方法会做2个主要的事情: 715行startAdb:开启AndroidDebugBridge 722-723行:初始化android设备监控并启动DeviceMonitor设备监控线程. 其中第一点我们上一小节已经做了详尽分析了,那么我们往下就去分析下第2点. Dev

老李推荐:第6章5节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-事件

老李推荐:第6章5节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-事件 从网络过来的命令字串需要解析翻译出来,有些命令会在翻译好后直接执行然后返回,但有一大部分命令在翻译后需要转换成对应的事件,然后放入到命令队列里面等待执行.Monkey在取出一个事件执行的时候主要是执行其injectEvent方法来注入事件,而注入事件根据是否需要往系统注入事件分为两种: 需要通过系统服务往系统注入事件:如MonkeyKeyEvent事件会通过系统的InputManager往系

老李推荐: 第1章1节《MonkeyRunner源码剖析》概述:前言

老李推荐: 第1章1节<MonkeyRunner源码剖析>概述:前言 前言 相信大家做过安卓移动平台UI自动化开发的必然会用过,至少听过MonkeyRunner这个名字.MonkeyRunner是一个针对安卓平台的UI自动化测试框架,这个框架的其中一个但绝不是唯一的优点是支持用当今非常流行和高效的Python语言来进行脚本开发.同时,它相比Instrumentation框架或者基于Instrumentation的自动化测试框架最大的优点之一就是可以跨应用测试. 这本书不会有什么序言或者致谢什么

第4章3节《MonkeyRunner源码剖析》ADB协议及服务: ADB协议概览SYNC.TXT翻译参考(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. 本文档的目的是去文档化一个客户端请求ADB服务器往adbd守护进程发送文件相关的请求.请查看OVERVIEW.TXT文档去查看(ADB服务器和adbd守护进程)相关信息,查看SERVICES.TXT去学习其他更多的可用

第5章5节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 获取系统服务引用(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. 上一节我们描述了monkey的命令处理入口函数run是如何调用optionProcess方法来解析命令行参数的.启动参数主要时去指导Monkey时怎么运行起来的,但Monkey作为MonkeyRunner框架的一部分,

第5章2节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 启动流程概览(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. 每个应用都会有一个入口方法来供操作系统调用执行,Monkey这个应用的入口方法就是在Monkey.java这个类里面的,也就是说Monkey.java就是整个Monkey应用的入口类. Monkey作为一个命令行应用,