react-native-webrtc / react-native-webrtc/react-native-incall-manager

Android AppRTCBluetoothManager does not properly update bluetoothState when user disconnects their headset

Open
#243 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
597
Forks
201
Avg merge
2h 42m
Merged PRs (30d)
1

Description

"react-native": "0.72.4",
"react-native-incall-manager": "^4.2.0",
"react-native-webrtc": "118.0.7",

Issue

I am developing a one way live stream and there is no need to ever send the audio to the Viewer's device's Earpierce, so I am using media: 'video' and also auto: true.

Initially, if the Viewer has no connected Bluetooth headsets, audio routes to the SpeakerPhone. If they have a connected Bluetooth headset when the join the stream or if they connect one midway, it will route to the device.

The issue arises when the Viewer turn off their only available Bluetooth headset. The AppRTCBluetoothManager identifies that a device was removed and that it needs to call BluetoothAudioDeviceCallback#updateDeviceList but does not perform the state updates needed to appropriately re-route to the SpeakerPhone.

Based on the native logs, bluetoothManager.getState() remains equal to AppRTCBluetoothManager.State.SCO_CONNECTED. This mean the selected audio device is still equal to AudioDevice.BLUETOOTH despite there being no Bluetooth device available. As a result, the device defaults back to the Earpiece and the audio routing remains in a denormalized/broken state until the call is restarted.

Reproduction Steps:

Using InCallManager.start({ media: 'video', auto: true });

  1. Join call with no Bluetooth Device Connected, Audio Routes to the SpeakerPhone
  2. Connect a Bluetooth Device, Audio routes to new device
  3. Turn Bluetooth Device Off, Audio routes to Earpiece
  4. Attempt to reconnect Bluetooth Device, Audio remains routed to Earpiece

To get my app working, I used patch-package to add bluetoothState = State.HEADSET_UNAVAILABLE; when newBtDevice === null. Im not sure how this would effect other use cases, but its a pretty simple change that appears to be handling my issue.

  private class BluetoothAudioDeviceCallback extends AudioDeviceCallback {
    ...
    private void updateDeviceList() {
      final AudioDeviceInfo newBtDevice = getScoDevice();
      boolean needChange = false;
      if (bluetoothAudioDevice != null && newBtDevice == null) {
        needChange = true;
        // NEW LINE
        bluetoothState = State.HEADSET_UNAVAILABLE;
      } else if (bluetoothAudioDevice == null && newBtDevice != null) {
        needChange = true;
      } else if (bluetoothAudioDevice != null && bluetoothAudioDevice.getId() != newBtDevice.getId()) {
        needChange = true;
      }
      if (needChange) {
        updateAudioDeviceState();
      }
    }
  }

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Android AppRTCBluetoothManager BluetoothAudioDeviceCallback.updateDeviceList() method and trace how getScoDevice(), bluetoothState, and updateAudioDeviceState() interact when the device list becomes empty. The fix is complete when disconnecting the only Bluetooth headset routes audio to the SpeakerPhone and reconnecting it restores Bluetooth routing; check the existing native logs or reproduction steps to verify both transitions.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, react-native
Domain
audio-video-rtc, mobile
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.