自 2025 年 3 月 27 日起,我们建议您使用 android-latest-release
而非 aosp-main
构建 AOSP 并为其做出贡献。如需了解详情,请参阅 AOSP 的变更。
Android 开放配件 1.0
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
Android USB 配件必须遵循 Android 开放配件 (AOA) 协议,该协议规定了配件如何检测 Android 设备并与其建立通信。配件应执行以下步骤:
- 等待设备连接并对其进行检测。
- 确定设备是否支持配件模式。
- 尝试以配件模式启动设备(如需要)。
- 如果设备支持 AOA,则与该设备建立通信。
以下部分介绍了如何执行上述步骤。
等待设备连接并对其进行检测
配件应该不间断地检查是否连接了 Android 设备。设备成功连接后,配件应该确定设备是否支持配件模式。
确定是否支持配件模式
注意:连接配件不需要 USB 调试,但在开发过程中可能需要 ADB。如需了解详情,请参阅调试注意事项。
当 Android 设备成功连接后,它可能处于以下三种状态之一:
- 支持 Android 配件模式,并且已处于配件模式。
- 支持 Android 配件模式,但是未处于配件模式。
- 不支持 Android 配件模式。
在初次连接时,配件应该检查所连接设备的 USB 设备描述符的版本、供应商 ID 和产品 ID。供应商 ID 应与 Google 的 ID (0x18D1
) 相符。如果设备已经处于配件模式,产品 ID 应为 0x2D00
或 0x2D01
,配件可以使用自己的通信协议通过批量传输端点与设备建立通信(不需要以配件模式启动设备)。
注意:0x2D00
是为支持配件模式的 Android 设备预留的产品 ID。0x2D01
则是为同时支持配件模式和 Android 调试桥 (ADB) 协议的设备预留的产品 ID,这类设备提供了第二个接口(具有两个批量端点,用于 ADB 通信)。如果您在计算机上模拟配件,可以使用这些端点调试配件应用。一般来说,不要使用该接口,除非配件在设备上实现了到 ADB 的直通通信。
如果发现 USB 设备描述符中的版本、供应商 ID 或产品 ID 与期望值不符,则配件无法确定设备是否支持 Android 配件模式。配件应尝试以配件模式启动设备(详见下文)以确定设备是否支持配件模式。
要点:USB 配件必须在初始握手后发送头文件。头文件中包含制造商、型号和版本。虽然版本是一个可选字段,但如果安装了仅版本匹配的 Android 应用而配件没有发送版本,搭载 Android 10 及更低版本的 Android 设备就会因系统进程中抛出的异常而重新启动。
尝试以配件模式启动
如果版本、供应商 ID 和产品 ID 与处于配件模式下的 Android 设备不对应,配件就无法确定设备是支持(但未处于)配件模式,还是不支持配件模式。发生这种情况是因为支持配件模式(但未处于配件模式下)的设备首先报告的是设备制造商的供应商 ID 和产品 ID,而不是 AOA 供应商 ID 和产品 ID。
配件应尝试以配件模式启动设备,以确定设备是否支持该模式:
- 发送 51 控制请求(“获取协议”)以确定设备是否支持 Android 配件协议。如果设备支持协议,则返回一个非零数字,代表所支持的协议版本。该控制请求为端点 0 上的请求,具有以下特征:
requestType: USB_DIR_IN | USB_TYPE_VENDOR
request: 51
value: 0
index: 0
data: protocol version number (16 bits little endian sent from the
device to the accessory)
- 如果设备返回所支持的协议版本,则向设备发送含标识字符串信息的控制请求。该信息让设备可以确定适合配件的应用(如果没有适合配件的应用,则向用户呈现一个网址)。该控制请求为端点 0 上的请求(适用每个字符串 ID),具有以下特征:
requestType: USB_DIR_OUT | USB_TYPE_VENDOR
request: 52
value: 0
index: string ID
data zero terminated UTF8 string sent from accessory to device
支持以下字符串 ID,并且每个字符串的最大大小为 256 个字节(必须以零结束,以 \0
结尾)。
manufacturer name: 0
model name: 1
description: 2
version: 3
URI: 4
serial number: 5
- 发送控制请求,要求设备以配件模式启动。该控制请求为端点 0 上的请求,具有以下特征:
requestType: USB_DIR_OUT | USB_TYPE_VENDOR
request: 53
value: 0
index: 0
data: none
完成这些步骤后,配件应等待所连接的 USB 设备在配件模式下将其自身重新接入总线,然后重新枚举所连接的设备。该算法通过检查供应商 ID 和产品 ID 来确定设备是否支持配件模式,如果设备成功切换到配件模式,那么供应商 ID 和产品 ID 就应该是正确的(例如,与 Google 的供应商 ID 和产品 ID 而不是设备制造商的 ID 相对应)。如果 ID 和版本正确无误,配件会进而与设备建立通信。
注意:AOA 当前不支持同时进行 AOA 连接和 MTP 连接。如需从 AOA 切换到 MTP,配件必须首先与 USB 设备断开连接(断开物理连接或以电气等效的方式断开),然后使用 MTP 重新连接 USB 设备。
如果有任意步骤失败,配件则确定设备不支持 Android 配件模式,并等待下一个设备连接。
与设备建立通信
如果配件检测到配件模式下的 Android 设备,则配件可以查询设备接口和端点描述符,以获取用于与设备进行通信的批量端点。
接口和批量端点的数量取决于产品 ID。具有以下产品 ID 的 Android 设备所具备的接口情况:
0x2D00
有一个接口,该接口有两个批量端点,用于输入和输出通信。
0x2D01
有两个接口,每个接口有两个批量端点,用于输入和输出通信。第一个接口处理标准通信,第二个接口则处理 ADB 通信。如需使用接口,请找到第一个批量输入和输出端点,使用 SET_CONFIGURATION
(0x09
) 设备请求将设备配置的值设为 1,然后使用端点进行通信。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-07-27。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-07-27。"],[],[],null,["# Android Open Accessory 1.0\n\nAndroid USB accessories must adhere to the Android Open Accessory (AOA)\nprotocol, which defines how an accessory detects and sets up communication with\nan Android-powered device. Accessories should carry out the following steps:\n\n1. Wait for and detect a connected device.\n2. Determine the device's accessory mode support.\n3. Attempt to start the device in accessory mode (if needed).\n4. If the device supports AOA, establish communication with the device.\n\nThe following sections explain how to implement these steps.\n\nWait for and detect connected\ndevices\n-------------------------------------\n\nAccessories should continuously check for connected Android-powered devices.\nWhen a device is connected, the accessory should determine if the device\nsupports accessory mode.\n\nDetermine accessory mode support\n--------------------------------\n\n**Note:** USB debugging isn't required for connecting accessories but\nADB might be necessary during development. For details, see\n[Debug considerations](https://developer.android.com/guide/topics/connectivity/usb#debug-considerations).\n\nWhen an Android-powered device connects, it can be in one of three states:\n\n- Supports Android accessory mode and is already in accessory mode.\n- Supports Android accessory mode but it is not in accessory mode.\n- Does not support Android accessory mode.\n\nDuring the initial connection, the accessory should check the version, vendor ID,\nand product ID of the connected device's USB device descriptor. The vendor ID\nshould match Google's ID (`0x18D1`). If the device is already in\naccessory mode, the product ID should be `0x2D00` or\n`0x2D01` and the accessory can\n[establish communication with\nthe device](#establish-communication-with-the-device) through bulk transfer endpoints using its own communication\nprotocol (the device does not need to be started in accessory mode).\n\n**Note:** `0x2D00` is reserved for\nAndroid-powered devices that support accessory mode. `0x2D01` is\nreserved for devices that support accessory mode as well as the Android Debug\nBridge (ADB) protocol, which exposes a second interface with two bulk endpoints\nfor ADB. You can use these endpoints for debugging the accessory application if\nyou are simulating the accessory on a computer. In general, do not use this\ninterface unless the accessory implements a passthrough to ADB on the device.\n\nIf the version, vendor ID, or product ID in the USB device descriptor do not\nmatch expected values, the accessory cannot determine if the device supports\nAndroid accessory mode. The accessory should attempt to start the device in\naccessory mode (detailed below) to determine device support.\n\n**Key point:**A USB accessory must\nsend a header upon initial handshake. The header contains the manufacturer, model, and\nversion. Though version is an optional field, if an Android app is installed that only\nmatches on version, but the accessory doesn't send a version, Android devices\nrunning on Android 10 and below will reboot due to an exception being thrown in\nthe system process.\n\nAttempt to start in accessory\nmode\n----------------------------------\n\nIf the version, vendor, and product IDs do not correspond to an Android-powered\ndevice in accessory mode, the accessory cannot determine if the device supports (but\nis not in) accessory mode or if the device does not support accessory mode. This\ncan occur because devices that support accessory mode (but are not in accessory\nmode) initially report the *device* manufacturer vendor and product IDs\ninstead of the *AOA* vendor and product IDs.\n\nThe accessory should try to start the device in accessory mode to determine\nif the device supports that mode:\n\n1. Send a 51 control request (\"Get Protocol\") to determine if the device supports the Android accessory protocol. If the device supports the protocol, it returns a non-zero number that represents the supported protocol version. The control request is on endpoint 0 with the following characteristics: \n\n ```\n requestType: USB_DIR_IN | USB_TYPE_VENDOR\n request: 51\n value: 0\n index: 0\n data: protocol version number (16 bits little endian sent from the\n device to the accessory)\n ```\n2. If the device returns a supported protocol version, send a control request with identifying string information to the device. This information allows the device to determine an appropriate application for the accessory (or present a URL to the user if an appropriate application does not exist). The control request is on endpoint 0 (for each string ID) with the following characteristics: \n\n ```\n requestType: USB_DIR_OUT | USB_TYPE_VENDOR\n request: 52\n value: 0\n index: string ID\n data zero terminated UTF8 string sent from accessory to device\n ```\n\n The following string IDs are supported, with a maximum size of 256 bytes\n for each string (must be zero-terminated with `\\0`). \n\n ```\n manufacturer name: 0\n model name: 1\n description: 2\n version: 3\n URI: 4\n serial number: 5\n ```\n3. Send a control request to ask the device to start in accessory mode. The control request is on endpoint 0 with the following characteristics: \n\n ```\n requestType: USB_DIR_OUT | USB_TYPE_VENDOR\n request: 53\n value: 0\n index: 0\n data: none\n ```\n\nAfter completing these steps, the accessory should wait for the connected USB\ndevice to re-introduce itself on the bus in accessory mode, then re-enumerate\nconnected devices. The algorithm\n[determines accessory mode support](#determine-accessory-mode-support)\nby checking the vendor and product IDs, which should be correct (for example, correspond\nto Google's vendor and product IDs instead of to the device manufacturer's IDs) if\nthe device successfully switched to accessory mode. If IDs and version are correct,\nthe accessory moves to [establish\ncommunication with the device](#establish-communication-with-the-device).\n\n**Note:** AOA does not currently support\nsimultaneous AOA and MTP connections. To switch from AOA to MTP, the accessory\nmust first disconnect the USB device (either physically or in an electrically\nequivalent way) and then reconnect using MTP.\n\nIf any step fails, the accessory determines the device does not support\nAndroid accessory mode and waits for the next device to connect.\n\nEstablish communication with\nthe device\n---------------------------------------\n\nIf the accessory detects an Android-powered device in accessory mode, the\naccessory can query the device interface and endpoint descriptors to obtain the\nbulk endpoints for communicating with the device.\n\nThe number of interfaces and bulk endpoints depends on the product ID. An\nAndroid-powered device with a product ID of:\n\n- `0x2D00` has one interface with two bulk endpoints for input and output communication.\n- `0x2D01` has two interfaces with two bulk endpoints each for input and output communication. The first interface handles standard communication and the second interface handles ADB communication. To use an interface, locate the first bulk input and output endpoints, set the device configuration to a value of 1 with a `SET_CONFIGURATION` (`0x09`) device request, then communicate using the endpoints."]]