audio_open_output_stream always tries to open 1st registered endpoint
based on assumption that there is only one endpoint registered anyway
(due to support for only one codec). With more endpoints available in
future we need to be able to retrieve endpoint id which is connected
and use it for streaming.
This patch adds special case for id=0 in open_stream IPC to return 1st
opened endpoint on BlueZ side which is enough for now since only one
headset can be connected at any time (i.e. we should not have more
than 1 endpoint opened).
When matching remote SEP to local SEP we do not match vendor codecs
properly, i.e. neither vendor ID not codec ID are checked, which may
cause wrong endpoint to be selected in case there are more that one
endpoints using vendor codec on remote.
This patch fixes this by assinging vendor codec indentification to
local SEP after it's registered and uses this information when matching
SEPs.
Connection state is not changed for incoming connection, i.e. during
discovery device is still in disconnected state and in case connection
fails for some reason, device won't be removed due to triggered state
change disconnected->disconnected which is silently ignored.
This patch fixes this problem by changing device state to connecting
immediately after signalling channel is connected. This allows device
to be removed properly in case something fails and is also consistent
with behaviour of Bluedroid.
In addition there's new flag added to device which stores information
whether we're initiator of connection. This is required because before
fix this property was decided based on HAL state which we can't now
use since it will be always connecting for both incoming and outgoing
connections.
This header contains IPC specific structures and code not related to
BT and audio HAL protocols. This allows to fully decouple IPC from
HAL messages.
This is first step to make HAL part of IPC unit-testable and reusable
between BT HAL and audio HAL.
Unregistering a SEP can trigger abort_cfm callback if some device is
connected thus we should free setups list after all endpoints are
unregistered to avoid error in abort_cfm due to non-existing setup.
In case audio IPC is suddenly disconnected (most likely due to crash of
mediaserver process) we should disconnect headset since it is no longer
associated with valid setup and cannot be used properly.
Invalid read of size 8
at 0x30EE465A78: g_slice_free_chain_with_offset (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x418209: bt_a2dp_unregister (a2dp.c:1576)
by 0x4039E6: main (main.c:347)
Address 0x4f2d248 is 8 bytes inside a block of size 16 free'd
at 0x4A07577: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x30EE44EF7E: g_free (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x30EE4655CA: g_slice_free1 (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x30EE465F0C: g_slist_remove (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x41645F: a2dp_device_free (a2dp.c:174)
by 0x30EE466477: g_slist_foreach (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x30EE46649A: g_slist_free_full (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x418209: bt_a2dp_unregister (a2dp.c:1576)
by 0x4039E6: main (main.c:347)
Remove setups when a2dp device is removed. This fix following:
Invalid read of size 4
at 0x115E32: bt_stream_close (a2dp.c:1352)
by 0x111DFB: ipc_handle_msg (ipc.c:95)
by 0x11234B: audio_watch_cb (audio-ipc.c:67)
by 0x48BD9C7: ??? (in /system/lib/libglib.so)
Address 0x4a590f4 is 12 bytes inside a block of size 20 free'd
at 0x4897E6C: free (in
/system/lib/valgrind/vgpreload_memcheck-arm-linux.so)
by 0x48C5E2B: g_free (in /system/lib/libglib.so)
Invalid read of size 4
at 0x113638: avdtp_close (avdtp.c:3201)
by 0x115E39: bt_stream_close (a2dp.c:1352)
by 0x111DFB: ipc_handle_msg (ipc.c:95)
by 0x11234B: audio_watch_cb (audio-ipc.c:67)
by 0x48BD9C7: ??? (in /system/lib/libglib.so)
Address 0x4a594a4 is 28 bytes inside a block of size 1,100 free'd
at 0x4897E6C: free (in
/system/lib/valgrind/vgpreload_memcheck-arm-linux.so)
by 0x48C5E2B: g_free (in /system/lib/libglib.so)
In case stream is started from remote we'll receive Resume Stream IPC
when audio is already considered as started (i.e. on first write from
AudioFlinger). In such case we should not try to send AVDTP_START since
this will fail but just reply success over IPC instead.
The endpoint is unregistered but it was still accessible via endpoints
list causing the following trace when audio HAL is closed:
Invalid read of size 8
at 0x414A49: unregister_endpoint (a2dp.c:114)
by 0x3862466477: g_slist_foreach (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x386246649A: g_slist_free_full (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x414985: audio_disconnected (a2dp.c:1446)
by 0x40FD5C: audio_watch_cb (audio-ipc.c:79)
by 0x38624492A5: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x3862449627: ??? (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x3862449A39: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x4034D5: main (main.c:449)
Address 0x4cd5e68 is 8 bytes inside a block of size 32 free'd
at 0x4A07577: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x386244EF7E: g_free (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x4159FD: bt_audio_close (a2dp.c:1296)
by 0x40F629: ipc_handle_msg (ipc.c:95)
by 0x40FD9F: audio_watch_cb (audio-ipc.c:67)
by 0x38624492A5: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x3862449627: ??? (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x3862449A39: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3800.2)
by 0x4034D5: main (main.c:449)
MTU value for transport channel is sent in Open Stream response, which
is required to calculate number of frames which can be packed into
single media packet.
This is to avoid including GPLv2 licensed headers in Audio HAL
implementation.
For SBC bitpool range may not strictly match with presets so it needs to
be adjusted to fit within remote capabilities otherwise the remote device
may reject the configuration.
This changes the connected state to be only sent once a transport is
open, before this was done right after the signalling was connected but
this reflect in the audio HAL side attempting to open a stream while
with possible no transport available.
audio_ipc_send_rsp_full() does not free buffer passed as parameter
thus it should be freed by caller.
This fixes following Valgrind report:
==1238== 5 bytes in 1 blocks are definitely lost in loss record 22 of 54
==1238== at 0x4896DC8: calloc (in /system/lib/valgrind/vgpreload_memcheck-arm-linux.so)
==1238== by 0x48C5DB7: g_malloc0 (gmem.c:189)
==1238== by 0x1150EF: bt_stream_open (a2dp.c:1177)
==1238== by 0x1116A7: ipc_handle_msg (ipc.c:95)
==1238== by 0x111C11: audio_watch_cb (audio-ipc.c:66)
==1238== by 0x48BD9C7: g_io_unix_dispatch (giounix.c:166)
==1238== by 0x48C2CCB: g_main_context_dispatch (gmain.c:2539)
==1238== by 0x48C2ED9: g_main_context_iterate.isra.19 (gmain.c:3146)
==1238== by 0x48C3167: g_main_loop_run (gmain.c:3340)
==1238== by 0x10B207: main (main.c:436)
avdtp_service_cap_new() makes own copy of data stored in "codec" thus
it should be freed by caller.
This fixes following Valgrind report:
==1238== 6 bytes in 1 blocks are definitely lost in loss record 27 of 54
==1238== at 0x4896DC8: calloc (in /system/lib/valgrind/vgpreload_memcheck-arm-linux.so)
==1238== by 0x48C5DB7: g_malloc0 (gmem.c:189)
==1238== by 0x115B4B: discover_cb (a2dp.c:303)
==1238== by 0x111DE7: finalize_discovery (avdtp.c:933)
==1238== by 0x114441: session_cb (avdtp.c:2556)
==1238== by 0x48BD9C7: g_io_unix_dispatch (giounix.c:166)
==1238== by 0x48C2CCB: g_main_context_dispatch (gmain.c:2539)
==1238== by 0x48C2ED9: g_main_context_iterate.isra.19 (gmain.c:3146)
==1238== by 0x48C3167: g_main_loop_run (gmain.c:3340)
==1238== by 0x10B207: main (main.c:436)
In case SEP was opened from local side, corresponding a2dp_setup
structure has just reference to a2dp_preset which is stored on presets
list. As a result, when closing SEP such preset will be freed leaving
dangling pointer on presets list.
struct audio_rsp_open_stream has only zero-length array member thus its
size equals to 0. We need to explicitly specify size of array element
type here.