Re: avrcp: possible race condition during connection establishment

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Marek,

On Wed, 21 Oct 2020 at 16:02, Marek Czerski <ma.czerski@xxxxxxxxx> wrote:
>
> Hi Marijn,
>
> Regarding the AVRCP version reported by the phone. There is something
> weird going on on android regarding avrcp version and mac addresses
> and absolute volume. I discovered couple of whings:
> 1. galaxy S7 will blacklist some mac addresses to not use absolute
> volume for that device (checked it with "adb shell dumpsys
> bluetooth_manager"). Changing mac addres of the device to something
> other allows for absolute volume to work. For both cases it reports
> avrcp version 1.4.

There is indeed a database with traits based on mac-addresses [1].

> 2. xiaomi redmi note 4 will report different avrcp version depending
> on mac address. version 1.3 for mac address that galaxy s7 blacklists
> and 1.6 for mac address that galaxy s7 does not blacklist. But in both
> cases the absolute volume does not work ...

You confirmed earlier that besides this versioning issue there's also
an initialization issue with supported_events. I assume this test was
without flipping the _init calls around?

> 3. xiaomi redmi 8 will not even report that it has "A/V_RemoteControl"
> (UUID 0x110E), it just reports that it has only
> "A/V_RemoteControlTarget" (UUID 0x110C) but still it can control
> volume on my yamaha av receiver and sony headphones and receive volume
> updates from them. Very, very wierd.

That's not really surprising to me, in fact it is slightly weird that
other phones report the A/V_RemoteControl profile. A phone will always
be the audio source (thus the RemoteControlTarget), never the sink.

(Unless applying some hacks to libfluoride: it is possible to use an
older phone as A2DP sink - for example to connect to a receiver at the
other side of the room. I would have enabled it on all my phones if it
didn't break A2DP source capabilities at the same time... Maybe
Gabeldorsche addresses that)

> For the record, to check the avrcp version of the phone I use sdptool
> browse command (and to be 100% sure I check also the raw communication
> on wireshark). For example this is one of the records reported for
> xiaomi redmi note 4 and avrcp version 1.6:
> Service RecHandle: 0x10007
> Service Class ID List:
>   "AV Remote" (0x110e)
>   "AV Remote Controller" (0x110f)
> Protocol Descriptor List:
>   "L2CAP" (0x0100)
>     PSM: 23
>   "AVCTP" (0x0017)
>     uint16: 0x0104
> Profile Descriptor List:
>   "AV Remote" (0x110e)
>     Version: 0x0106
> If there is something more I can do to help please let me know. For
> example I can send hci snoop logs for specific cases etc.

I will send a _preliminary_ patch to this thread that should resolve
both the versioning and ordering issue as I've finally figured a way
to check whether the session associated with an AVRCP command is
running as source or sink. It is not finalized yet so please don't be
too hard on it :)

