Bug 87081

Summary: Bluetooth cannot select a2dp profile automatically in 6.0 RC1
Product: PulseAudio Reporter: Weng Xuetian <wengxt>
Component: modulesAssignee: pulseaudio-bugs
Status: RESOLVED FIXED QA Contact: pulseaudio-bugs
Severity: normal    
Priority: medium CC: lennart
Version: unspecified   
Hardware: Other   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:
Bug Depends on:    
Bug Blocks: 75721    

Description Weng Xuetian 2014-12-07 22:11:59 UTC
6.0RC1 supports hsp/hfp and a2dp for my bluetooth, if bluetooth headset is disconnected with "hsp/hfp" active, next time it will connect to "hsp/hfp" automatically, which is fine.

When it is disconnected with a2dp active, next time the profile will be "off" when get connected.

With 5.0 it can automatically connect to a2dp by default.

Following is Related pactl output.

Card #3
        Name: bluez_card.00_12_3D_00_08_8F
        Driver: module-bluez5-device.c
        Owner Module: 32
        Properties:
                device.description = "Avantree sacool"
                device.string = "00:12:3D:00:08:8F"
                device.api = "bluez"
                device.class = "sound"
                device.bus = "bluetooth"
                device.form_factor = "headset"
                bluez.path = "/org/bluez/hci0/dev_00_12_3D_00_08_8F"
                bluez.class = "0x240404"
                bluez.alias = "Avantree sacool"
                device.icon_name = "audio-headset-bluetooth"
                device.intended_roles = "phone"
        Profiles:
                headset_head_unit: Headset Head Unit (HSP/HFP) (sinks: 1, sources: 1, priority: 20, available: yes)
                a2dp_sink: High Fidelity Playback (A2DP Sink) (sinks: 1, sources: 0, priority: 10, available: yes)
                off: 关闭 (sinks: 0, sources: 0, priority: 0, available: yes)
        Active Profile: a2dp_sink
        Ports:
                headset-output: Headset (priority: 0, latency offset: 0 usec, available)
                        Part of profile(s): headset_head_unit, a2dp_sink
                headset-input: Headset (priority: 0, latency offset: 0 usec)
                        Part of profile(s): headset_head_unit
Comment 1 Tanu Kaskinen 2014-12-08 13:10:30 UTC
Thanks for reporting!

I'll mark this bug as a release blocker.
Comment 2 David Henningsson 2014-12-08 13:51:25 UTC
Confirmed here, notice the "profile has no transport" error:

D: [lt-pulseaudio] bluez5-util.c: Properties changed in device /org/bluez/hci0/dev_00_18_91_3A_B6_EC
D: [lt-pulseaudio] bluez4-util.c: dbus: interface=org.freedesktop.DBus.Properties, path=/org/bluez/hci0/dev_00_18_91_3A_B6_EC, member=PropertiesChanged
D: [lt-pulseaudio] bluez4-util.c: dbus: interface=org.bluez.Profile1, path=/Profile/HSPAGProfile, member=NewConnection
D: [lt-pulseaudio] backend-native.c: dbus: path=/Profile/HSPAGProfile, interface=org.bluez.Profile1, member=NewConnection
D: [lt-pulseaudio] backend-native.c: dbus: NewConnection path=/org/bluez/hci0/dev_00_18_91_3A_B6_EC, fd=21
D: [lt-pulseaudio] bluez5-util.c: Transport /org/bluez/hci0/dev_00_18_91_3A_B6_EC/fd21 state changed from disconnected to idle
D: [lt-pulseaudio] module-bluez5-discover.c: Loading module-bluez5-device path=/org/bluez/hci0/dev_00_18_91_3A_B6_EC
I: [lt-pulseaudio] module-card-restore.c: Restored profile 'a2dp_sink' for card bluez_card.00_18_91_3A_B6_EC.
I: [lt-pulseaudio] module-card-restore.c: Restoring port latency offsets for card bluez_card.00_18_91_3A_B6_EC.
I: [lt-pulseaudio] card.c: Created 1 "bluez_card.00_18_91_3A_B6_EC"
W: [lt-pulseaudio] module-bluez5-device.c: Profile has no transport
D: [lt-pulseaudio] core-subscribe.c: Dropped redundant event due to change event.
I: [lt-pulseaudio] card.c: Changed profile of card 1 "bluez_card.00_18_91_3A_B6_EC" to off
Comment 3 David Henningsson 2014-12-08 14:08:20 UTC
Notice that the "Transport /org/bluez/hci0/dev_00_18_91_3A_B6_EC/fd2 available for profile a2dp_sink" comes *after* trying to set the profile to a2dp_sink.

D: [lt-pulseaudio] bluez4-util.c: dbus: interface=org.freedesktop.DBus.Properties, path=/org/bluez/hci0/dev_00_18_91_3A_B6_EC, member=PropertiesChanged
D: [lt-pulseaudio] bluez4-util.c: dbus: interface=org.bluez.Profile1, path=/Profile/HSPAGProfile, member=NewConnection
D: [lt-pulseaudio] backend-native.c: dbus: path=/Profile/HSPAGProfile, interface=org.bluez.Profile1, member=NewConnection
D: [lt-pulseaudio] backend-native.c: dbus: NewConnection path=/org/bluez/hci0/dev_00_18_91_3A_B6_EC, fd=21
D: [lt-pulseaudio] bluez5-util.c: Transport /org/bluez/hci0/dev_00_18_91_3A_B6_EC/fd21 state changed from disconnected to idle
D: [lt-pulseaudio] module-bluez5-discover.c: Loading module-bluez5-device path=/org/bluez/hci0/dev_00_18_91_3A_B6_EC
I: [lt-pulseaudio] module-card-restore.c: Restored profile 'a2dp_sink' for card bluez_card.00_18_91_3A_B6_EC.
I: [lt-pulseaudio] module-card-restore.c: Restoring port latency offsets for card bluez_card.00_18_91_3A_B6_EC.
I: [lt-pulseaudio] card.c: Created 1 "bluez_card.00_18_91_3A_B6_EC"
W: [lt-pulseaudio] module-bluez5-device.c: Profile has no transport
D: [lt-pulseaudio] core-subscribe.c: Dropped redundant event due to change event.
I: [lt-pulseaudio] card.c: Changed profile of card 1 "bluez_card.00_18_91_3A_B6_EC" to off
I: [lt-pulseaudio] module.c: Loaded "module-bluez5-device" (index: #26; argument: "path=/org/bluez/hci0/dev_00_18_91_3A_B6_EC").
D: [lt-pulseaudio] backend-native.c: Transport /org/bluez/hci0/dev_00_18_91_3A_B6_EC/fd21 available for profile headset_head_unit
D: [lt-pulseaudio] backend-native.c: RFCOMM << AT+VGS=10
D: [lt-pulseaudio] backend-native.c: RFCOMM >> OK
D: [lt-pulseaudio] backend-native.c: RFCOMM << AT+VGM=15
D: [lt-pulseaudio] backend-native.c: RFCOMM >> OK
D: [lt-pulseaudio] backend-native.c: RFCOMM << AT+CSRSF=0,0,0,0,0,1
D: [lt-pulseaudio] backend-native.c: RFCOMM >> OK
D: [lt-pulseaudio] bluez4-util.c: dbus: interface=org.bluez.MediaEndpoint1, path=/MediaEndpoint/A2DPSource, member=SelectConfiguration
D: [lt-pulseaudio] bluez5-util.c: dbus: path=/MediaEndpoint/A2DPSource, interface=org.bluez.MediaEndpoint1, member=SelectConfiguration
D: [lt-pulseaudio] bluez5-util.c: Unknown interface org.freedesktop.DBus.Introspectable found, skipping
D: [lt-pulseaudio] bluez5-util.c: Unknown interface org.bluez.MediaTransport1 found, skipping
D: [lt-pulseaudio] bluez5-util.c: Unknown interface org.freedesktop.DBus.Properties found, skipping
D: [lt-pulseaudio] bluez4-util.c: dbus: interface=org.freedesktop.DBus.ObjectManager, path=/, member=InterfacesAdded
D: [lt-pulseaudio] bluez4-util.c: dbus: interface=org.bluez.MediaEndpoint1, path=/MediaEndpoint/A2DPSource, member=SetConfiguration
D: [lt-pulseaudio] bluez5-util.c: dbus: path=/MediaEndpoint/A2DPSource, interface=org.bluez.MediaEndpoint1, member=SetConfiguration
D: [lt-pulseaudio] bluez5-util.c: Transport /org/bluez/hci0/dev_00_18_91_3A_B6_EC/fd2 state changed from disconnected to idle
D: [lt-pulseaudio] card.c: Setting card bluez_card.00_18_91_3A_B6_EC profile a2dp_sink to availability status unknown
D: [lt-pulseaudio] bluez5-util.c: Transport /org/bluez/hci0/dev_00_18_91_3A_B6_EC/fd2 available for profile a2dp_sink
Comment 4 David Henningsson 2014-12-08 14:26:18 UTC
After having looked at this for a little while, I think we need to contact the bluez people to figure out how to defer card creation until the transports are set up.
Comment 5 Tanu Kaskinen 2014-12-09 10:26:52 UTC
BlueZ 5 doesn't have the Audio interface, which we use with BlueZ 4 for synchronization (the Audio interface becomes connected after both A2DP and HSP have become connected, so we wait until the Audio interface become connected before loading the device module).

We've had problems with this before, and I think it became clear last time that it's really not a good idea to implement a synchronization point like BlueZ 4 has done. Bluetooth devices can and sometimes do advertise their supported devices asynchronously, in a way that makes it simply impossible for bluetoothd to know when all profiles have been initialized.

The problem was solved by extending module-card-restore so that if it tries to restore a profile that isn't available when the card is initially created, restoring the profile will be done at the time the profile is added. Maybe this dynamic profile adding has broken at some point?
Comment 6 David Henningsson 2014-12-09 22:06:13 UTC
(In reply to Tanu Kaskinen from comment #5)
> BlueZ 5 doesn't have the Audio interface, which we use with BlueZ 4 for
> synchronization (the Audio interface becomes connected after both A2DP and
> HSP have become connected, so we wait until the Audio interface become
> connected before loading the device module).
> 
> We've had problems with this before, and I think it became clear last time
> that it's really not a good idea to implement a synchronization point like
> BlueZ 4 has done. Bluetooth devices can and sometimes do advertise their
> supported devices asynchronously, in a way that makes it simply impossible
> for bluetoothd to know when all profiles have been initialized.
> 
> The problem was solved by extending module-card-restore so that if it tries
> to restore a profile that isn't available when the card is initially
> created, restoring the profile will be done at the time the profile is
> added. Maybe this dynamic profile adding has broken at some point?

You mean when the profile is added, or when it becomes available?

If we don't have a synchronisation point, then maybe we should just instead not set the profile to "off" unless we really have to. Right now there is code that sets the profile to "off" if the profile has no transport when the card is created, which seems to always be the case to a2dp.

What if we instead allow the card to stay at the broken profile?
Comment 7 Tanu Kaskinen 2014-12-10 10:59:15 UTC
I mean when the profile is added. That's the hook that module-card-restore uses.

This dynamic profile adding was implemented to deal with new uuids being announced after the device has been created. The BlueZ 5 code doesn't seem to use pa_card_add_profile() at all. I think Mikel Astiz used that in the original BlueZ 5 patches, but Mikel's code got reverted. The current BlueZ 5 code doesn't seem to handle the case of new uuids appearing, which probably causes problems to some people, but that's not the problem in this case, because the a2dp uuid has already been announced by the device at the point where pulseaudio loads the device module.

So, the problem appears to be that the a2dp profile is not yet connected when the device module is loaded. It makes sense to create the card profile, but its state is unavailable. How should module-card-restore behave in such situation? What if a2dp never gets connected?

I think it's quite likely that if the card had previously the a2dp profile selected, the profile will get connected again, so I think module-card-restore should allow unavailable profiles to be selected, at least in case of bluetooth devices (I'm not sure that makes sense with alsa, but alsa profiles don't currently have availability information anyway). In the unlikely case that a2dp doesn't get connected, well, then the user has to switch the profile manually.

I guess it's not module-card-restore that sets the profile to "off", though. Instead, it's the bluetooth card itself. If we want to allow the a2dp profile to be selected while it's unavailable, then module-bluez5-device has to be modified to not do the automatic switch to "off". So, my answer to "what if we instead allow the card to stay at the broken profile?" is that we should do that. I don't know how difficult it will be - I guess we want to keep the sink around too, so the sink will need to handle the situation where there's no transport available.
Comment 8 David Henningsson 2014-12-19 11:59:30 UTC
This should be fixed in git head (see http://cgit.freedesktop.org/pulseaudio/pulseaudio/commit/?id=de1e78a47cd13496c38f627d56944045a629053e and http://cgit.freedesktop.org/pulseaudio/pulseaudio/commit/?id=1d3fd4f8627942b931ab6db4137186a567fe6939 ).

Please test and reopen the bug if this is not the case. Thanks!
Comment 9 Weng Xuetian 2014-12-20 19:59:51 UTC
Hi, I just test the 5.99.2 version, it seems to work fine.

Thank you very much!

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.