| RFC-0200:支持用于硬件测试的 adb 协议和接口 | |
|---|---|
| 状态 | 已接受 |
| 区域 |
|
| 说明 | 添加了 adb 协议和接口支持,以使 Fuchsia 设备能够与标准 adb 客户端互动,从而实现硬件测试用例。 |
| 问题 | |
| Gerrit 更改 | |
| 作者 | |
| 审核人 | |
| 提交日期(年-月-日) | 2022-08-24 |
| 审核日期(年-月-日) | 2022-11-17 |
摘要
此 RFC 建议向 Fuchsia 添加 Android 调试桥 (adb) 协议和接口支持,以用于硬件测试。这将使 Fuchsia 设备能够与标准 adb 客户端交互,这在当前的硬件测试工作流程中有多种应用。adb 支持还将使我们能够从 Windows 主机发现 Fuchsia 设备并与之交互,而这目前不受 Fuchsia 工具的支持。此外,添加对 adb 的支持将使我们能够重复使用围绕 adb shell 构建的大部分测试、工具和流程,以进行硬件验证和制造。为了添加 adb 接口支持,Fuchsia 的 USB 外围设备配置将更新为使用新的 adb 接口,该接口将替换(或与)已启用 adb 的 build 中的现有 USB CDC 以太网接口一起使用。adb 协议支持将仅限于硬件验证和制造用例认为必要的功能。支持的 adb 服务将是 Fuchsia 特有的,不会尝试模仿 Android adb 服务。
设计初衷
在硬件验证和制造测试场景中,adb 支持非常有用:
- 围绕 adb 构建了多种工具、库和框架(1、2、3 等等),这些工具、库和框架可以重复使用。
- 适用于各种平台的 adb 客户端预构建二进制分发版广泛可用,并且易于设置。
- 依赖 adb 提供设备发现、连接和命令执行服务的现有测试框架无需进行任何更改即可正常运行。
- 由于 adb 的普及,开发者对其非常熟悉,并且开源社区也提供了广泛的支持。
- 它可以通过在当前不支持的环境(如 Windows)中对 overnet 连接进行隧道传输,进一步扩展
ffx的使用场景。适用于 Windows 的 adb 经过了充分的测试,并被广泛使用,并且 Google 随时可提供 adb Windows 驱动程序供安装。 - adb 支持基于 USB 外围设备的发现和通信,与 Fuchsia 目前使用的基于 mDNS 的发现相比,延迟更低。缩短延迟时间对于制造用例非常重要。
考虑到 adb 是一种轻量级且通常稳定的工具,它将成为 Fuchsia 工具集的良好补充。
利益相关方
辅导员:
leannogasawara@google.com
审核者:
- curtisgalloway@google.com
- rdzhuang@google.com
- gkalsi@google.com
- prashanthsw@google.com
- jeremymason@google.com
- surajmalhotra@google.com
已咨询:
- palmer@google.com
社会化:我们开发了概念验证,并与相关利益相关方进行了讨论。
设计
本文档中的关键字“必须”“不得”“必需”“会”“不会”“应”“不应”“建议”“可以”和“可选”应按照 IETF RFC 2119 中的描述进行解释。
概览
Android 调试桥 (adb) 由三个主要部分组成:客户端、服务器和守护程序。客户端和服务器在主机上运行,并使用套接字相互通信。adb 守护程序 (adbd) 在设备上运行,通常通过 USB 连接到 adb 服务器。adb 守护程序与服务器之间的通信在 adb 协议中定义。
为了让 adb 发现 Fuchsia 设备,我们必须公开新的 USB adb 接口。为此,必须更新 USB 外围设备配置,并编写新的 USB ADB 功能驱动程序。在主机上运行的 adb 服务器将通过此接口连接到设备。连接后,adb 服务器将通过由 USB adb 功能驱动程序支持的 USB adb 接口发送/接收 adb 协议消息。为了对这些 adb 协议消息进行编码/解码,我们需要编写一个 adb 精灵组件。根据所请求的服务,adb 精灵会将请求转发到相应的组件。我们可能需要编写新的 adb 服务组件,以桥接现有组件与 adb 精灵之间的连接。我们打算仅支持一部分 adb 命令(请参阅 adb 服务)。下图展示了提议的 adb 软件堆栈:

以下各部分详细介绍了每个部分。
adb 接口和设备发现
adb 仅在支持 USB 外围设备模式的 Fuchsia 板上可用。为了在 Fuchsia 产品中包含 adb 支持,产品配置必须包含 adb 软件包,并配置启动实参以指定 USB adb 接口。默认情况下,adb 接口仅在硬件测试产品中启用。在用户 build 或正式版 build 中不应启用 adb,以限制这些 build 的攻击面。
Fuchsia 的 USB 外围设备配置将更新为使用新的 adb 接口,该接口将替换(或与)已启用 adb 的 build 中的现有 USB CDC 以太网接口。新接口将遵循 adb 接口要求:
- USB 类:
vendor - USB 子类:
0x42 - 协议:
1
在主机上运行的 adb 服务器会不断轮询接口描述符与上述属性匹配的新 USB 设备。如果找到,它会记下 USB 设备描述符中提到的 USB 序列号,并使用该序列号来标识设备。adb 客户端将使用此序列号将请求路由到设备。在 Fuchsia 上,此序列号由引导加载程序传递,或从 MAC 地址派生,或是一个硬编码的后备序列号,具体取决于按所列顺序可用的序列号。
USB adb 函数驱动程序
此驱动程序负责处理 adb 接口的 USB 请求。此驱动程序将仅负责处理 USB 数据包和回调。
adb 组件
此组件了解 adb 协议,负责解析消息并将其路由到相应的服务。
adb 服务
当 adb 客户端向 adb 服务器发送命令时,服务器可能会向守护进程发送请求,以连接到设备上的服务,例如 shell 或 logger 服务。adb 精灵会查看已注册的服务提供商列表,以找到匹配项。如果匹配,注册的服务提供方会请求一个 Zircon 套接字。adb 守护进程会将来自 adb 客户端的所有与服务相关的通信转发到此套接字。所请求的服务示例包括 shell、logcat、端口转发和文件同步。此方案旨在通过为每项服务提供单独的组件来支持这些服务。例如,我们可以有一个 adb-shell 组件,用于打开 dash shell 并管理 adb 传输和 dash shell 之间基于 pty 设备的通信;我们还可以有一个 adb-ffx 组件,用于促进 adb 传输和 overnet 的关联。服务列表
服务与 adb 组件之间的接口可能位于以下行中:
// Max length of arguments passed in adb OPEN message.
const MAX_ARGS_LENGTH uint64 = 1024
/// A Provider is a provider for one service.
/// The interaction between the adb daemon and Provider is as follows:
/// - adb daemon is started eagerly by core.cml
/// - When an request for a service comes in, adb daemon starts up a lazy component serving
/// Provider and calls ConnectToService, handing it a socket.
/// - If the service has already been started, it opens that service and hands it a socket.
/// - adb daemon and Provider communicate over the socket.
@discoverable
protocol Provider {
/// Connect `socket` to the service (called in response to adb OPEN message).
/// `args` provides additional arguments passed by the client if any.
ConnectToService(resource struct {
socket zx.handle:SOCKET;
args string:<MAX_ARGS_LENGTH, optional>;
}) -> (struct {}) error zx.status;
};
adb 协议指定了多种服务,但我们只打算支持其中的一部分 - shell、logcat、sync(用于 adb push/pull)。这些服务可能无法模拟其他平台上 adb 的所有行为,并且会针对 Fuchsia 进行定制,例如,shell 命令必须与 Fuchsia 支持的命令相匹配,日志可能采用 Fuchsia 系统日志格式。下一部分将详细讨论 adb shell 服务。未来是否会支持更多服务,我们将根据具体情况进行考虑。
示例 adb 服务:adb shell
本部分以 adb shell 服务为例,介绍了 adb 服务与 adb 精灵之间的互动。adb shell 组件将负责通过 dash 启动器服务将 adb shell I/O 桥接到 dash shell I/O,从而提供 adb shell 服务。默认情况下,adb-shell.cm 将提供类似于通过 sshd-host.cm 使用 ffx component
explore 的 shell,或者提供功能更受限的 shell。如果我们在 Fuchsia 中迁移到不同的界面,adb-shell 也可以迁移到该界面。为了限制特定产品配置和特定使用情形下的功能,可以使用功能有限的自定义 shell 提供程序来替换此组件。这与使用 ffx component
explore <specific-moniker> 类似。
每次用户请求新的 adb shell 实例时,adb daemon 都会请求新的 adb shell 会话(以及新的 dash 会话)。从 adb 客户端或控制台关闭连接将关闭整个会话。以下序列图显示了交互序列:

身份验证和加密
adb 协议支持使用 RSA 密钥对进行身份验证。它还支持 TLS 加密。 这两项功能都是可选的。对于初始实现,这些功能将不会实现,因为预期用途仅限于在受限环境中运行的开发者或测试 build。此外,由于 USB 是唯一受支持的传输方式,因此在一定程度上会限制攻击方法。未来,如果支持这些功能,则只需更新 adb 精灵。
维护
系统将支持当前的 adb 协议版本 0x01000000。未来对该协议的更新将根据具体情况进行。adb 协议很少发生更改,并且一直向后兼容。
实现
实现可以分为三部分。
- 在不同主板和 build 中添加支持。
- adb 守护程序
- 在 OSRB 获得批准后,其中的部分内容将从 Android 代码库导入。
- adb 服务
- 目前的计划是支持
adb-shell和adb-ffx。 - 如果必须支持其他命令,此阶段可能会延长。
- 目前的计划是支持
目前已存在概念验证,可作为实现参考。
性能
计算影响:添加 adb 支持不应产生任何显著的计算开销。adb 将取代 ssh 精灵程序和/或 overnetstack,这两者都依赖于类似的驱动程序和组件,因此系统的总体 CPU 使用率应保持不变。
对大小的影响:添加 adb 精灵和服务后,映像大小将增加约 1MB。请注意,这仅适用于通过 adb 支持组装的开发和测试 build。由于将使用 adb 而不是现有工具,因此对运行时内存占用空间应该不会有任何重大影响。
延迟时间:由于没有额外的网络堆栈,因此 adb 中命令处理的延迟时间会略低于 ssh 或其他基于网络的服务。设备发现延迟时间预计也会更短,因为它是基于 USB 枚举,而不是像 mDNS 那样基于定期广播。
向后兼容性
这方面有三个部分 - 一是 adb 协议本身的向后兼容性,这超出了 Fuchsia 项目的控制范围。不过,众所周知,adb 协议一直保持着向后兼容性。其次,支持的 adb 服务 - 服务的弃用会影响依赖于这些服务的主机端命令/脚本。在进行此类更改时,必须使用适当的迁移策略。第三,shell 命令。例如,如果弃用假设的 CLI xyz-tool,则运行 adb shell xyz-tool 的脚本将不再起作用。此问题属于 Fuchsia 工具的范围,并非 adb 特有的问题,因此不会解决。
安全注意事项
至于 adb 传输的安全注意事项,其中规定了启用身份验证和加密的条件。不过,这些功能不会在初始实现中启用。由于 adb 仅在开发者 build 或测试 build 等特定 build 中可用,而在用户 build 中不可用,因此这不应成为主要问题。
通过 adb 公开的服务的安全性注意事项与 Fuchsia 上现有服务的安全性注意事项并无不同。该 adb-shell / adb-ffx 公开的交互界面与 dash-shell /ffx 的交互界面相同或更小。对于特定用例,可以通过将 shell 提供程序从 adb-shell 替换为 custom-shell,使用针对该用例量身定制的紧密限定范围的 shell。
初始实现将仅支持 USB 传输。与基于网络的连接相比,这会限制可能的攻击方法。此外,adb 守护程序本身就是一个组件,因此其中的任何漏洞都会被沙盒化到该特定进程,并且只会影响 adb 操作。
隐私注意事项
adb 服务公开的数据与 ffx component explore 或 SSH 公开的数据相同,这两者都经过隐私权方面的审核。此外,此技术将仅限于开发者 build 或测试 build,不会部署在用户 build/生产 build 中。不过,USB adb 接口会公开设备序列号,该序列号与其他 USB 接口(例如 CDC 以太网接口)所用的序列号相同。如果不是从 MAC 地址派生出来的,则主要由引导加载程序配置。在产品配置期间,必须注意不要直接使用具有重要意义的设备 ID。
测试
adb 堆栈的所有部分都将进行单元测试。最终,我们将添加 adb 精灵和 adb 服务之间的集成测试。由于 adb 子系统之间的合约基于 FIDL(USB adb 驱动程序除外),因此测试可以是封闭的。将为 USB adb 接口添加设备枚举测试。如果需要,将添加针对 adb 的主机端 E2E 测试。对于 E2E 测试,我们可能需要在测试宿主机上安装 adb。E2E 测试 / 集成测试可用于性能测试和命令延迟时间测试。频繁插拔 USB 以对 adb 连接进行周期性压力测试,这将纳入可靠性测试的考虑范围。此外,还将考虑对 adb 精灵实现进行模糊测试。
文档
您需要添加以下文件:
- 支持的 adb 功能列表
- 扩展 adb 服务的指南
- 用户指南
缺点、替代方案和未知因素
支持 adb 需要付出维护成本。同时使用两套工具(即 ffx 和 adb)进行通信和设备控制会产生开销。虽然这两者会具有重叠的功能,但各自的用例是可区分的,并且它们将共享相同的后端实现。ffx 适用于各种开发者工作流程,但目前在主机端脚本编写和各种平台支持方面存在限制。adb 可用于弥补硬件测试方面的这些不足。通过在 ffx 和 adb 之间共享设备上的服务,可以进一步降低维护成本。例如,dash 启动器、overnetstack、日志接收器等也可以与 adb 搭配使用。
替代方案:将 ffx 移植到 Windows
目前,实现此目标的主要障碍是获取对 Windows 的 Rust 工具链支持,以及向 ffx 添加 USB 链接。此外,依赖于 adb 的现有测试框架必须更改为使用 ffx,或者必须在 adb 和 ffx 之间提供转换 shim。此策略可在未来重新考虑。在开发适用于 Windows 的 ffx 期间,adb 提供了一种便捷的解决方案。
替代方案:在 Linux 虚拟机中运行主机端 ffx
使用在 Windows 上运行的 Linux 虚拟机(VM),并直通设备 USB 连接。通过此设置,现有的 ffx 工作流将同时适用于设备发现和互动。但设置虚拟机所花费的时间可能很长,并且可能不稳定/不可靠。此外,部分组织还会限制在受管理的 Windows 机器上使用虚拟机。使用 Docker 容器是另一种替代方案,但 USB 转发可能无法正常运行,具体取决于 Windows 版本。
替代方案:USB 串行设备
为 Fuchsia 添加了对 USB CDC ACM 外围设备的支持。Windows 包含一个内置的 USB 串行驱动程序,适用于任何 USB CDC ACM 接口。这样一来,我们就可以将 USB 端口用作串行通信设备。此方法的缺点是缺少丰富的命令集(仅提供 shell)、日志和 shell 未分离,以及仅支持单个实例。此外,基于 adb 的现有测试框架也必须更新。
在先技术和参考资料
- adb 概览 - adb 客户端、服务器和守护程序概览
- adb 协议 - adb 消息类型和字段
- Android 上的 adb - Android adb 实现