> wt., 20 paź 2020 o 15:12 Marek Czerski <ma.czerski@xxxxxxxxx> napisał(a):
> >
> > Hi Marijn,
> >
> > wt., 20 paź 2020 o 11:11 Marijn Suijten <marijns95@xxxxxxxxx> napisał(a):
> > >
> > > Hi Marek,
> > >
> > > (Apologies for sending this to you twice; missed the reply-all button
> > > so this didn't end up on the mailing list)
> > >
> > > On Tue, 20 Oct 2020 at 09:31, Marek Czerski <ma.czerski@xxxxxxxxx> wrote:
> > > >
> > > > Hi Marijn,
> > > >
> > > > pon., 19 paź 2020 o 21:53 Marijn Suijten <marijns95@xxxxxxxxx> napisał(a):
> > > > >
> > > > > Hi Luiz, Marek,
> > > > >
> > > > > On Mon, 19 Oct 2020 at 18:47, Luiz Augusto von Dentz
> > > > > <luiz.dentz@xxxxxxxxx> wrote:
> > > > > >
> > > > > > Hi Marek, Marijn,
> > > > > >
> > > > > > On Mon, Oct 19, 2020 at 9:06 AM Marek Czerski <ma.czerski@xxxxxxxxx> wrote:
> > > > > > >
> > > > > > > Hi Marijn,
> > > > > > >
> > > > > > > pon., 19 paź 2020 o 16:16 Marijn Suijten <marijns95@xxxxxxxxx> napisał(a):
> > > > > > > >
> > > > > > > > Hi Marek,
> > > > > > > >
> > > > > > > > > Hi all,
> > > > > > > > >
> > > > > > > > > I was looking into, so called, absolute volume control that was
> > > > > > > > > introduced in AVRCP v1.4. What I want to achieve is to send audio from
> > > > > > > > > android smartphone to linux based device running bluez and make the
> > > > > > > > > volume control on the smartphone side to control the volume on the
> > > > > > > > > device. So the device is the a2dp sink + avrcp CT/TG and the phone is
> > > > > > > > > a2dp source + avrcp CT/TG.
> > > > > > > > >
> > > > > > > > > I assume that if all is working correctly then on the dbus the Volume
> > > > > > > > > property of the org.bluez.MediaTransport1 will be changed by the
> > > > > > > > > volume control of the phone and changes made to this property from the
> > > > > > > > > device would propagate to the phone volume slider.
> > > > > > > > >
> > > > > > > > > This is not happening and what I believe is the cause is that
> > > > > > > > > AVRCP_EVENT_VOLUME_CHANGED event registration request sent from the
> > > > > > > > > phone is rejected by the bluez. I can see that on the wireshark snoop
> > > > > > > > > from the device's bluetooth adapter. And on wireshark I see that
> > > > > > > > > AVRCP_EVENT_VOLUME_CHANGED event registration is sent by the phone
> > > > > > > > > before bluez initializes session->supported_events variable (not
> > > > > > > > > really sure about that). I think that this rejection makes the phone
> > > > > > > > > to not send SetAbsoluteVolume commands to the device on volume change.
> > > > > > > >
> > > > > > > > I looked into the same issue earlier this year, see
> > > > > > > > 20200118194841.439036-1-marijns95@xxxxxxxxx [1].  The gist of it is that BlueZ
> > > > > > > > bases supported_events solely on the remote AVRCP controller version, which
> > > > > > > > Android sets to 1.3 when it is a media source [2].  This version is not
> > > > > > > > relevant in your use-case because the Android phone is the AVRCP target while
> > > > > > > > blueZ is the controller.
> > > > > > > >
> > > > > > >
> > > > > > > I didn't tested Your patch but after looking at the code it seems that
> > > > > > > just applying Your patch would solve my problem.
> > > > >
> > > > > It should, even though I don't immediately see how swapping
> > > > > target/controller_init as per your initial email solves the problem.
> > > > >
> > > >
> > > > The sequence of events is important here. The
> > > > session->supported_events must be initialised (which is done in
> > > > target_init) before first AVRCP_REGISTER_NOTIFICATION command from the
> > > > remote side controller. If supported_events is not initialised and
> > > > AVRCP_REGISTER_NOTIFICATION arrives the
> > > > avrcp_handle_register_notification function rejects the event
> > > > registration. And this is what I see in wireshark.
> > >
> > > That's interesting and means we are dealing with two distinct problems
> > > here. No matter what order I flip controller/target_init in
> > > AVRCP_REGISTER_NOTIFICATION is always received after both functions
> > > complete. handle_vendordep_pdu is registered before these
> > > initialization functions making this possible though. I wonder if PDUs
> > > are dropped when the callback is registered later, after init. Perhaps
> > > controller/target_init need to be split in two, a static
> > > initialization part based on the remote profile version followed by
> > > registering this callback and finally functions that send commands to
> > > the remote like avrcp_get_capabilities.
> > >
> > > > And in my case, calling target_init earlier (the is before
> > > > controller_init) solves the problem because supported_events is
> > > > already initialised at the time the AVRCP_REGISTER_NOTIFICATION
> > > > arrives.
> > >
> > > That means your phone reports an AVRCP remote version of at least
> > > 0x104, otherwise supported_events would not contain
> > > AVRCP_EVENT_VOLUME_CHANGED. Can you validate this in wireshark or
> > > DBG("%p version 0x%04x", ...) in the logs? I'm seeing:
> > >
> > >     profiles/audio/avrcp.c:target_init() 0x5614a2cbab70 version 0x0103
> > >
> >
> > Yes, I get this in my logs when connecting from samsung galaxy S7:
> > profiles/audio/avrcp.c:target_init() 0x1103758 version 0x0104
> > profiles/audio/avrcp.c:controller_init() 0x1112c18 version 0x0104
> >
> > > Either way the split Luiz and I mentioned mean one variant of
> > > supported_events (the one relevant for registering
> > > AVRCP_EVENT_VOLUME_CHANGED) is initialized in controller_init.
> > >
> > > > But I think that the problem is more general. There is some gap
> > > > between AVCTP connection establishment and BlueZ readiness to handle
> > > > commands from the remote side. There could be devices that send
> > > > commands during this gap and those devices would not work correctly
> > > > with BlueZ despite the fact that they are consistent with the
> > > > specification (or not ?).
> > > >
> > > > > > > Regarding avrcp version, in android there is developer option to set
> > > > > > > avrcp version. For example my Xiaomi redmi 8 (android 10) reports
> > > > > > > version according to this setting, but samsung galaxy s7 (android 8)
> > > > > > > always report version 1.4 regardless of this setting.
> > > > >
> > > > > I think this is the version used for the AVRCP Remote Target [1]. The
> > > > > version linked above, the one that is causing problems here is that of
> > > > > the AVRCP controller.
> > > > >
> > > > > There have always been problems changing these settings in developer
> > > > > options - sometimes they work, sometimes they don't. The system has
> > > > > been overhauled for Android 11 and is now much more consistent though
> > > > > avrcp still runs through a property. If I remember correctly
> > > > > restarting bluetooth or re-adding a device (in case of SDP caching) is
> > > > > the only solution.
> > > > >
> > > > > > We need to rework a little bit how the controller/target works, this
> > > > > > roles are actually supposed to be interpreted as client/server and
> > > > > > much like GATT they can be used simultaneously, so we need a target
> > > > > > versions and a controller version and independent supported events.
> > > > >
> > > > > Yes, I think that's the change we proposed last time and are proposing
> > > > > now. Unfortunately relevant functions need to know if the local
> > > > > (BlueZ) end is operating as target or controller for that particular
> > > > > operation.
> > > > >
> > > > > > That said if the remote side controller version does not indicate 1.4
> > > > > > or later we obviously can't support absolute volume control as that is
> > > > > > reserved in earlier versions.
> > > > >
> > > > > That depends on the way audio is flowing. When the local (BlueZ) end
> > > > > is the sink (rendering the audio) meaning it takes the role of AVRCP
> > > > > controller (the situation in the mail from Marek), the remote must be
> > > > > the AVRCP target and hence its controller version is irrelevant.
> > > > > Likewise when BlueZ is the audio source (AVRCP target), it should only
> > > > > care about the remote controller profile and version.
> > > > > But that is exactly what you described above: BlueZ needs to attain
> > > > > separation between handling notification registrations (and perhaps
> > > > > other code) as a controller and target separately.
> > > > >
> > > >
> > > > I don't know if I'm interpreting your words correctly but I think that
> > > > You make an assumption that a2dp sink must be avrcp CT and a2dp source
> > > > is avrcp TG.
> > > > In case of the absolute volume control it is not true. For absolute
> > > > volume control to work it is the other way around which makes both
> > > > sides be CT and TG at the same time.
> > >
> > > Quite the contrary, in my previous mail I attempted to explain
> > > multiple times that the CT/TG designation in the spec is used for
> > > initiator and target respectively, not the AVRCP controller and target
> > > profile. Indeed, depending on the transaction either side (controller
> > > or target) can be the initiator (CT). In other words CT and TG are
> > > _not_ abbreviations for the controller and target profile.
> > >
> > > > a2dp sink is avrcp CT for
> > > > controlling playback and a2dp source is avrcp CT for setting the
> > > > volume. It is the a2dp source that is sending
> > > > AVRCP_SET_ABSOLUTE_VOLUME commands.
> > >
> > > Correct, yet the A2DP sink will always take on the AVRCP controller
> > > profile where the phone being the A2DP source takes the AVRCP target
> > > profile.
> > >
> > > > > > > > It was decided in that mail thread to split supported_events in two; one based
> > > > > > > > on the external controller version (when BlueZ operates as target it'll
> > > > > > > > validate incoming notification registrations) and the other based on what BlueZ
> > > > > > > > currently supports as controller.
> > > > > > > >
> > > > > > > > The second check might not be all too relevant and is already covered by the
> > > > > > > > switch-case; perhaps it makes more sense to base this check on the external
> > > > > > > > target version, and again validate whether we expect to receive that particular
> > > > > > > > notification registration?
> > > > > > > >
> > > > > > > > Both checks together implicitly validate what BlueZ supports locally in its
> > > > > > > > role of controller or target, as remote_{target,controller}_supported_events
> > > > > > > > (anticipated names of the new members replacing supported_events) will only be
> > > > > > > > set to events that BlueZ is able to emit.
> > > > > > > >
> > > > > > >
> > > > > > > One thing is not clear for me, what is the purpose of the
> > > > > > > supported_events ?  It is used in two places:
> > > > > > > First is the avrcp_handle_register_notification function. If the
> > > > > > > remote side want to register itself for specific event notification it
> > > > > > > does not matter what version of avrcp that remote side supports. If it
> > > > > > > ask for specific event it clearly support that event.
> > > > >
> > > > > Looking at commit 4ae6135 that introduced this check it was apparently
> > > > > causing crashes without. I can only guess that devices were sending
> > > > > vendor-specific notification requests, assuming implementations are
> > > > > supposed to filter out anything beyond what their reported version
> > > > > supports? Either way input validation is still a sane thing to do.
> > > > >
> > > > > > > Second is in avrcp_handle_get_capabilities in CAP_EVENTS_SUPPORTED
> > > > > > > case. Does it matter if local side reply with events that are not
> > > > > > > supported in the version of avrcp supported by the remote side ?
> > > > >
> > > > > I guess it is sane here to not report capabilities the CT should -
> > > > > given it's version - not know about. I could not find anything in the
> > > > > 1.6.2 spec mandating this though, perhaps Luiz knows.
> > > > >
> > > > > > As I said we need to split the supported events to
> > > > > > ct(client)/tg(server) to avoid interpreting them as the same, it is
> > > > > > very odd that the remote would have different versions for each role
> > > > >
> > > > > Yeah, Android exposes different versions for its AVRCP Remote and
> > > > > AVRCP Remote Target.
> > > > > This is slightly confusing though: we discussed earlier that CT and TG
> > > > > is about the initiator and receiver respectively, with no direct
> > > > > mapping to AVRCP remote and target as either side can be the initiator
> > > > > (sender) of a command. Correct?
> > > > > In this specific case a notification registration will always be
> > > > > initiated by a CT and fulfilled by the TG, no matter whether it is an
> > > > > AVRCP remote or target.
> > > > >
> > > > > > but it looks like this is happening in this case although it is work
> > > > > > confirming if the CT version if in fact 1.3 as well we cannot enable
> > > > > > absolute volume control as that is not supported by that version, what
> > > > > > we can perhaps is to detect if SetAbsoluteVolume control is used then
> > > > > > update the events for the session.
> > > > >
> > > > > Again, in the specific case of this issue it is fine if the CT
> > > > > (initiator, the Android phone, supposed to behave like the target as
> > > > > it is the audio source) reports a controller version of 1.3 as we are
> > > > > only concerned about the target version, which will be the one
> > > > > registering for EVENT_VOLUME_CHANGED notifications from the
> > > > > sink/controller (BlueZ). Android always reports the AVRCP Remote
> > > > > Target as 1.4 or higher based on developer settings [1].
> > > > >
> > > > > > > > Unfortunately my ramblings in that mail shadowed an important question: how to
> > > > > > > > determine in avrcp_handle_register_notification whether BlueZ is running as
> > > > > > > > controller or target?  set_volume in transport.c derives this from
> > > > > > > > transport->source_watch but there seems to be no easy access to the
> > > > > > > > accompanying transport in avrcp_handle_register_notification.  With this
> > > > > > > > question answered I'll be able to update and resubmit the original patch.
> > > > > > > >
> > > > > > > > > To test my theory i changed the session_init_control function in the
> > > > > > > > > profiles/audio/avrcp.c to call first target_init and then
> > > > > > > > > controller_init. This caused  the AVRCP_EVENT_VOLUME_CHANGED event not
> > > > > > > > > been rejected and the volume control from the phone works as expected.
> > > > > > > > >
> > > > > > > > > After reading AVRCP specification I did not find any reason for the CT
> > > > > > > > > on the phone side not to send event registration immediately after the
> > > > > > > > > AVCTP connection establishment. So I believe that bluez should not
> > > > > > > > > reject event registration in this case.
> > > > > > > > >
> > > > > > > > > Best Regards,
> > > > > > > > > Marek Czerski
> > > > > > > >
> > > > > > > > Best regards,
> > > > > > > > Marijn Suijten
> > > > > > > >
> > > > > > > > [1]: https://marc.info/?l=linux-bluetooth&m=157937699001093
> > > > > > > > [2]: https://android.googlesource.com/platform/system/bt/+/android-11.0.0_r4/bta/av/bta_av_main.cc#761
> > > > > > >
> > > > > > >
> > > > > > > Best regards,
> > > > > > > Marek Czerski
> > > > > >
> > > > > >
> > > > > >
> > > > > > --
> > > > > > Luiz Augusto von Dentz
> > > > >
> > > > > P.S.: I hope it is fine to respond to two emails in one, seems like
> > > > > that will get confusing real quick if depth increases.
> > > > >
> > > > > - Marijn
> > > > >
> > > > > [1]: https://android.googlesource.com/platform/system/bt/+/android-11.0.0_r4/bta/av/bta_av_main.cc#612
> > > >
> > > > Best regards,
> > > > Marek
> > >
> > > - Marijn
> >
> >
> >
> > --
> > mgr inż. Marek Czerski
> > +48 696 842 686
>
>
>
> --
> mgr inż. Marek Czerski
> +48 696 842 686

- Marijn

[1]: https://android.googlesource.com/platform/system/bt/+/master/device/include/interop_database.h




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux