Created
January 16, 2020 13:02
-
-
Save halilozercan/94915f623d8dfb352b166af1fd88a102 to your computer and use it in GitHub Desktop.
This file contains 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
fun updateAudioDeviceState() { | |
// Check if any Bluetooth headset is connected. The internal BT state will | |
// change accordingly. | |
if (bluetoothManager.state == State.HEADSET_AVAILABLE || bluetoothManager.state == State.HEADSET_UNAVAILABLE || bluetoothManager.state == State.SCO_DISCONNECTING) { | |
bluetoothManager.updateDevice() | |
} | |
// Update the set of available audio devices. | |
val newAudioDevices: MutableSet<AudioDevice> = | |
HashSet() | |
if (bluetoothManager.state == State.SCO_CONNECTED || bluetoothManager.state == State.SCO_CONNECTING || bluetoothManager.state == State.HEADSET_AVAILABLE) { | |
newAudioDevices.add(AudioDevice.BLUETOOTH) | |
} | |
if (hasWiredHeadset) { // If a wired headset is connected, then it is the only possible option. | |
newAudioDevices.add(AudioDevice.WIRED_HEADSET) | |
} else { | |
// No wired headset, hence the audio-device list can contain speaker // phone (on a tablet), or speaker phone and earpiece (on mobile phone). | |
newAudioDevices.add(AudioDevice.SPEAKER_PHONE) | |
if (hasEarpiece()) { | |
newAudioDevices.add(AudioDevice.EARPIECE) | |
} | |
} | |
// Store state which is set to true if the device list has changed. | |
var audioDeviceSetUpdated = audioDevices != newAudioDevices | |
// Update the existing audio device set. | |
audioDevices = newAudioDevices | |
// Correct user selected audio devices if needed. | |
if (bluetoothManager.state == State.HEADSET_UNAVAILABLE | |
&& userSelectedAudioDevice == AudioDevice.BLUETOOTH | |
) { // If BT is not available, it can't be the user selection. | |
userSelectedAudioDevice = AudioDevice.NONE | |
} | |
// If user selected speaker phone, but then plugged wired headset then make | |
// wired headset as user selected device. | |
if (hasWiredHeadset && userSelectedAudioDevice == AudioDevice.SPEAKER_PHONE) { | |
userSelectedAudioDevice = AudioDevice.WIRED_HEADSET | |
} | |
// If user selected wired headset, but then unplugged wired headset then make | |
// speaker phone as user selected device. | |
if (!hasWiredHeadset && userSelectedAudioDevice == AudioDevice.WIRED_HEADSET) { | |
userSelectedAudioDevice = AudioDevice.SPEAKER_PHONE | |
} | |
// Need to start Bluetooth if it is available and user either selected it explicitly or | |
// user did not select any output device. | |
val needBluetoothAudioStart = | |
(bluetoothManager.state == State.HEADSET_AVAILABLE | |
&& (userSelectedAudioDevice == AudioDevice.NONE | |
|| userSelectedAudioDevice == AudioDevice.BLUETOOTH)) | |
// Need to stop Bluetooth audio if user selected different device and | |
// Bluetooth SCO connection is established or in the process. | |
val needBluetoothAudioStop = | |
((bluetoothManager.state == State.SCO_CONNECTED | |
|| bluetoothManager.state == State.SCO_CONNECTING) | |
&& (userSelectedAudioDevice != AudioDevice.NONE | |
&& userSelectedAudioDevice != AudioDevice.BLUETOOTH)) | |
// Start or stop Bluetooth SCO connection given states set earlier. | |
if (needBluetoothAudioStop) { | |
bluetoothManager.stopScoAudio() | |
bluetoothManager.updateDevice() | |
} | |
if (needBluetoothAudioStart && !needBluetoothAudioStop) { // Attempt to start Bluetooth SCO audio (takes a few second to start). | |
if (!bluetoothManager.startScoAudio()) { // Remove BLUETOOTH from list of available devices since SCO failed. | |
audioDevices.remove(AudioDevice.BLUETOOTH) | |
audioDeviceSetUpdated = true | |
} | |
} | |
// Update selected audio device. | |
val newAudioDevice = when { | |
// If a Bluetooth is connected, then it should be used as output audio | |
// device. Note that it is not sufficient that a headset is available; | |
// an active SCO channel must also be up and running. | |
bluetoothManager.state == State.SCO_CONNECTED -> { | |
AudioDevice.BLUETOOTH | |
} | |
// If a wired headset is connected, but Bluetooth is not, then wired headset is used as | |
// audio device. | |
hasWiredHeadset -> { | |
AudioDevice.WIRED_HEADSET | |
} | |
// No wired headset and no Bluetooth, hence the audio-device list can contain speaker | |
// phone (on a tablet), or speaker phone and earpiece (on mobile phone). | |
// |defaultAudioDevice| contains either AudioDevice.SPEAKER_PHONE or AudioDevice.EARPIECE | |
// depending on the user's selection. | |
else -> { | |
defaultAudioDevice | |
} | |
} | |
// Switch to new device but only if there has been any changes. | |
if (newAudioDevice != selectedAudioDevice || audioDeviceSetUpdated) { // Do the required device switch. | |
setAudioDeviceInternal(newAudioDevice) | |
onAudioDeviceChanged?.invoke(selectedAudioDevice, audioDevices) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment