Przewodnik integracji emulatora USB passthrough

Na tej stronie opisano sposób podłączenia dwóch urządzeń peryferyjnych (Bluetooth i Wi-Fi) do emulatora AAOS. W tym procesie kluczowe są trzy obszary specyficzne dla wsparcia kierowców:

  • Jądro gościa
  • Gościnny Android
  • Host Linuksa

Najpierw kompilujesz i włączasz odpowiednie sterowniki USB w jądrze gościa. Następnie system Guest Android musi wybrać odpowiednią warstwę HAL i usługi, aby wyświetlić sterowniki. Na koniec host Linux musi uzyskać dostęp do sterownika USB, a następnie przesłać go do QEMU .

Testowane klucze

Przetestowano następujące klucze sprzętowe:

Inne klucze sprzętowe mogą działać, jednak żadne inne nie były testowane.

Natywna obsługa USB

QEMU zawiera opcje przekazywania USB do emulatora. Obraz systemu AAOS obsługuje już podłączony telefon. Aby uzyskać szczegółowe informacje, zobacz akcesorium Android Open (AOA) .

Ponieważ telefon zmienia wartości vendorID i productID po nawiązaniu połączenia AOA, nowy interfejs USB (jak również oryginalny interfejs USB) widzi urządzenie, gdy telefon znajduje się w trybie AOA.

Aby określić wartości vendorID i productID przed i po trybie AOA, użyj 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

Alternatywnie przekaż port fizyczny do 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.

Obraz systemu AAOS rozpoznaje telefon, przełącza go w tryb AOA i rozpoznaje ponownie, gdy tryb AOA jest uruchomiony.

Aby obsługiwać przekazywanie USB, potwierdź, że używasz emulatora 30.5.0 :

# Check for the emulator version
$ emulator --version

Emulator 30.5.0 zawiera aktualizację libusb i tymczasowe obejście problemu zgodności szybkości obsługi klucza sprzętowego ASUS:

Obsługa Bluetootha

Aby obsługiwać transmisję Bluetooth, Google przetestowało adapter USB ASUS USB-BT400 USBBT400 i adapter USB Wi-Fi Bluetooth firmy Auscomer.

Najpierw musisz dodać obsługę jądra dla klucza sprzętowego. Aby poznać stos Bluetooth w systemie Android, zobacz Bluetooth . W przypadku HIDL emulator wykorzystuje symulowaną implementację. Dlatego zmień to na natywną implementację systemu Linux.

Jądro gościa

Aby obsługiwać klucz USB Bluetooth:

  1. Dodaj brakujący btusb.ko do swojego jądra:

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

Gościnny Android

  1. W pliku vendor.mk dołącz natywny język HIDL dla systemu Linux i kilka uprawnień:

    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. Utwórz właściwość ścieżki jednokierunkowej, aby wyłączyć HIDL w taki sposób, aby korzystał z natywnej implementacji HIDL dla systemu 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. Ilekroć właściwość qemu.preferred.bt.service jest ustawiona na passthrough , wyłączysz implementację 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. Dodaj plik konfiguracyjny Bluetooth, aby uzyskać pełne możliwości, na przykład na prawdziwym urządzeniu 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. Zmodyfikuj plik BoardConfig.mk , aby określić, gdzie zapisany jest plik konfiguracyjny:

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

Host Linuksa

Na hoście z Linuksem:

  1. Zaktualizuj ustawienia udev , aby umożliwić procesowi użytkownika (na przykład QEMU) posiadanie uprawnień do odczytu/zapisu:

    $ 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. Aby uruchomić emulator, ustaw następujące parametry wiersza poleceń:

    # 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
    

Obsługa Wi-Fi

Aby sprawdzić działanie podwójnego Bluetooth i Wi-Fi, Google przetestowało adapter USB Wi-Fi Bluetooth.

Jądro gościa

Ten konkretny klucz sprzętowy USB wykorzystuje układ RTL8821CU, którego główne jądro systemu jeszcze nie obsługuje. Nowo opracowany moduł jądra można znaleźć pod adresem 8821cu .

Następnie na liście zmian 1575108 zewnętrzne moduły jądra zostały zintegrowane ze źródłem jądra złotej rybki, aby je skompilować.

Wreszcie moduł jądra kompiluje się, ale z pewnymi awariami CFI. Aby to naprawić, musisz ręcznie załatać kod. Aby uzyskać szczegółowe informacje, zobacz Integralność przepływu sterowania w jądrze Androida .

Pomocne może być włączenie CONFIG_CFI_PERMISSIVE i przejście do przodu, najpierw debugując resztę stosu:

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

W każdym razie przejdź do listy zmian 1575109, aby zobaczyć właściwą poprawkę dotyczącą awarii CFI.

Gościnny Android

Aby dowiedzieć się więcej na temat stosu Wi-Fi, zobacz Omówienie Wi-Fi . Emulator zawiera ustawienia umożliwiające działanie Wi-Fi.

Host Linuksa

Na hoście z systemem Linux musisz zaktualizować ustawienia udev , aby umożliwić procesowi użytkownika (na przykład QEMU) posiadanie uprawnień do odczytu/zapisu.

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

Aby przekazać klucz sprzętowy do 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

Listy zmian portów

Przenieś następujące listy zmian: