模拟器 USB 透传模式集成指南

本文介绍如何将两个外围设备(蓝牙和 Wi-Fi)连接到 AAOS 模拟器。在此过程中,特定于驱动程序支持的三个方面是关键:

  • 客户机内核
  • 客户机 Android
  • Linux 主机

首先,您要在客户机内核中编译并启用相关的 USB 驱动程序。 接下来,客户机 Android 必须选择正确的 HAL 和服务来启动驱动程序。最后,Linux 主机必须访问 USB 驱动程序,然后将其传输到 QEMU

已测试的加密狗

以下加密狗已经过测试:

其他加密狗可能也适用,但并未经过测试。

原生 USB 支持

QEMU 附带将 USB 传递到模拟器的选项。AAOS 系统映像已经处理了一部连接的手机。如需了解详情,请参阅 Android 开放配件 (AOA)

由于手机会在建立 AOA 连接后更改 vendorIDproductID 的值,因此新的 USB 接口(以及原始 USB 接口)会在手机处于 AOA 模式时检测到该设备。

如需确定 AOA 模式前后的 vendorIDproductID 的值,请使用 lsusb

# Note Vendor ID and Product ID of your phone
$ lsusb
Bus 001 Device 079: ID 18d1:4ee1 Google Inc. Nexus/Pixel Device (MTP)
# Start up an emulator!
$ ./emulator @AVD_NAME -no-snapshot -qemu -device usb-ehci,id=ehci -device usb-host,bus=ehci.0,vendorid=0x18d1,productid=0x4ee1 -device usb-host,bus=ehci.0,vendorid=0x18d1,productid=0x2d00

或者,也可将物理端口传递到 QEMU:

# First plug something into the interested USB port and note the Bus and Device number.
$ lsusb
Bus 001 Device 012: ID 0bda:c820 Realtek Semiconductor Corp. 802.11ac NIC
# Now figure out where the Port number is.
$ lsusb -t
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/12p, 480M
    |__ Port 4: Dev 12, If 1, Class=Wireless, Driver=btusb, 480M
    |__ Port 4: Dev 12, If 2, Class=Vendor Specific Class, Driver=, 480M
    |__ Port 4: Dev 12, If 0, Class=Wireless, Driver=btusb, 480M
# Launch the emulator
 ./emulator @AVD_NAME -no-snapshot -qemu -device usb-ehci,id=ehci -device usb-host,bus=ehci.0,hostbus=1,hostport=4
# Now, whatever you plug into the emulator, USB passthrough will happen on the fly.

AAOS 系统映像识别到手机,将其置于 AOA 模式,并在 AOA 模式运行时再次识别手机。

如需支持 USB 透传模式,请确认您使用的是模拟器 30.5.0

# Check for the emulator version
$ emulator --version

模拟器 30.5.0 包含 libusb 升级以及针对华硕加密狗支持处理速度兼容性问题的临时权宜解决方法:

蓝牙支持

为了支持蓝牙透传模式,Google 已测试 ASUS USB-BT400 USB 适配器 USBBT400 和 Auscomer 出产的 USB Wi-Fi 蓝牙适配器。

首先,您需要为加密狗添加内核支持。如需了解 Android 蓝牙堆栈,请参阅蓝牙。对于 HIDL,模拟器使用模拟实现。因此,可以将其切换为原生 Linux 实现。

客户机内核

如需支持 USB 蓝牙加密狗,请执行以下操作:

  1. 将缺少的 btusb.ko 添加到您的内核中:

    --- a/goldfish_defconfig.fragment
    +++ b/goldfish_defconfig.fragment
    @@ -1,6 +1,7 @@
     # CONFIG_CRYPTO_DEV_VIRTIO is not set
     CONFIG_BLK_DEV_MD=m
    +CONFIG_BT_HCIBTUSB=m
     CONFIG_CPUFREQ_DUMMY=m
    

