Android 开放配件 2.0

本文档介绍了自 Android 开放配件 (AOA) 协议首次发布以来的变更,并补充了 AOA 1.0 文档。AOAv2 添加了以下功能

  • 音频输出(在 Android 8.0 中已弃用)。
  • 支持配件充当 Android 设备的一个或多个人机接口设备 (HID)。

Android SDK API 对 Android 应用开发者保持不变。

检测 AOAv2 支持

要确定连接的 Android 设备是否支持配件以及支持的协议版本,配件必须发送 getProtocol() 命令并检查结果。仅支持 AOAv1 中功能的 Android 设备必须返回 1 作为协议版本;支持 AOAv2 中附加功能的设备必须返回 2 作为协议版本。AOAv2 向后兼容 AOAv1,因此为原始配件协议设计的配件可以继续与较新的 Android 设备配合使用。

以下示例来自配件开发套件 2011 源代码<adk-src>/adk1/board/AndroidAccessory/AndroidAccessory.cpp) 库,演示了此协议检查

bool AndroidAccessory::switchDevice(byte addr)
{
    int protocol = getProtocol(addr);
    if (protocol >= 1) {
        Serial.print("device supports protocol 1 or higher\n");
    } else {
        Serial.print("could not read device protocol version\n");
        return false;
    }

    sendString(addr, ACCESSORY_STRING_MANUFACTURER, manufacturer);
    sendString(addr, ACCESSORY_STRING_MODEL, model);
    sendString(addr, ACCESSORY_STRING_DESCRIPTION, description);
    sendString(addr, ACCESSORY_STRING_VERSION, version);
    sendString(addr, ACCESSORY_STRING_URI, uri);
    sendString(addr, ACCESSORY_STRING_SERIAL, serial);

    usb.ctrlReq(addr, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_VENDOR |
                USB_SETUP_RECIPIENT_DEVICE, ACCESSORY_START, 0, 0, 0, 0, NULL);
    return true;
}

AOAv2 包括新的 USB 产品 ID,用于配件模式下可用的 USB 接口的每种组合

版本 产品 ID 通信 说明
AOAv1 0x2D00 配件 提供两个批量端点,用于与 Android 应用通信。
0x2D01 配件 + adb 用于配件开发期间的调试目的。仅当用户在 Android 设备设置中启用了USB 调试时才可用。
AOAv2 0x2D02 音频 用于将音频从 Android 设备流式传输到配件。
0x2D03 音频 + adb
0x2D04 配件 + 音频
0x2D05 配件 + 音频 + adb

AOAv1 中使用的产品 ID(0x2D000x2D01)在 AOAv2 中继续受支持。

音频支持

AOAv2 包括通过标准 USB 音频类接口支持从 Android 设备到配件的音频输出,该接口能够支持 2 声道、16 位 PCM 音频,比特率为 44100 Khz(未来可能会添加其他音频模式)。

要启用音频支持,配件必须发送新的 USB 控制请求

**SET_AUDIO_MODE**
requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
request:        58
value:          0 for no audio (default),
                1 for 2 channel, 16-bit PCM at 44100 KHz
index:          0
data            none

此命令必须在发送用于进入配件模式的 ACCESSORY_START 命令之前发送。

HID 支持

AOAv2 允许配件向 Android 设备注册一个或多个人机接口设备 (HID)。这种方法颠倒了典型 USB HID 设备(例如 USB 鼠标和键盘)的通信方向。通常,HID 设备是连接到 USB 主机(即个人计算机)的外围设备,但在 AOA 中,USB 主机可以充当 USB 外围设备的一个或多个输入设备。

HID 支持是标准 HID 事件的代理;该实现不对事件的内容或类型做任何假设,只是将其传递到输入系统,从而使 AOAv2 配件可以充当任何 HID 设备(鼠标、键盘、游戏控制器等)。您可以使用 HID 支持来提供基本功能(例如媒体坞上的播放/暂停按钮),或高级功能(例如带有鼠标和全尺寸 QWERTY 键盘的扩展坞)。

