AVAudioSession blocks 20–36s on A2DP→HFP switch while another AudioUnit is rendering (iOS 27.0.1, AirPods Spatial Audio)

While an AVAudioPlayer/AudioUnit is rendering to AirPods over A2DP with system Spatial Audio + Head Tracking enabled, switching the shared AVAudioSession to playAndRecord + voiceChat (A2DP → HFP) blocks the main thread for tens of seconds on synchronous AVAudioSession APIs (setCategory / setMode / channel getters / setPreferred*). iOS hang detection reports a Severe Hang of 41.02 s. Stopping playback and deactivating the session before the identical switch completes in ~87 ms.

Feedback: FB25324099

Environment

  • iPhone 15 Pro (iPhone16,1), iOS 27.0.1 (24A446)
  • AirPods worn; Spatial Audio + Head Tracking on
  • AVFoundation-only repro (no third-party SDK): https://github.com/shinobuwz/ios27-spatial-audio-stall-repro
  • Info.plist: LSApplicationCategoryType = public.app-category.games, LSSupportsGameMode = YES; does NOT set AVGameBypassSystemSpatialAudio (those two keys are required for system Spatial Audio on this path)

Steps

  1. Wear AirPods with Spatial Audio + Head Tracking enabled
  2. Launch the repro app; allow mic (or use auto-repro)
  3. Play 440 Hz (BluetoothA2DP, spatial=1)
  4. After ~2 s, run Repro: keep playing and switch to PlayAndRecord + VoiceChat
  5. Compare with Control: stop playback + setActive:NO, then the same switch

Expected: each call returns in ms; whole reconfiguration ≪ 50 ms
Actual (cold launches): configuration total 20.8–28.9 s (options=13); with options=237 ≈ 36.2 s; first input buffer ~40–58 s from switch start. Control ≈ 87 ms.

Evidence in the repo: docs/MEASUREMENTS-2026-10-26.md, evidence/*.log, hangs.xml, main-thread stacks in avas::client::SessionCore (sync XPC to the audio daemon). Even inputNumberOfChannels / outputNumberOfChannels getters stall for seconds.

Question: Is this a known regression on iOS 27? Any workaround besides stopping all rendering AudioUnits before the HFP switch? Happy to attach sysdiagnose / Instruments / screen recording if useful.