Forum Discussion

indegym's avatar
indegym
Honored Guest
1 month ago

USB: Input-Only Microphone Should Not Mute Built-in Speakers, Technical Analysis & Proposed Fix

When any USB-C audio device is connected to Quest 3 — even an input-only microphone with no speaker/DAC capability — Meta Horizon OS routes ALL audio (both input AND output) to the USB-C port and mutes the built-in headset speakers. This contradicts standard Android AOSP behavior and blocks legitimate professional use cases.

The Problem

Many professional VR applications need external microphone input (for speech recognition, recording, or communication) while maintaining audio output through the built-in speakers. Examples include therapeutic VR, education, accessibility, content creation, live streaming, and enterprise training.

We purchased a USB-C gooseneck microphone that is input-only (no speaker, no DAC, isSink=false). On standard Android devices, connecting this mic only affects audio input — speakers continue working. On Quest 3, the built-in speakers are immediately muted, even though the USB device has zero output capability.

What We've Tried (Everything Fails)

1. usb_audio_automatic_routing_disabled=1 (ADB): Does not selectively disable routing — prevents the USB device from registering with AudioService entirely (UsbAlsaManager.selectAlsaDevice() returns early), so setPreferredDevice() cannot find the mic at all.

2. AudioManager.setCommunicationDevice(builtInSpeaker) (API 31+): Only affects USAGE_VOICE_COMMUNICATION streams, not media/game audio. Unity uses FMOD → AAudio (native C layer), which routes through USAGE_GAME — unaffected.

3. AudioTrack.setPreferredDevice(builtInSpeaker): Would require intercepting the engine's internal audio output at the native layer — not feasible, and Quest 3's audio HAL may override it anyway.

4. "External Microphone" toggle (Settings > Advanced, v64+): Enables USB mic recognition only. Does NOT provide split input/output routing.

5. Input-only USB mic (isSource=true, isSink=false): Expected AOSP-compliant behavior (only input rerouted). Built-in speakers are still muted.

Root Cause Analysis — AOSP vs. Meta Horizon OS

In upstream AOSP, UsbAlsaManager.java checks actual device capabilities via USB Audio Class descriptors:

// AOSP: frameworks/base/services/usb/java/com/android/server/usb/UsbAlsaManager.java

private void selectAlsaDevice(UsbAlsaDevice alsaDevice) {

UsbDescriptorParser parser = alsaDevice.getParser();

if (parser.hasOutput()) {

// Only register OUTPUT if USB device has playback capability alsaDevice.startOutput();

}

if (parser.hasInput()) {

// Only register INPUT if USB device has capture capability

alsaDevice.startInput();

}

}

The AOSP AudioPolicyManager then only reroutes streams matching registered capabilities. An input-only device never triggers checkOutputsForDevice(), so speakers remain active.

Meta's Horizon OS overrides this separation. The most likely cause:

// Probable Meta override (simplified):

void AudioPolicyManager::onNewUsbDevice(audio_devices_t device) {

// Does not check if device has output capability

setDeviceConnectionState(AUDIO_DEVICE_OUT_SPEAKER, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);

setDeviceConnectionState(AUDIO_DEVICE_OUT_USB_DEVICE, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);

}

Proposed Fix

Check the USB device's Audio Class descriptors before modifying output routing:

void AudioPolicyManager::onNewUsbDevice(const sp<UsbAlsaDevice>& device) {

if (device->hasCapture()) {

setDeviceConnectionState(AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);

}

if (device->hasPlayback()) {

// Route output to USB ONLY if device has output capability

setDeviceConnectionState(AUDIO_DEVICE_OUT_USB_DEVICE, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);

}

// If !hasPlayback(): leave built-in speaker routing UNCHANGED

}

This is a single conditional check in the audio policy layer. It requires zero UI changes and simply aligns Quest 3 with upstream AOSP behavior.

Additional Solutions (If a Broader Fix is Planned)

- User-facing setting: Add "Audio Output" under Settings > Sound with options "Headset Speakers" / "USB-C" / "Automatic", independent of input routing.

- Developer API: Allow applications to call setPreferredDevice() with routing respected for all audio usages (not just USAGE_VOICE_COMMUNICATION).

Impact

The Quest 3 hardware is fully capable — speakers and USB operate on independent audio paths. This is purely a software routing policy that could be resolved with a minimal code change. The fix would unblock every developer building applications that need external audio input while maintaining speaker output.

Happy to provide dumpsys audio output or USB device descriptors to help diagnose the exact policy override.

Related: A similar request was posted on the archived forum: "Request for Enhanced Audio Routing Controls with External Microphones on Meta Quest" (jrb-vr, October 2024) — which received no response.

1 Reply

  • steve_40's avatar
    steve_40
    Honored Visionary

    Meta has shifted most of its feedback channels into private systems - such as in‑app reporting, developer programs, and internal analytics - rather than public forums where users can share and upvote ideas. This site used to have an Ideas Board, but Meta shut it down months ago. Posting here is unlikely to get much attention. You'll have better luck submitting feedback through the headset via Quick Settings > Report problem, or by opening a ticket in the Developer Feedback Center.

→ Find helpful resources to begin your development journey in Getting Started

→ Get the latest information about HorizonOS development in News & Announcements.

→ Access Start program mentor videos and share knowledge, tutorials, and videos in Community Resources.

→ Get support or provide help in Questions & Discussions.

→ Show off your work in What I’m Building to get feedback and find playtesters.

→ Looking for documentation?  Developer Docs

→ Looking for account support?  Support Center

→ Looking for the previous forum?  Forum Archive

→ Looking to join the Start program? Apply here.

 

Recent Discussions