AOAv2 添加了新的 USB 控制请求,允许配件充当 Android 设备的一个或多个 HID 输入设备。HID 支持完全通过端点零上的控制请求来处理,因此不需要新的 USB 接口。四个新的控制请求是

  • ACCESSORY_REGISTER_HID 向 Android 设备注册新的 HID 设备。配件提供一个 ID,用于标识其他三个调用的人机接口设备。此 ID 有效,直到 USB 断开连接或配件发送 ACCESSORY_UNREGISTER_HID 以注销 HID 设备为止。
  • ACCESSORY_UNREGISTER_HID 注销先前使用 ACCESSORY_REGISTER_HID 注册的 HID 设备。
  • ACCESSORY_SET_HID_REPORT_DESC 将 HID 设备的报告描述符发送到 Android 设备。此请求用于描述 HID 设备的功能,并且必须在向 Android 设备报告任何 HID 事件之前发送。如果报告描述符大于端点零的最大数据包大小,则会发送多个 ACCESSORY_SET_HID_REPORT_DESC 命令来传输整个描述符。
  • ACCESSORY_SEND_HID_EVENT 将输入事件从配件发送到 Android 设备。

新控制请求的代码定义如下

/* Control request for registering a HID device.
 * Upon registering, a unique ID is sent by the accessory in the
 * value parameter. This ID will be used for future commands for
 * the device
 *
 *  requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
 *  request:        ACCESSORY_REGISTER_HID_DEVICE
 *  value:          Accessory assigned ID for the HID device
 *  index:          total length of the HID report descriptor
 *  data            none
 */
#define ACCESSORY_REGISTER_HID         54

/* Control request for unregistering a HID device.
 *
 *  requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
 *  request:        ACCESSORY_REGISTER_HID
 *  value:          Accessory assigned ID for the HID device
 *  index:          0
 *  data            none
 */
#define ACCESSORY_UNREGISTER_HID         55

/* Control request for sending the HID report descriptor.
 * If the HID descriptor is longer than the endpoint zero max packet size,
 * the descriptor will be sent in multiple ACCESSORY_SET_HID_REPORT_DESC
 * commands. The data for the descriptor must be sent sequentially
 * if multiple packets are needed.
 *
 *  requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
 *  request:        ACCESSORY_SET_HID_REPORT_DESC
 *  value:          Accessory assigned ID for the HID device
 *  index:          offset of data in descriptor
 *                      (needed when HID descriptor is too big for one packet)
 *  data            the HID report descriptor
 */
#define ACCESSORY_SET_HID_REPORT_DESC         56

/* Control request for sending HID events.
 *
 *  requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
 *  request:        ACCESSORY_SEND_HID_EVENT
 *  value:          Accessory assigned ID for the HID device
 *  index:          0
 *  data            the HID report for the event
 */
#define ACCESSORY_SEND_HID_EVENT         57

与 AOAv1 的互操作性

原始协议(AOAv1)提供对 Android 应用的支持,以通过 USB 直接与 USB 主机(配件)通信。AOAv2 继续提供此支持,并添加了新功能,以允许配件与 Android 操作系统本身(特别是音频和输入系统)通信。AOAv2 的设计使得构建既使用新的音频和 HID 支持又使用原始功能集的配件成为可能。只需将新功能与原始功能结合使用即可。

在没有 Android 应用的情况下连接 AOAv2

您可以设计一种使用音频和 HID 支持但不与 Android 设备上的应用通信的配件(例如音频坞站)。对于这些配件,用户无需接收对话框提示,以查找新连接的配件并将其与可以与之通信的 Android 应用关联。

要在配件连接后禁止显示此类对话框,配件可以选择不向 Android 设备发送制造商和型号名称。当未向 Android 设备提供这些字符串时

  • 系统不会尝试查找与配件通信的应用。
  • 在设备进入配件模式后,配件 USB 接口不会出现在 Android 设备 USB 配置中。