Android 开放配件协议 1.0

Android USB 配件必须遵循 Android 开放配件 (AOA) 协议,该协议规定了配件如何检测 Android 设备并与其建立通信。配件应执行以下步骤:

  1. 等待设备连接并对其进行检测。
  2. 确定设备是否支持配件模式。
  3. 尝试以配件模式启动设备(如需要)。
  4. 如果设备支持 AOA,则与该设备建立通信。

以下部分介绍了如何执行上述步骤。

等待设备连接并对其进行检测

配件应该不间断地检查是否连接了 Android 设备。设备成功连接后,配件应该确定设备是否支持配件模式。

确定是否支持配件模式

当 Android 设备成功连接后,它可能处于以下三种状态之一:

  • 支持 Android 配件模式,并且已处于配件模式。
  • 支持 Android 配件模式,但是未处于配件模式。
  • 不支持 Android 配件模式。

在初次连接时,配件应该检查所连接设备的 USB 设备描述符的版本、供应商 ID 和产品 ID。供应商 ID 应与 Google 的 ID (0x18D1) 相符。如果设备已经处于配件模式,产品 ID 应为 0x2D000x2D01,配件可以使用自己的通信协议通过批量传输端点与设备建立通信(不需要以配件模式启动设备)。

注意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。

配件应尝试以配件模式启动设备,以确定设备是否支持该模式:

  1. 发送 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)
    
  2. 如果设备返回所支持的协议版本,则向设备发送含标识字符串信息的控制请求。该信息让设备可以确定适合配件的应用(如果没有适合配件的应用,则向用户呈现一个网址)。该控制请求为端点 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
    
  3. 发送控制请求,要求设备以配件模式启动。该控制请求为端点 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,然后使用端点进行通信。