From 62d9ff102949d6a3d298599b854d2080d73c80c4 Mon Sep 17 00:00:00 2001 From: Patrick Burns Date: Thu, 28 May 2026 19:40:56 -0500 Subject: [PATCH] AudioDeviceSpinnerAdapter: always expose raw USB audio path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop deduping the UsbManager-discovered USB audio entry against AudioManager's listing. On automotive Android skins (car-dash head units) the AudioManager-listed entry routes via AudioRecord + setPreferredDevice(), which the in-car audio policy silently overrides back to the built-in mic — so the waterfall keeps showing cabin noise no matter what the user picks. The raw USB path opens the interface directly via UsbManager and bypasses that policy entirely. Both entries are now shown side-by-side; the raw one is labeled "(USB direct)" so users on broken HALs know which to pick. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../ft8cn/ui/AudioDeviceSpinnerAdapter.java | 32 ++++--------------- .../com/bg7yoz/ft8cn/wave/UsbAudioDevice.java | 2 +- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/ft8cn/app/src/main/java/com/bg7yoz/ft8cn/ui/AudioDeviceSpinnerAdapter.java b/ft8cn/app/src/main/java/com/bg7yoz/ft8cn/ui/AudioDeviceSpinnerAdapter.java index 03ae6db5..77aeb23b 100644 --- a/ft8cn/app/src/main/java/com/bg7yoz/ft8cn/ui/AudioDeviceSpinnerAdapter.java +++ b/ft8cn/app/src/main/java/com/bg7yoz/ft8cn/ui/AudioDeviceSpinnerAdapter.java @@ -57,37 +57,19 @@ public void refreshDevices() { } } - // 2. Scan for USB Audio Class devices not recognized by AudioManager + // 2. Scan for USB Audio Class devices and list them as a separate "direct" entry. + // We intentionally do NOT dedupe against AudioManager-listed USB devices: on + // automotive Android skins the AudioManager entry routes through AudioRecord + + // setPreferredDevice(), which the in-car audio policy silently overrides back to + // the built-in mic. The raw USB path bypasses that policy entirely, so users on + // those systems need both entries visible and labeled distinctly. try { List usbDevices = UsbAudioDevice.findUsbAudioDevices(mContext); for (UsbAudioDevice.UsbAudioDeviceInfo usbDev : usbDevices) { boolean matchesDirection = isInput ? usbDev.hasInput : usbDev.hasOutput; if (!matchesDirection) continue; - - // Check if this device is already listed by AudioManager (by matching type) - boolean alreadyListed = false; - for (AudioDeviceInfo adi : audioDeviceList) { - if (adi.getType() == AudioDeviceInfo.TYPE_USB_DEVICE - || adi.getType() == AudioDeviceInfo.TYPE_USB_ACCESSORY - || adi.getType() == AudioDeviceInfo.TYPE_USB_HEADSET) { - // AudioManager already has a USB audio device — might be the same one - // Compare product name if available - String adName = adi.getProductName() != null - ? adi.getProductName().toString() : ""; - String usbName = usbDev.device.getProductName() != null - ? usbDev.device.getProductName() : ""; - if (!adName.isEmpty() && !usbName.isEmpty() - && adName.equals(usbName)) { - alreadyListed = true; - break; - } - } - } - - if (!alreadyListed) { - usbAudioDeviceList.add(usbDev); - } + usbAudioDeviceList.add(usbDev); } } catch (Exception e) { // Ignore USB enumeration errors diff --git a/ft8cn/app/src/main/java/com/bg7yoz/ft8cn/wave/UsbAudioDevice.java b/ft8cn/app/src/main/java/com/bg7yoz/ft8cn/wave/UsbAudioDevice.java index 76994e6a..83652103 100644 --- a/ft8cn/app/src/main/java/com/bg7yoz/ft8cn/wave/UsbAudioDevice.java +++ b/ft8cn/app/src/main/java/com/bg7yoz/ft8cn/wave/UsbAudioDevice.java @@ -573,7 +573,7 @@ public String getDisplayName() { name = String.format("USB Audio [%04X:%04X]", device.getVendorId(), device.getProductId()); } - return name + " (USB)"; + return name + " (USB direct)"; } } }