客户机 Android

  1. vendor.mk 文件中,添加 Linux 原生 HIDL 和多项权限:

    PRODUCT_PACKAGES += \
        android.hardware.bluetooth@1.1-service.btlinux
    PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.hardware.usb.host.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.usb.host.xml
    
  2. 创建单向路径属性来断开 HIDL,以便使用 Linux 原生 HIDL 实现:

    selinux/common/domain.te
    
    get_prop(domain, qemu_prop)
    +get_prop(domain, vendor_build_prop)
    
    selinux/common/property_contexts
    
    qemu.cmdline            u:object_r:qemu_cmdline:s0
    +qemu.preferred.bt.service u:object_r:qemu_prop:s0
    
  3. 每当属性 qemu.preferred.bt.service 设置为 passthrough 时,您便会断开 HIDL 实现:

    service btlinux-1.1 /vendor/bin/hw/android.hardware.bluetooth@1.1-service.btlinux
      class hal
      user bluetooth
      group bluetooth net_admin net_bt_admin
      capabilities NET_ADMIN NET_RAW SYS_NICE
      disabled
    
    on property:qemu.preferred.bt.service=passthrough
      stop vendor.bluetooth-1-1
      start btlinux-1.1
    
  4. 添加蓝牙配置文件以获取如同使用真实 USB 设备一样的完整功能:

    hal/bluetooth/bdroid_buildcfg.h
    
    #ifndef _BDROID_BUILDCFG_H
    #define _BDROID_BUILDCFG_H
    #define BTM_DEF_LOCAL_NAME "gCar Emulator"
    #define BTA_AV_SINK_INCLUDED TRUE
    /* Handsfree device */
    #define BTA_DM_COD {0x26, 0x04, 0x08}
    #endif
    
  5. 修改 BoardConfig.mk 文件以确定配置文件的保存位置:

    BoardConfig.mk
    
    # Bluetooth
    BOARD_HAVE_BLUETOOTH := true
    BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR := vendor/auto/embedded/hal/bluetooth
    

Linux 主机

在 Linux 主机上:

  1. 更新 udev 设置,以允许用户进程(如 QEMU)具有读取/写入权限:

    $ echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="0b05", ATTRS{idProduct}=="17cb", MODE="0666", GROUP="plugdev"' | sudo tee /etc/udev/rules.d/99-mynew.rules >/dev/null
    $ sudo udevadm control --reload
    $ sudo udevadm trigger
    
  2. 如需运行模拟器,请设置以下命令行参数:

    # Start up an emulator!
    $ ./emulator @AVD_NAME -no-snapshot -prop qemu.preferred.bt.service=passthrough -qemu -device usb-ehci,id=ehci -device usb-host,bus=ehci.0,vendorid=0x0b05,productid=0x17cb
    # Start Bluetooth Passthrough
    

Wi-Fi 支持

为了验证双蓝牙和 Wi-Fi 支持,Google 使用 USB Wi-Fi 蓝牙适配器进行了测试。

客户机内核

这款 USB 加密狗使用 RTL8821CU 芯片,Mainline 内核上游尚不支持此芯片。您可以在 8821cu 中找到新开发的内核模块。

然后,在更改列表 1575108 中,外部内核模块已集成到 goldfish 内核源代码中,以便对该源代码进行编译。

最后,系统虽然会编译该内核模块,但会导致一些 CFI 崩溃。您需要手动修补代码,以解决此问题。如需了解详情,请参阅 Android 内核中的控制流完整性

先启用 CONFIG_CFI_PERMISSIVE 并继续调试堆栈其余部分可能会有帮助:

--- a/goldfish_defconfig.fragment
+++ b/goldfish_defconfig.fragment
@@ -1,6 +1,7 @@
 CONFIG_CFI_CLANG=m
+CONFIG_CFI_PERMISSIVE=m

在任何情况下,都请打开更改列表 1575109,查看针对 CFI 崩溃的正确修复方法。

客户机 Android

如需详细了解 Wi-Fi 堆栈,请参阅 Wi-Fi 概览。模拟器附带相关设置以使 Wi-Fi 网络正常运行。

Linux 主机

在 Linux 主机中,您必须更新 udev 设置,以允许用户进程(例如 QEMU)获得读取/写入权限。

# /lib/udev/rules.d/40-usb_modeswitch.rules
$ ATTR{idVendor}=="0bda", ATTR{idProduct}=="1a2b", RUN+="usb_modeswitch '/%k'"
$ echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="c820", MODE="0666", GROUP="plugdev"' | sudo tee /etc/udev/rules.d/99-mynew2.rules >/dev/null
$ sudo udevadm control --reload
$ sudo udevadm trigger

如需将加密狗传递到 QEMU,请执行以下操作:

# Start up an emulator!
$ ./emulator @AVD_NAME -no-snapshot -qemu -device usb-ehci,id=ehci -device usb-host,bus=ehci.0,vendorid=0x0bda,productid=0xc820

移植更改列表

移植以下更改列表: