Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AudioDeviceChangeListener called with Earpiece after a switch to Bluetooth #47

Closed
alizeec opened this issue Aug 3, 2020 · 26 comments
Closed
Labels
bug Something isn't working

Comments

@alizeec
Copy link

alizeec commented Aug 3, 2020

Describe the bug
After selecting a bluetooth device, the AudioDeviceChangeListener is called first with selectedAudioDevice = BluetoothHeadset (correct) and then with selectedAudioDevice = Earpiece 5 seconds later

To Reproduce
Steps to reproduce the behavior:

  1. Put a log or a breakpoint in
audioDeviceSelector.start { list, selectedDevice ->
println("when list of devices change selectedAudioDevice = ${selectedDevice?.name} audioDevices = $list")
}
availableAudioDevices.find { it is AudioDevice.BluetoothHeadset }?.let { audioDeviceSelector.selectDevice(it) }
audioDeviceSelector.activate()

Expected behavior
I should see in log

2020-08-03 11:34:46.041 when list of devices change selectedAudioDevice = AirPods audioDevices = [BluetoothHeadset(name=AirPods), Earpiece(name=Earpiece), Speakerphone(name=Speakerphone)]

Actual behavior
I see

2020-08-03 11:34:46.041 when list of devices change selectedAudioDevice = AirPods audioDevices = [BluetoothHeadset(name=AirPods), Earpiece(name=Earpiece), Speakerphone(name=Speakerphone)]
2020-08-03 11:34:51.675 when list of devices change selectedAudioDevice = Earpiece audioDevices = [BluetoothHeadset(name=AirPods), Earpiece(name=Earpiece), Speakerphone(name=Speakerphone)]

But the audio is still routed to bluetooth

Android Device (please complete the following information):

  • Device: OnePlus 6T
  • API Version: API 29

Version

  • Version: 0.2.1
@alizeec alizeec added the bug Something isn't working label Aug 3, 2020
@Alton09
Copy link
Contributor

Alton09 commented Aug 3, 2020

Hi @alizeec . Thank you for filing this issue! I have found the root cause for this bug and will begin working on a fix.

@Alton09
Copy link
Contributor

Alton09 commented Aug 3, 2020

Hi @alizeec . I've only been able to reproduce this bug with the following steps in a test application:

  1. Launch the app and call the AudioDeviceSelector's start and activate functions in an Activity's onCreate function.
  2. Press back on the device, which finishes the Activity.
  3. Relaunch the app.
  4. See the earpiece in the selectedDevice as you described.

However, this only works if the application does not call the AudioDeviceSelector's stop() function before exiting the activity. We strongly encourage developers to invoke stop() when they no longer need audio routing focus in their applications in order to avoid these types of problems. Can you please confirm that your application is in fact invoking the stop() function when necessary? Thanks!

Also, you can find the code where I ran the reproduction steps here.

@alizeec
Copy link
Author

alizeec commented Aug 4, 2020

Hi @Alton09

I confirm that audioDeviceSelector.stop() is called before the activity is finished.

  1. Start the call with bluetooth device connected. I receive as selected device earpiece first and then Bluetooth
  2. Switch to earpiece -> all good
  3. Switch to bluetooth -> I receive as selected device first Bluetooth and then earpiece 5 seconds later
  4. audioDeviceSelector.stop() at the end of the call, before finishing the Activity

@Alton09
Copy link
Contributor

Alton09 commented Aug 4, 2020

Thanks for the information @alizeec . It appears that the library is unable to activate bluetooth SCO (i.e. audio) on the connected headset, and is reverting back to the earpiece after 5 seconds. This could be occurring because the AirPods are not "active" in the OS. In the Bluetooth settings app on that device, do the AirPods appear as "active"?

Also, can you please run through the steps you mentioned above, open logcat and filter on "bluetooth" with verbose level filtering on your application enabled and share those logs? This will help us see what is going on with bluetooth as you run through the reproductions steps. Thanks!

@alizeec
Copy link
Author

alizeec commented Aug 5, 2020

Hi @Alton09
Thanks for your answer

I don't think AirPods are "not active" on Android. I use them every day, it's compatible. Currently in our app we handle the bluetooth manually and we don't have any problems. Moreover, in your previous version 0.1.4 it was working.
The listener fallback to earpiece, but the sound is still routed to the Airpods.
Please note that is this test, when the earpiece was selected, the sound was still routed to Airpods

You can find attached the logs.

  • 1 : I started the call with bluetooth -> expected behavior
  • 2: I switch to earpiece -> 1st timeout in logs. The listener returns earpiece but the sound is routed to Airpods
  • 3: I switch to Bluetooth -> 2nd timeout in logs. The listener returns bluetooth and then earpiece but the sound is always routed to Airpods

Thanks

logs_bluetooth.txt

@Alton09
Copy link
Contributor

Alton09 commented Aug 5, 2020

Hi @alizeec . Thank you, this is very helpful information. Although, the logs appear to be from an older version of AudioSwitch, as the "Invoking bluetooth sco action" log is being displayed. In version 0.2.1, we introduced more detailed logging for starting and stopping bluetooth sco and better audio device fallback support. Do you mind running the same steps with logs on version 0.2.1? Thanks!

@alizeec
Copy link
Author

alizeec commented Aug 6, 2020

Hi @Alton09
I'm sorry, I don't understand why I had logs of a previous version because I was using the 0.2.1 already. Probably a cache issue.
Anyway, here is the logs after a clean, on 0.2.1, with the exact same steps. I have the same behavior
logs-bluetooth-2.txt

Thanks

@alizeec
Copy link
Author

alizeec commented Aug 6, 2020

@Alton09 to give you more context, https://gist.github.com/alizeec/098295222a1bae1746477a80d39f0b05 you can see in this gist how I use the SDK, and where the "[AUDIOSDK] ..." logs are

@Alton09
Copy link
Contributor

Alton09 commented Aug 6, 2020

@alizeec Thanks for the logs from the most recent version and the code reference! From the behavior you are describing above and from what I'm seeing in your logs, it appears that bluetooth SCO is connected before your AudioService class invokes the selectDevice() AudioDeviceSelector function. Because of this, the library is unable to activate SCO (since it is already in that state) and then the sco job timeout occurs.

The library should definitely guard against this by checking the SCO connection status before attempting to start a SCO connection. I will work to get that change in the upcoming release. As a workaround In the meantime, please ensure the following in your application:

  1. Your app is not starting bluetooth sco outside of the AudioSwitch library.
  2. Ensure that the app properly invokes deactivate() or stop() when BT audio routing is no longer needed in your application. You mentioned that the activity invokes stop() during tear down, but perhaps you need to invoke deactivate() or stop() right after your call ends before starting a new one.

@Alton09
Copy link
Contributor

Alton09 commented Aug 7, 2020

Hi @alizeec . We believe we have provided a fix for this issue. Can you please validate by using this snapshot version of the library, 0.2.1-issue-47-SNAPSHOT? Thanks!

@alizeec
Copy link
Author

alizeec commented Aug 10, 2020

Hi @Alton09

Thanks for the fix, it does solve the problem where the bluetooth fallback on earpiece 5 seconds later. Now the selected device returned is the one I'm suppose to have.

But I still have a lot of problem with the device really selected .

