fix(bluetooth): wait for SCO link before Oboe restart + detect A2DP devices

Three fixes for Bluetooth audio not working:

1. is_bluetooth_available() now checks for TYPE_BLUETOOTH_A2DP (8) in
   addition to TYPE_BLUETOOTH_SCO (7) — many headsets only register as
   A2DP until SCO is explicitly started.

2. set_bluetooth_sco(on=true) polls isBluetoothScoOn() for up to 3s
   before restarting Oboe. startBluetoothSco() is async — the SCO link
   takes 500ms-2s to establish. Without waiting, Oboe opens against
   earpiece and audio goes nowhere.

3. Frontend skips redundant set_speakerphone(false) when transitioning
   to BT — start_bluetooth_sco() handles speaker-off internally,
   avoiding a double Oboe restart.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-04-12 16:46:56 +04:00
parent a798634b3d
commit 7e8dc400dc
3 changed files with 30 additions and 7 deletions

View File

@@ -185,10 +185,11 @@ pub fn is_bluetooth_sco_on() -> Result<bool, String> {
.map_err(|e| format!("isBluetoothScoOn: {e}"))
}
/// Check whether a Bluetooth SCO-capable device is currently connected.
/// Check whether a Bluetooth audio device is currently connected.
///
/// Iterates `AudioManager.getDevices(GET_DEVICES_OUTPUTS)` and looks for
/// `TYPE_BLUETOOTH_SCO` (7).
/// any Bluetooth device type. Many headsets only register as A2DP until
/// SCO is explicitly started, so we check for both SCO and A2DP types.
pub fn is_bluetooth_available() -> Result<bool, String> {
let (vm, activity) = jvm_and_activity()?;
let mut env = vm
@@ -220,8 +221,9 @@ pub fn is_bluetooth_available() -> Result<bool, String> {
.call_method(&device, "getType", "()I", &[])
.and_then(|v| v.i())
.unwrap_or(0);
// TYPE_BLUETOOTH_SCO = 7
if device_type == 7 {
// TYPE_BLUETOOTH_SCO = 7, TYPE_BLUETOOTH_A2DP = 8
if device_type == 7 || device_type == 8 {
tracing::info!(device_type, idx = i, "is_bluetooth_available: found BT device");
return Ok(true);
}
}