feat: configure the iOS audio session natively in the default path#434
Merged
Conversation
setupIOSAudioManagement's default path now pushes the audio-session policy to native via AudioDeviceModule.setAutomaticAudioSessionConfiguration() instead of registering willEnable/didDisable JS handlers, so the audio engine's worker thread no longer round-trips to JS in the stock path. That round trip could stall or deadlock engine operations when the JS thread was itself blocked in a synchronous bridge call. Custom configurations (onConfigureNativeAudio) keep the JS handler path, still bounded by the native wait timeout. Repeated setup calls and switches between the default and custom paths are safe: each setup supersedes the previous one by claiming a token, stale cleanup functions become no-ops, and each path arms its own mechanism before tearing down the other's so the engine hooks stay owned throughout a switch.
Spell out that the custom callback runs inside the audio engine's lifecycle callbacks under a bounded native wait, so it must return quickly and must not call into the WebRTC engine or a peer connection. Doing so can block on the very engine operation the callback is holding up, stalling it until the wait times out. Also note that the default path involves no JavaScript per transition, that repeated setup calls supersede the previous one, and that switching paths is best done while disconnected.
🦋 Changeset detectedLatest commit: 0b0339e The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
The previous wording claimed a switch during an active call takes full effect from the next engine transition. That undersold the failure mode: switching away from a custom setup mid-call abandons the audio session activation its handlers took, and with the shared activation count nobody releases it, so the session can stay active after the call ends. State it as unsupported with the concrete consequence.
2 tasks
davidliu
added a commit
to livekit/react-native-webrtc
that referenced
this pull request
Jul 23, 2026
…er (#96) ## Summary Adds an iOS-only API that pushes the default audio-session policy to native once. When no custom JS handlers are registered, `willEnableEngine` and `didDisableEngine` now configure `AVAudioSession` on the native worker thread. This removes the JS round trip from the default path and the circular-wait risk described in #89. Custom JS handlers still take precedence and keep the bounded timeout. Native activation tracking handles normal stop, interruptions, and external deactivation. Switching between native and custom management during an active call remains unsupported. Switch while disconnected. ## Testing - Built for iOS device and simulator with Xcode 26.6 and WebRTC-SDK 144.7559.10 - Smoke tested on device with CallKit and RNCallKeep through connect, mic publish, mute, and disconnect - Observed no freeze, bridge-wait timeout, or native configuration failure - Confirmed the audio session returned inactive after teardown Current iOS CI failure is unrelated to this change. The React Native 0.71 example fails while compiling Yoga after `macos-latest` moved to macOS 26, before the native code from this PR is compiled. ## Before undrafting - [ ] Add a regression test for the #89 circular-wait shape - [ ] Repeat the device smoke test with the final decision logs Companion PR: livekit/client-sdk-react-native#434 --------- Co-authored-by: davidliu <davidliu@deviange.net>
davidliu
marked this pull request as ready for review
July 23, 2026 14:02
davidliu
approved these changes
Jul 23, 2026
Merged
davidliu
pushed a commit
that referenced
this pull request
Jul 23, 2026
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @livekit/react-native@2.12.0 ### Minor Changes - Configure the iOS audio session natively in the default path, removing the audio engine's JS round trip and its deadlock window. Deprecate the unsafe `onConfigureNativeAudio` callback form of `setupIOSAudioManagement`. Developers can instead pass in a static `IOSAudioSessionPolicy`. - [#434](#434) ([@hiroshihorie](https://github.com/hiroshihorie)) ### Patch Changes - Update @livekit/react-native-webrtc to 144.1.2 - [#434](#434) ([@hiroshihorie](https://github.com/hiroshihorie)) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
setupIOSAudioManagement's default path now pushes the audio-session policy to native viaAudioDeviceModule.setAutomaticAudioSessionConfiguration()instead of registeringwillEnable/didDisableJS handlers, so the audio engine's worker thread no longer round-trips to JS in the stock path. That round trip could stall or deadlock engine operations when the JS thread was itself blocked in a synchronous bridge call (livekit/react-native-webrtc#89). Custom configurations viaonConfigureNativeAudiokeep the JS handler path, still bounded by the native wait timeout.onConfigureNativeAudiocontract is documented: it runs under a bounded native wait and must not call into the WebRTC engine or a peer connection.Podfile.locksynced with the WebRTC-SDK 144.7559.10 pin. Changeset included (minor).Dependency
Depends on livekit/react-native-webrtc#96. CI here installs
@livekit/react-native-webrtcfrom the registry, which does not yet shipsetAutomaticAudioSessionConfiguration, so typecheck stays red until that PR merges, a release is cut, and the dependency here is bumped. Local verification was done against the linked fork.Testing
tscclean forsrc/against the linked fork branch (including the fork's literal-union types).Before undrafting
@livekit/react-native-webrtcdependency to that release