First test (my Airpods are already connected before the call):

  • selected device is Bluetooth, sound is routed to bluetooth -> OK
  • I select earpiece, the sound is still routed to bluetooth -> NOK
    (I can repeat this several times, it's always routed to bluetooth)
  • I select speaker, the sound is routed to speaker -> OK
  • I select bluetooth, the sound is routed to earpiece -> NOK
    ( from there, I can't route the sound to bluetooth anymore)

When I stop the call and do another (audioDeviceSelector.stop() is called, it's another instance of the activity), with my bluetooth device connected, the selected device is earpiece while it should have been bluetooth. After that, I have the same behavior than above

Thanks

@aaalaniz
Copy link
Contributor

Hey @alizeec

I have been investigating this bug and I do have some leads, but I wanted to get some more information before we try any more changes to the library.

  1. Would it be possible for you to provide a sample project forked from the Video Quickstart that replicates your usage of AudioSwitch and reproduces the bug? I'm afraid the steps you provided do not provide enough information to reproduce this problem reliably on our end. These are steps that we have a decent amount of test coverage for and I think we may be missing something.
  2. Can you ensure that there is only one instance of AudioDeviceSelector in your application? I have been able to reproduce similar bugginess if I create multiple AudioDeviceSelector objects that have called start with a bluetooth device connected.
  3. Is your application using any other Android bluetooth APIs prior to creating the AudioDeviceSelector object? This was something that I noticed would also cause some undefined behavior in AudioSwitch.

We appreciate your patience as we work through this issue. If we cannot resolve over GitHub then we can schedule a live debug session to ensure we get this problem fixed. If you would like to setup a debug call with myself and @Alton09 you can reach out to me at aalaniz [at] twilio.com

Thanks!

@aaalaniz
Copy link
Contributor

Hey @alizeec

I just wanted to check the status of this issue. We are pausing development of this issue fix until we clearly understand the steps to reproduce. Let us know if you have any updates.

Thanks!

@iorgad
Copy link

iorgad commented Aug 14, 2020

Hi @aaalaniz,

Great job with this library, thank you! I also have the an issue where after disconnecting a wired/bluetooth headsets, even if I apply the above code snippet (manually selecting the Speakerphone Audio Device) it still selects the Earpiece Audio Device. I've also ensured that there is only a single instance of AudioDeviceSelector where ever I use it.

I am currently using version 0.2.1, the entire Twilio functionality is inside a Fragment that I start from an Activity where I initialize the AudioDeviceSelector that I then pass to a BroadcastReceiver and the respective Fragment. I start() the AudioDeviceSelector in the Activity but inside the Fragment, with the passed AudiosDeviceSelector, I cannot receive any devices and when I try to activate() it fails. If I also start() in the Fragment it will get the Audio Devices properly. The BroadcastReceiver I use it for detecting Audio Devices changes where I just do a findAvailableDevices and select one.

Please let me know if you are still working on fixing this issue or if there are other workarounds that I can apply.

Best regards,
Dragos I.

@aaalaniz
Copy link
Contributor

Hey @iorgad

Can you open a separate issue with the scenario you described? What you are describing sounds slightly different than what @alizeec describes.

In your scenario it looks like the library may be erroneously falling back to earpiece when you have selected speakerphone after a bluetooth disconnect. @alizeec seems to be describing a scenario where the app switches to speakerphone, but audio continues to flow out of the bluetooth device.

I recommend upgrading to 0.3.0, enabling logging, and providing a log file when you are able to reproduce the issue.

Thank you!

@alizeec
Copy link
Author

alizeec commented Aug 17, 2020

hello @aaalaniz

Sorry for the late response I was in holidays

  1. It will be complicated right now for me because I don't have the time to work on the sample you asked. I will, when I will have more bandwidth
  2. I'm sure we have only one instance of AudioDeviceSelector
  3. I removed all the occurence of bluetooth APIs in the app

So I guess you can close the issue for now, and I will re-open it with the sample later. Is it ok for you?

Thanks

@Alton09
Copy link
Contributor

Alton09 commented Aug 17, 2020

Thanks for the response @alizeec ! Yes, that sounds like a good plan. Please create a new issue at your convenience later on.

@Alton09 Alton09 closed this as completed Aug 17, 2020
@iorgad
Copy link

iorgad commented Aug 18, 2020

Hi @aaalaniz,

Sorry for the late response. I've just updated the library to 0.3.0 and everything works properly now when switching from headsets to speaker.

Thank you for your quick response and instructions.

Great work on this library!

Best regards,
Dragos

@Alton09
Copy link
Contributor

Alton09 commented Aug 18, 2020

Hi @iorgad. Glad to hear that the upgrade solved your problem! We also just released our first stable release of the library, 1.0.0 which adds a couple enhancements.

@alizeec
Copy link
Author

alizeec commented Sep 15, 2020

Hi @Alton09

I tried the version 1.0.0.
At first, I still had the issue reported above

selected device is Bluetooth, sound is routed to bluetooth -> OK
I select earpiece, the sound is still routed to bluetooth -> NOK

but I tried to remove the audioSwitch.activate() after audioSwitch.selectDevice(earpieceDevice) even if the doc say that I have to do it https://github.com/twilio/audioswitch#select-a-device and I didn't had the issue anymore.

But now I have the initial issue again (it seems random) :

After selecting a bluetooth device, the AudioDeviceChangeListener is called first with selectedAudioDevice = BluetoothHeadset (correct) and then with selectedAudioDevice = Earpiece 5 seconds later

Should I open a new issue for that? Because it's still the same bug

Thanks

@Alton09
Copy link
Contributor

Alton09 commented Sep 15, 2020

Hi @alizeec . This issue sounds very similar to #66. We have found that this issue occurs on Huawei devices. Can you please confirm what device you are experiencing this bug on?

Also, we have noticed improvements when using the latest version, 1.0.1. Can you please test on this release? Thanks!

@alizeec
Copy link
Author

alizeec commented Sep 17, 2020

Hi @Alton09
I can try the last version yes, but I'm using a OnePlus 6T, not a Huawei

@jbialkowski13
Copy link

Hi @Alton09
I found the same issue with this library.

I am 100% sure that:

  • There is only 1 instance of AudioSwitch
  • I don't call anywhere startBluetoothSco

My use-case:
Device: Samsung s10
Bluetooth device: Bose QuiteComfort 35 II and JBL GO 2

Steps:

  1. Call audioSwitch.start after Voice.connect is called
  2. Bluetooth headset/speakers are selected as audio source automatically
  3. Change to speakers
  4. Change to phone
  5. Change to Bluetooth

In logs I constantly see: Attempting to enable bluetooth SCO

My logs:

D/AS/BluetoothHeadsetManager: Device size 0
D/AS/AudioDeviceManager: Earpiece available
D/AS/AudioDeviceManager: Speakerphone available
D/AS/AudioSwitch: Available AudioDevice list updated: [BluetoothHeadset(name=Bluetooth), Earpiece(name=Earpiece), Speakerphone(name=Speakerphone)]
D/AS/AudioSwitch: Current user selected AudioDevice = null
D/AS/WiredHeadsetReceiver: Wired headset device  disconnected
D/AS/BluetoothHeadsetManager: Device size 0
D/AS/AudioDeviceManager: Earpiece available
D/AS/AudioDeviceManager: Speakerphone available
D/AS/AudioSwitch: Available AudioDevice list updated: [BluetoothHeadset(name=Bluetooth), Earpiece(name=Earpiece), Speakerphone(name=Speakerphone)]
D/AS/AudioSwitch: Current user selected AudioDevice = null
D/AS/BluetoothHeadsetManager: Bluetooth JBL GO 2 connected
D/AS/BluetoothHeadsetManager: Headset state changed to Connected
D/AS/BluetoothHeadsetManager: Device size 1 with device name: JBL GO 2
D/AS/AudioDeviceManager: Earpiece available
D/AS/AudioDeviceManager: Speakerphone available
D/AS/AudioSwitch: Available AudioDevice list updated: [BluetoothHeadset(name=JBL GO 2), Earpiece(name=Earpiece), Speakerphone(name=Speakerphone)]
D/AS/AudioSwitch: Current user selected AudioDevice = null
D/AS/AudioSwitch: Selected AudioDevice = Earpiece(name=Earpiece)
D/AS/BluetoothHeadsetManager: Device size 1 with device name: JBL GO 2
D/AS/AudioDeviceManager: Earpiece available
D/AS/AudioDeviceManager: Speakerphone available
D/AS/AudioSwitch: Available AudioDevice list updated: [BluetoothHeadset(name=JBL GO 2), Earpiece(name=Earpiece), Speakerphone(name=Speakerphone)]
D/AS/AudioSwitch: Current user selected AudioDevice = Earpiece(name=Earpiece)
W/AS/BluetoothHeadsetManager: Cannot deactivate when in the Connected state
D/AS/AudioSwitch: Selected AudioDevice = BluetoothHeadset(name=JBL GO 2)
D/AS/BluetoothHeadsetManager: Device size 1 with device name: JBL GO 2
D/AS/AudioDeviceManager: Earpiece available
D/AS/AudioDeviceManager: Speakerphone available
D/AS/AudioSwitch: Available AudioDevice list updated: [BluetoothHeadset(name=JBL GO 2), Earpiece(name=Earpiece), Speakerphone(name=Speakerphone)]
D/AS/AudioSwitch: Current user selected AudioDevice = BluetoothHeadset(name=JBL GO 2)
D/AS/BluetoothScoJob: Scheduled bluetooth sco job
D/AS/BluetoothScoJob: Scheduled bluetooth sco job
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Headset state changed to AudioActivating
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
D/AS/BluetoothHeadsetManager: Attempting to enable bluetooth SCO
E/AS/BluetoothScoJob: Bluetooth sco job timed out
    java.util.concurrent.TimeoutException
        at com.twilio.audioswitch.bluetooth.BluetoothScoJob$BluetoothScoRunnable.run(BluetoothScoJob.kt:53)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:8167)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496

@Alton09
Copy link
Contributor

Alton09 commented Dec 16, 2020

Hi @whiter13! Sorry for the late reply on this one. Can you please create a separate issue for this problem following the New Issue template? This appears to be a slightly different issue and it will help us track it better. Thanks!

@VitaliyHTC
Copy link

Hi @Alton09.
I tried to use this lib on Samsung A51 Android 11. (Actually i think we can reproduce behaviour on any other Samsungs with Android 11).
So, I'm trying to implement AudioDevices output switch, and found same bad behaviour as for my code.

If you connect BT headset & WiredHeadset, you will see 3 options: Speaker, Headset, Bluetooth (Or name of BT device).
With AudioSwitch lib I'm getting clicking sound in BT headset for about 1 minute, when it's stabilized.
Sometimes it displays that WiredHeadset is selected device when in real sound played through BT headset.
Actually top problem is that on Samsung Android 11 I can't switch to WiredHeadset. Looks like system in some way redirects output to BT instead of BT. But if you'll verify audioManager.isBluetoothSCOOn() you will see true after selecting WiredHeadset and activating it.

Maybe it's caused by my program configuration. Not sure.

Please check how it behaves on Samsungs with Android 11 when BT headset & WiredHeadset connected to phone, how stable switching is.

Also we experienced problems with Wearable SmartWatches. If device, after reboot saw only SmartWatches as connected BT device - there is also some problems with AudioOutput. Sadly can't provide more info, will be able to check behaviour with SmartWatch later.

BR, Vitaliy.

@Alton09
Copy link
Contributor

Alton09 commented May 21, 2021

Thanks for reaching out @VitaliyHTC ! Do you mind creating a new issue following our new issue template with as much detail as possible? This will help us provide better support for your problem. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

6 participants