-
Notifications
You must be signed in to change notification settings - Fork 572
TechNote_BluetoothAudio
Bluetooth audio devices work differently during a phone call and listening to music. Most Bluetooth audio devices expose two endpoints, A2DP and SCO.
A2DP is a protocol supported on most Bluetooth Audio devices. This protocol is used for high quality music.
To achieve high quality music, Android encodes music with a codec. The headset receives this data and decodes it into PCM data. Android and headsets should support the SBC codec. Additional codecs like aptX, AAC, and LDAC are supported on a per device basis.
During a voice call, SCO is used. The underlying protocols HSP/HFP are supported on most Bluetooth devices. HSP (HeadSet Profile) is used for voice communication and HFP (Hands-Free Profile) was meant to control a phone from another unit.
Compared to A2DP, SCO has worse audio quality but lower latency.
Bluetooth audio devices default to A2DP when not in a voice call. You can add some functionality in your app to add a callback whenever a new audio device is added to see if a SCO device is added.
mAudioManager.registerAudioDeviceCallback(new AudioDeviceCallback() {
@Override
public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
List<AudioDeviceListEntry> deviceList =
AudioDeviceListEntry.createListFrom(addedDevices, mDirectionType);
if (deviceList.size() > 0){
mDeviceAdapter.addAll(deviceList);
}
}
}, null);
You can check whether an audio device is SCO from AudioDeviceInfo.
@RequiresApi(api = Build.VERSION_CODES.M)
private boolean isScoDevice(int deviceId) {
if (deviceId == 0) return false; // Unspecified
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
final AudioDeviceInfo[] devices;
devices = audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
for (AudioDeviceInfo device : devices) {
if (device.getId() == deviceId) {
return device.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO;
}
}
return false;
}
You can set setDeviceId() on a stream to set the audio device as SCO. Also, you need to start Bluetooth SCO in Android.
private void startBluetoothSco() {
AudioManager myAudioMgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
myAudioMgr.startBluetoothSco();
}
Please call startBluetoothSco() and setDeviceId() at similar times. Not doing so will result in the lack of sound. See HelloOboe for a full example of turning on a Bluetooth SCO device when the Bluetooth SCO endpoint is selected.
In most cases, Android itself has a latency between 30-100 ms. Most of the latency comes from buffering on various headsets.
If a specific headset has a high latency, try changing the Bluetooth Audio Codec in developer settings. Also, try toggling "Disable Bluetooth A2DP hardware offload".
- Apps Using Oboe or AAudio
- Tech Notes
- OboeTester Instructions
- Quirks and Bugs
- Developer Notes