Guide d'intégration de l'émulateur USB Passthrough

Cet article décrit comment connecter deux périphériques (Bluetooth et Wi-Fi) à l'émulateur AAOS. Dans cette démarche, trois domaines spécifiques à l’accompagnement des conducteurs sont essentiels :

  • Noyau invité
  • Invité Android
  • Hôte Linux

Tout d'abord, vous compilez et activez les pilotes USB appropriés dans le noyau invité. Ensuite, Guest Android doit sélectionner le HAL et les services appropriés pour afficher les pilotes. Enfin, l'hôte Linux doit accéder au pilote USB puis le transférer vers QEMU .

Clés testées

Les dongles suivants ont été testés :

D'autres dongles peuvent fonctionner, mais aucun autre n'a été testé.

Prise en charge USB native

QEMU est livré avec des options pour transmettre l'USB à l'émulateur. L'image système AAOS gère déjà un téléphone connecté. Pour plus de détails, consultez Android Open Accessoire (AOA) .

Étant donné que le téléphone modifie les valeurs de vendorID et productID lors de l'établissement d'une connexion AOA, la nouvelle interface USB (ainsi que l'interface USB d'origine) voit l'appareil lorsque le téléphone est en mode AOA.

Pour déterminer les valeurs de vendorID et productID avant et après le mode AOA, utilisez 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

Vous pouvez également transmettre le port physique à 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.

L'image système AAOS reconnaît le téléphone, le met en mode AOA et le reconnaît à nouveau lorsque le mode AOA est en cours d'exécution.

Pour prendre en charge le relais USB, confirmez que vous utilisez Emulator 30.5.0 :

# Check for the emulator version
$ emulator --version

L'émulateur 30.5.0 inclut une mise à niveau libusb et une solution de contournement temporaire pour résoudre la compatibilité de vitesse de la prise en charge du dongle ASUS :

Prise en charge Bluetooth

Pour prendre en charge le relais Bluetooth, Google a testé l'adaptateur USB ASUS USB-BT400 USBBT400 et l'adaptateur USB Wi-Fi Bluetooth d'Auscomer.

Tout d'abord, vous devez ajouter la prise en charge du noyau pour le dongle. Pour comprendre la pile Bluetooth Android, consultez Bluetooth . Pour HIDL, l'émulateur utilise une implémentation simulée. Par conséquent, remplacez cela par une implémentation Linux native.

Noyau invité

Pour prendre en charge un dongle USB Bluetooth :

  1. Ajoutez le btusb.ko manquant à votre noyau :

    --- 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
    

Invité Android

  1. Dans le fichier vendor.mk , incluez le HIDL natif Linux et plusieurs autorisations :

    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. Créez une propriété de chemin unidirectionnel pour désactiver le HIDL de manière à ce qu'il utilise une implémentation HIDL native Linux :

    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. Chaque fois qu'une propriété qemu.preferred.bt.service est définie sur passthrough , vous désactivez l'implémentation 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. Ajoutez un fichier de configuration Bluetooth pour obtenir toutes les fonctionnalités, comme sur un vrai périphérique 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. Modifiez le fichier BoardConfig.mk pour déterminer où le fichier de configuration est enregistré :

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

Hôte Linux

Sur l'hôte Linux :

  1. Mettez à jour les paramètres udev pour permettre au processus utilisateur (par exemple QEMU) d'avoir des autorisations de lecture/écriture :

    $ 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. Pour exécuter l'émulateur, définissez les paramètres de ligne de commande suivants :

    # 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
    

Prise en charge Wi-Fi

Pour valider le double Bluetooth et Wi-Fi, Google a testé avec l'adaptateur USB Wi-Fi Bluetooth.

Noyau invité

Ce dongle USB particulier utilise la puce RTL8821CU, que le noyau principal en amont ne prend pas encore en charge. Vous pouvez trouver un module de noyau nouvellement développé sur 8821cu .

Ensuite, dans la liste des modifications 1575108 , les modules externes du noyau ont été intégrés dans la source du noyau Goldfish pour le compiler.

Finalement, le module noyau compile mais avec quelques crashs de CFI. Vous devez corriger le code manuellement pour résoudre ce problème. Pour plus de détails, consultez Control Flow Integrity dans le noyau Android .

Il peut être utile d'activer CONFIG_CFI_PERMISSIVE et de commencer par déboguer le reste de la pile :

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

Dans tous les cas, accédez à la liste de modifications 1575109 pour voir le correctif approprié aux plantages de CFI.

Invité Android

Pour en savoir plus sur la pile Wi-Fi, consultez Présentation du Wi-Fi . L'émulateur est livré avec les paramètres permettant de faire fonctionner le Wi-Fi.

Hôte Linux

Sur l'hôte Linux, vous devez mettre à jour les paramètres udev pour permettre au processus utilisateur (par exemple, QEMU) d'avoir des autorisations de lecture/écriture.

# /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

Pour transmettre le dongle à 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

Listes de modifications de ports

Portez les listes de modifications suivantes :