この記事では、2 台の周辺機器(Bluetooth と Wi-Fi)を AAOS エミュレータに接続する方法について説明します。このプロセスでは、ドライバ サポートに固有の 3 つの重要な領域があります。
- ゲストカーネル
- ゲスト Android
- Linux ホスト
まず、ゲストカーネルで関連する USB ドライバをコンパイルして有効にします。 次にゲスト Android が、ドライバを起動する適切な HAL とサービスを選択します。最後に、Linux ホストが USB ドライバにアクセスして、QEMU に転送します。
テスト済みのドングル
以下のドングルがテストされました。
- ASUS USB-BT400 USB アダプター USBBT400
- Auscomer の USB Wi-Fi Bluetooth アダプター
他のドングルも動作する可能性がありますが、テストは行われていません。
ネイティブ USB のサポート
QEMU には、USB をエミュレータに渡すオプションが用意されています。AAOS システム イメージは、接続されているスマートフォンをすでに処理しています。詳細については、Android Open Accessory(AOA)をご覧ください。
スマートフォンでは AOA 接続の確立時に vendorID
と productID
の値が変更されるため、スマートフォンが AOA モードのときに新しい USB インターフェース(および元の USB インターフェース)でデバイスを確認できます。
AOA モードの前後に vendorID
と productID
の値を判別するには、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
のアップグレードと、ASUS ドングルに対応する速度を確保するための一時的な回避策が含まれています。
- https://android-review.googlesource.com/c/platform/external/qemu/+/1573247
- https://android-review.googlesource.com/c/platform/external/qemu/+/1580924
- https://android-review.googlesource.com/c/platform/external/libusb/+/1580923
Bluetooth のサポート
Bluetooth パススルーをサポートするために、Google は ASUS USB-BT400 USB アダプター USBBT400 と Auscomer の USB Wi-Fi Bluetooth アダプターをテストしました。
まず、ドングルのカーネル サポートを追加する必要があります。Android Bluetooth スタックの詳細については、Bluetooth をご覧ください。HIDL の場合、エミュレータはシミュレートされた実装を使用します。これをネイティブ Linux の実装に切り替えます。
ゲストカーネル
USB Bluetooth ドングルをサポートする方法:
欠落している
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
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
Linux ネイティブ HIDL の実装を使用するように 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
プロパティ
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
Bluetooth 構成ファイルを追加して、実際の 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
BoardConfig.mk
ファイルを変更して、構成ファイルの保存場所を決定します。BoardConfig.mk # Bluetooth BOARD_HAVE_BLUETOOTH := true BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR := vendor/auto/embedded/hal/bluetooth
Linux ホスト
Linux ホストで次のようにします。
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
エミュレータを実行するには、次のコマンドライン パラメータを設定します。
# 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
WiFi のサポート
デュアル Bluetooth と Wi-Fi を検証するため、Google は USB WiFi Bluetooth アダプターでテストしました。
ゲストカーネル
この USB ドングルは、アップストリームのメインライン カーネルではまだサポートされていない、RTL8821CU チップを使用します。新たに開発されたカーネル モジュールは 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 ホストでユーザー プロセス(QEMU など)に読み取り / 書き込み権限を付与するには、udev
設定を更新する必要があります。
# /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
変更リストの移行
次の変更リストを移行します。